Dieser Artikel enthält eine Sammlung häufig gestellter Fragen (FAQ) zu Microsoft DirectX.
Allgemeine Probleme bei der DirectX-Entwicklung
Sollten Sich Spieleentwickler wirklich um die Unterstützung von x64-Editionen sorgen?
Absolut. Die x64-Technologie ist auf dem Markt weit verbreitet. Der Großteil der neuen CPUs, die in den letzten Jahren verkauft wurden, und fast alle Prozessorlinien in der Entwicklung von AMD und Intel, sind x64-fähig. Windows XP Professional x64 Edition hat die Betriebssystem-Aktivierungstechnologie für x64 eingeführt, die im April 2005 veröffentlicht wurde. Da x64-Editionen eine neue Generation nativer 64-Bit-Treiber erfordern, war diese erste Version auf die OEM-Verteilung beschränkt.
Mit Windows Vista können Kunden entweder 32-Bit- oder 64-Bit-Editionen auswählen, wenn Sie Windows-basierte Computer kaufen, und Lizenzen für Windows Vista gelten sowohl für 32-Bit- als auch für 64-Bit-Editionen des Betriebssystems. Darüber hinaus sind viele 64-Bit-Treiber in der Box verfügbar, und Gerätehersteller müssen sowohl 32-Bit- als auch 64-Bit-native Treiber als Teil des Windows-Zertifizierungsprogramms bereitstellen.
All diese Faktoren erhöhen die Bereitstellungen von 64-Bit-Editionen von Windows erheblich. Da neue Computer mit mehr als 2 GB physischem RAM auf den Markt kommen, verringert sich der Anreiz, ein 32-Bit-Betriebssystem zu verwenden, erheblich zugunsten von 64-Bit-Editionen. Sechzig-Vier-Bit-Technologie unterstützt vollständig nativen 32-Bit-Code, obwohl 64-Bit-native Implementierungen erforderlich sind, um den neuen 64-Bit-Speicherplatz vollständig zu nutzen. Jede 32-Bit-Anwendung sollte 64-Bit-Kompatibilität als Mindestauslieferungsanforderung aufweisen, und das Erfüllen dieser Anforderung ist eine grundlegende Anforderung für die Windows Vista-Kompatibilität. Inkompatibilitäten ergeben sich in der Regel aus der Verwendung von 16-Bit-Code, der für das Windows 3.1-Betriebssystem entwickelt wurde, oder aus der Installation von Treibern, die nicht in 32-Bit- und 64-Bit-nativen Formen bereitgestellt werden.
Weitere Informationen zur 64-Bit-Technologie finden Sie unter 64-Bit-Programmierung für Spieleentwickler.
Sollten Spieleentwickler weiterhin Spiele für Windows 95, Windows 98 oder Windows ME veröffentlichen?
Aus zwei Gründen ist das nicht mehr der Fall: Leistung und Funktionsumfang.
Wenn die für Ihr Spiel erforderliche minimale CPU-Geschwindigkeit 1,2 GHz oder höher ist (was für High-Performance-Titel immer häufiger der Fall ist), werden die meisten qualifizierten Computer Windows XP ausführen. Zum Zeitpunkt, zu dem Computer mit CPU-Geschwindigkeiten über 1,2 GHz verkauft wurden, wurde Windows XP als Standardbetriebssystem von fast allen Herstellern installiert. Dies bedeutet, dass es viele Features in Windows XP gibt, die Entwickler von heutigen Spielen nutzen sollten, darunter:
- Verbessertes Multitasking – was zu einer besseren, reibungsloseren Erfahrung für Video, Audio und Spiele führt.
- Stabileres Videotreibermodell – das einfacheres Debuggen, ein reibungsloseres Spielerlebnis und eine bessere Leistung ermöglicht.
- Einfachere Konfiguration für Netzwerke – was den Zugriff auf Multi-Player-Spiele vereinfacht.
- Unterstützung für DMA-Übertragungen standardmäßig von Festplatten – was zu reibungsloseren, schneller ladenden Anwendungen führt.
- Windows-Fehlerberichterstattung – was zu einem stabileren Betriebssystem, Treibern und Anwendungen führt.
- Unicode-Unterstützung – was Lokalisierungsprobleme erheblich vereinfacht.
- Bessere Sicherheit und Stabilität – was zu besseren Verbrauchererfahrungen führt.
- Bessere Unterstützung für moderne Hardware – von denen der Großteil keine Windows 98-Treiber mehr verwendet.
- Verbesserte Speicherverwaltung – was zu einer besseren Stabilität und Sicherheit führt.
- Verbessertes NTFS-Dateisystem – was widerstandsfähiger gegen Ausfälle ist und eine bessere Leistung mit Sicherheitsfeatures bietet.
Sollten Spieleentwickler weiterhin Spiele für Windows 2000 veröffentlichen?
Jetzt nicht mehr. Zusätzlich zu den in Sollten Spieleentwickler weiterhin Spiele für Windows 95, Windows 98 oder Windows ME veröffentlichen? aufgeführten Gründen verfügt Windows 2000 nicht über diese Features:
- Windows XP unterstützt fortschrittliche Prozessorfunktionen wie Hyperthreading, Multi-Core und x64.
- Windows XP unterstützt parallele Komponenten, was Anwendungsversionskonflikte erheblich reduziert.
- Windows XP unterstützt Nichtausführungs-Speicherschutz, was dazu beiträgt, schädliche Programme zu verhindern und das Debuggen unterstützen kann.
- Windows XP bietet verbesserte Unterstützung für fortschrittliche AGP- und PCI Express-basierte Grafikkarten.
- Windows XP unterstützt schnelles Wechseln von Benutzern, Remotedesktop und Remoteunterstützung, wodurch die Produktsupportkosten gesenkt werden können.
- Leistungstools wie PIX (im DirectX-Entwickler-SDK) unterstützen Windows 2000 nicht mehr.
Kurz gesagt: Windows 2000 wurde nie als Verbraucherbetriebssystem entwickelt oder vermarktet.
Welche Unterschiede bestehen zwischen den verschiedenen Editionen von Windows Vista? Wie wirken sie sich auf meine DirectX-Anwendung aus?
Die Windows Vista-Familie umfasst fünf Editionen:
- Windows Vista Home Basic
- Windows Vista Home Premium
- Windows Vista Business
- Windows Vista Enterprise
- Windows Vista Ultimate
Home Basic und Home Premium sind verbraucherorientierte Versionen mit Features wie Family Safety (früher als Jugendschutz bezeichnet), und Home Premium beinhaltet Media Center. Business und Enterprise sind Unternehmenseditionen mit Features wie Domänenbeitritt und Remotedesktop-/Terminaldiensten. Die Ultimate-Edition kombiniert alle Features sowohl der Verbraucher- als auch der Unternehmensedition in einer Version. Alle Editionen sind sowohl in 32-Bit-Editionen (x86) als auch in 64-Bit-Editionen (x64) verfügbar, und Benutzer können denselben Produktbezeichner für beide Plattformen verwenden.
Die Technologie, die den verschiedenen Editionen zugrunde liegt, ist identisch, und sie verfügen alle über dieselbe Version der DirectX-Runtime und anderer Komponenten. Die Editionen weisen jedoch einige geringfügige Unterschiede im Hinblick auf Spiele auf:
- Der Spiele-Explorer ist in allen Editionen vorhanden, die Verknüpfung „Spiele“ im Startmenü befindet sich jedoch nur in Home Basic, Home Premium und Ultimate. Der Spiele-Explorer befindet sich weiterhin in allen Editionen (durch Klicken auf „Start“, zeigen auf „Alle Programme“ und dann auf „Spiele“) und die IGameExplorer-Schnittstellenfunktionen aller Editionen.
- Die in Windows enthaltenen Spiele sind in Business und Enterprise nicht standardmäßig verfügbar, können aber vom Administrator aktiviert werden.
- Family Safety- und Spielbewertungen werden nicht angezeigt oder haben keinen Einfluss auf das Verhalten von Business oder Enterprise, und sie sind auf Ultimate deaktiviert, wenn einer Domäne beigetreten wird.
Die Einstellungen für die Benutzerkontensteuerung weisen die gleichen Standardwerte für alle Editionen auf, können jedoch von Gruppenrichtlinieneinstellungen für die Domäne auf Business, Enterprise und Ultimate außer Kraft gesetzt werden. Beispielsweise kann die Richtlinieneinstellung „Benutzerkontensteuerung: Verhalten“ der Eingabeaufforderung für erhöhte Rechte für Standardbenutzer in vielen Geschäftseinstellungen zur Verbesserung der Sicherheit möglicherweise auf „Anforderungen für erhöhte Rechte automatisch ablehnen“ festgelegt werden, und viele Benutzer in diesen Umgebungen werden immer als Standardbenutzer ausgeführt, ohne dass sie auch nur die Möglichkeit haben, sich für die Ausführung als Administrator zu entscheiden. Jedes Programm (z. B. ein Installationsprogramm), das Administratorrechte erfordert, entweder aufgrund der Legacy-Setuperkennung oder eines Manifests, das die angeforderte Ausführungsebene als „requireAdministrator“ angibt, kann in solchen Situationen nie gestartet werden. Andere Richtlinieneinstellungen, z. B. „Benutzerkontensteuerung: Nur ausführbare Dateien heraufstufen, die signiert und überprüft sind“, können auch verhindern, dass ihr Installationsprogramm funktioniert, wenn Sie ihre ausführbare Datei nicht mit Authenticode signieren.
Diese Arten von Richtlinienänderungen können auf jede Edition von Windows Vista angewendet werden, sind aber wahrscheinlicher auf Computern, die einer Domäne beigetreten sind.
Was sind die Unterschiede zwischen den verschiedenen Editionen von Windows 7? Wie wirken sie sich auf meine DirectX-Anwendung aus?
Die Mehrzahl der Windows 7-Benutzer verfügt wahrscheinlich über eine von zwei Editionen: Windows 7 Home Premium für private Benutzer oder Windows 7 Professional für Geschäftsbenutzer und Entwickler. Für große Unternehmen gibt es die volumenlizenzierte Windows 7 Enterprise-Edition, die alle Windows 7-Features enthält; Windows 7 Ultimate ist das Einzelhandelsäquivalent dieser Edition.
Windows 7 Starter Edition ist weltweit für OEMs verfügbar, und es wird erwartet, dass sie primär mit Netbooks, also Notebook-Computern mit extrem niedriger Stromaufnahme, bereitgestellt werden. Windows 7 Home Basic ist nur in Schwellenländern verfügbar.
Beachten Sie, dass alle Editionen von Windows 7 (außer Starter Edition) sowohl für 32-Bit-Versionen (x86) als auch für 64-Bit-Versionen (x64) verfügbar sind, und alle Einzelhandelspakete von Windows 7 enthalten Medien für beide Versionen. Wie bei Windows Vista können Benutzer denselben Einzelhandelsproduktbezeichner auf beiden Plattformen verwenden.
Die zugrunde liegende Technologie in den verschiedenen Editionen ist identisch, und alle Editionen haben dieselbe Version der DirectX-Runtime und anderer Komponenten. Sie haben einige Unterschiede in Bezug auf Gaming-Features:
- Der Spiele-Explorer ist in allen Editionen vorhanden, die Verknüpfung „Spiele“ im Startmenü ist jedoch in Windows 7 Professional und Enterprise standardmäßig ausgeblendet. Der Spiele-Explorer befindet sich dennoch im Startmenü (indem Sie auf „Alle Programme“ klicken und dann auf „Spiele“ doppelklicken), und die direkte Verknüpfung „Spiele“ kann vom Benutzer aktiviert werden.
- Die in Windows enthaltenen Spiele sind unter Windows 7 Professional und Enterprise standardmäßig nicht verfügbar, können aber vom Administrator aktiviert werden.
- Family Safety und Spielbewertungen sind für alle Editionen verfügbar, sind jedoch unter Windows 7 Professional, Enterprise und Ultimate deaktiviert, wenn das Betriebssystem einer Domäne beitritt. Wie bei Windows Vista Ultimate kann dieses Feature auf Computern, die einer Domäne beigetreten sind, wieder aktiviert werden.
Die Einstellungen für die Benutzerkontensteuerung (User Account Control, UAC) können von den Gruppenrichtlinieneinstellungen in Windows 7 Professional-, Enterprise- und Ultimate-Editionen wie Windows Vista beeinflusst werden. Weitere Informationen finden Sie unter Was sind die Unterschiede zwischen den verschiedenen Editionen von Windows Vista? Wie wirken sie sich auf meine DirectX-Anwendung aus?
Wird DirectX 10 für Windows XP verfügbar sein?
Nein. Windows Vista, das DirectX 10 enthält, beinhaltet eine aktualisierte DirectX-Runtime basierend auf der Runtime in Windows XP SP2 (DirectX 9.0c) mit Änderungen, um mit dem neuen Windows-Bildschirmtreibermodell (Windows Display Driver Model, WDDM) und dem neuen Audiotreiberstapel zu funktionieren, sowie mit anderen Aktualisierungen im Betriebssystem. Zusätzlich zu Direct3D 9 unterstützt Windows Vista zwei neue Schnittstellen, wenn die richtige Videohardware und Treiber vorhanden sind: Direct3D9Ex und Direct3D10.
Da diese neuen Schnittstellen auf die WDDM-Technologie angewiesen sind, werden sie nie in früheren Versionen von Windows zur Verfügung stehen. Alle anderen Änderungen, die an DirectX-Technologien für Windows Vista vorgenommen wurden, sind ebenfalls spezifisch für die neue Version von Windows. Der Name DirectX 10 ist insofern irreführend, als viele Technologien im DirectX-SDK (XACT, XINPUT, D3DX) nicht von dieser Versionsnummer eingeschlossen sind. Daher hat die Bezugnahme auf die Versionsnummer der DirectX-Runtime insgesamt einen Großteil ihrer Bedeutung verloren, sogar für 9,0c. Das DirectX Diagnostic Tool (DXdiag.exe) unter Windows Vista meldet DirectX 10, aber dies bezieht sich wirklich nur auf Direct3D 10.
Wird DirectX 11 für Windows Vista oder Windows XP verfügbar sein?
DirectX 11 ist in Windows 7 integriert und ist als Update für Windows Vista verfügbar (siehe https://go.microsoft.com/fwlink/p/?linkid=160189). Dazu gehören die Direct3D 11-API, DirectX Graphics Infrastructure (DXGI) 1.1, 10Level9-Featureebenen, Windows Advanced Rasterization Platform (WARP) 10-Softwarerenderinggerät, Direct2D, DirectWrite und ein Update auf die Direct3D 10.1-API zur Unterstützung von 10Level9 und WARP 10.
Aus denselben Gründen, die in der vorstehenden Frage angegeben sind (Wird DirectX 10 für Windows XP verfügbar sein? ), sind Direct3D 11 und zugehörige APIs unter Windows XP nicht verfügbar.
Was ist mit DirectShow passiert? Ich kann es nicht im DirectX-SDK finden.
DirectShow wurde im April 2005 aus dem DirectX-SDK entfernt. Sie können die Header, Bibliotheken, Tools und Beispiele für DirectShow im Windows Software Development Kit (früher als Platform SDK bezeichnet) abrufen. DirectSetup im DirectX-SDK unterstützt weiterhin die Umverteilung der Systemkomponenten von DirectShow, und die neuesten Komponenten werden bereits auf den folgenden Betriebssystemen installiert: Microsoft Windows XP Service Pack 2, Windows XP Professional x64 Edition, Windows Server 2003 Service Pack 1 und Windows Vista.
Welche Änderungen wurden an der DirectX-Runtime für Windows Vista vorgenommen?
Die wichtigsten Änderungen wurden vorgenommen, um den neuen WDDM zu unterstützen. Ausführliche Informationen zum neuen Treibermodell, zu den Auswirkungen auf Direct3D 9 und zu den beiden neuen Grafikschnittstellen Direct3D 9Ex und Direct3D 10 finden Sie unter Grafik-APIs in Windows. Neue Grafik-APIs für Windows 7 – Direct3D 11, Direct2D, DirectWrite, DXGI 1.1 und ein aktualisiertes Direct3D 10.1 – sind als Update für Windows Vista verfügbar (siehe https://go.microsoft.com/fwlink/p/?linkid=160189).
Windows Vista Service Pack 1 enthält eine aktualisierte Version der DirectX-Runtime. Dieses Update erweitert die Unterstützung von Windows Vista um Direct3D 10.1, wodurch neue optionale Hardwarefeatures verfügbar sind. (Sämtliche Hardware, die Direct3D 10.1 unterstützt, unterstützt auch alle Features von Direct3D 10 vollständig.)
DirectSound wurde aktualisiert, um die Funktionen des neuen Windows Vista-Audiotreiberstapels verfügbar zu machen, der Multikanalsoftwarepuffer unterstützt. Die Direct3D Retained Mode-API wurde vollständig aus Windows Vista entfernt. DirectPlay Voice wurde ebenfalls entfernt, sowie die NAT-Hilfsfunktion von DirectPlay und die Action-Mapper-UI von DirectInput. Die Unterstützung für die DirectX 7- und DirectX 8-Schnittstellen für Visual Basic 6.0 ist unter Windows Vista nicht verfügbar.
Welche Änderungen wurden an der DirectX-Runtime für Windows 7 vorgenommen?
Windows 7 enthält alle in Windows Vista enthaltenen DirectX-Runtime-Komponenten und fügt Direct3D 11, DXGI 1.1, 10Level9-Featureebenen, das WARP10-Softwaregerät, Direct2D, DirectWrite und ein Update auf Direct3D 10.1 zur Unterstützung von 10Level9 und WARP10 hinzu. Weitere Informationen finden Sie unter Grafik-APIs in Windows.
Alle anderen Komponenten sind identisch mit Windows Vista, mit der Ergänzung der nativen 64-Bit-Unterstützung (x64) für die Kern-DirectMusic-API im Zusammenhang mit MIDI mit Zeitstempel. Die Leistungsebene von DirectMusic bleibt veraltet, und sie ist nur für 32-Bit-Anwendungen unter Windows 7 zur Anwendungskompatibilität verfügbar. Beachten Sie, dass die native 64-Bit-Unterstützung von DirectMusic unter Windows Vista nicht verfügbar ist.
Ich glaube, ich habe einen Treiberfehler gefunden. Was soll ich tun?
Stellen Sie zunächst sicher, dass Sie die Ergebnisse mit dem Referenzraster überprüft haben. Überprüfen Sie dann die Ergebnisse mit der neuesten WHQL-zertifizierten Version des IHVs-Treibers. Sie können den WHQL-Status programmgesteuert mithilfe der GetAdapterIdentifier()-Methode auf der IDirect3D9-Schnittstelle überprüfen, die das D3DENUM_WHQL_LEVEL-Flag übergibt.
Warum erhalte ich so viele Fehlermeldungen, wenn ich versuche, die Beispiele zu kompilieren?
Wahrscheinlich ist Ihr Includepfad nicht richtig eingestellt. Viele Compiler, einschließlich Microsoft Visual C++, enthalten eine frühere Version des SDK. Wenn Ihr Includepfad also zuerst die Standardcompiler-Include-Verzeichnisse durchsucht, erhalten Sie falsche Versionen der Headerdateien. Um dieses Problem zu beheben, stellen Sie sicher, dass der Includepfad und Bibliothekspfade so festgelegt sind, dass zuerst die Microsoft DirectX-Include- und Bibliothekspfade durchsucht werden. Siehe auch die Datei dxreadme.txt im SDK. Wenn Sie das DirectX-SDK installieren und Visual C++ verwenden, kann das Installationsprogramm optional die Includepfade für Sie einrichten.
Ich erhalte Linkerfehler zu mehreren oder fehlenden Symbolen für global eindeutige Bezeichner (GUIDs). Was soll ich tun?
Die verschiedenen GUIDs, die Sie verwenden, sollten einmal und nur einmal definiert werden. Die Definition für die GUID wird eingefügt, wenn Sie das INITGUID-Symbol definieren (#define), bevor Sie die DirectX-Headerdateien einschließen. Daher sollten Sie sicherstellen, dass dies nur für eine einzige Kompilierungseinheit erfolgt. Eine Alternative zu dieser Methode ist das Verknüpfen mit der dxguid.lib-Bibliothek, die Definitionen für alle DirectX-GUIDs enthält. Wenn Sie diese Methode (empfohlen) verwenden, sollten Sie niemals das INITGUID-Symbol definieren (#define).
Kann ich einen Zeiger auf eine DirectX-Schnittstelle in eine niedrigere Versionsnummer umwandeln?
Nein. DirectX-Schnittstellen sind COM-Schnittstellen. Dies bedeutet, dass es keine Anforderung für höhere nummerierte Schnittstellen gibt, die von entsprechenden niedrigeren nummerierten Schnittstellen abgeleitet werden müssen. Daher besteht die einzige sichere Methode zum Abrufen einer anderen Schnittstelle zu einem DirectX-Objekt darin, die QueryInterface-Methode der Schnittstelle zu verwenden. Diese Methode ist Teil der IUnknown-Standardschnittstelle, von der alle COM-Schnittstellen abgeleitet werden müssen.
Kann ich die Verwendung von DirectX 9-Komponenten und DirectX 8- oder früheren Komponenten innerhalb derselben Anwendung kombinieren?
Sie können verschiedene Komponenten unterschiedlicher Version beliebig mischen; Sie können beispielsweise DirectInput 8 mit Direct3D 9 in derselben Anwendung verwenden. In der Regel können Sie jedoch nicht verschiedene Versionen derselben Komponente innerhalb derselben Anwendung kombinieren; beispielsweise können Sie DirectDraw 7 nicht mit Direct3D 9 kombinieren (da diese effektiv die gleiche Komponente sind, da DirectDraw ab DirectX 8 in Direct3D subsumiert wurde). Es gibt jedoch Ausnahmen, z. B. die Verwendung von Direct3D 9 und Direct3D 10 zusammen in derselben Anwendung, die zulässig ist.
Kann ich die Verwendung von Direct3D 9 und Direct3D 10 innerhalb derselben Anwendung kombinieren?
Ja, Sie können diese Versionen von Direct3D zusammen in derselben Anwendung verwenden.
Was bedeuten die Rückgabewerte aus den Release- oder AddRef-Methoden?
Der Rückgabewert ist die aktuelle Referenzanzahl des Objekts. Die COM-Spezifikation gibt jedoch an, dass Sie sich nicht darauf verlassen sollten und der Wert in der Regel nur für Debuggingzwecke verfügbar ist. Die beobachteten Werte können unerwartet sein, da möglicherweise verschiedene andere Systemobjekte Verweise auf die von Ihnen erstellten DirectX-Objekte enthalten. Aus diesem Grund sollten Sie keinen Code schreiben, der „Release“ wiederholt aufruft, bis die Referenzanzahl null ist, da das Objekt dann freigegeben werden kann, auch wenn eine andere Komponente weiterhin darauf verweist.
Spielt es eine Rolle, in welcher Reihenfolge ich DirectX-Schnittstellen freigebe?
Es sollte nicht wichtig sein, da COM-Schnittstellen über Verweiszählung verfügen. Es gibt jedoch einige bekannte Fehler im Zusammenhang mit der Freigabereihenfolge von Schnittstellen in einigen Versionen von DirectX. Zur Sicherheit wird empfohlen, Schnittstellen nach Möglichkeit in umgekehrter Erstellungsreihenfolge freizugeben.
Was ist ein intelligenter Zeiger und sollte ich ihn verwenden?
Ein intelligenter Zeiger ist eine C++-Vorlagenklasse zum Kapseln der Zeigerfunktionalität. Insbesondere gibt es standardmäßige intelligente Zeigerklassen, die zum Kapseln von COM-Schnittstellenzeigern entwickelt wurden. Diese Zeiger führen automatisch QueryInterface anstelle einer Umwandlung aus, und sie handhaben AddRef und Release für Sie. Ob Sie sie verwenden sollten, ist weitgehend eine Sache des Geschmacks. Wenn Ihr Code vielfaches Kopieren von Schnittstellenzeigern enthält, mit mehreren AddRefs und Releases, können intelligente Zeiger ihren Code wahrscheinlich übersichtlicher und weniger fehleranfällig machen. Andernfalls kommen Sie ohne sie aus. Visual C++ enthält einen standardmäßigen intelligenten Microsoft COM-Zeiger, der in der Headerdatei „comdef.h“ definiert ist (suchen Sie in der Hilfe nach com_ptr_t).
Ich habe Probleme beim Debuggen meiner DirectX-Anwendung. Irgendwelche Tipps?
Das häufigste Problem beim Debuggen von DirectX-Anwendungen ist der Versuch, zu debuggen, während eine DirectDraw-Oberfläche gesperrt ist. Diese Situation kann zu einer „Win16-Sperre“ auf Microsoft Windows 9x-Systemen führen, wodurch das Zeichnen des Debuggerfensters verhindert wird. Die Angabe des D3DLOCK_NOSYSLOCK-Flags beim Sperren der Oberfläche kann dies in der Regel vermeiden. Windows 2000 leidet nicht unter diesem Problem. Beim Entwickeln einer Anwendung ist es nützlich, mit der Debugversion der DirectX-Runtime (ausgewählt beim Installieren des SDK) auszuführen, die einige Parameterüberprüfungen ausführt und nützliche Meldungen an die Debuggerausgabe ausgibt.
Was ist die richtige Methode zum Überprüfen von Rückgabecodes?
Verwenden Sie die Makros SUCCEEDED und FAILED. DirectX-Methoden können mehrere Erfolgs- und Fehlercodes zurückgeben, weshalb ein einfacher:
== D3D_OK
oder ein ähnlicher Test nicht immer ausreicht.
Wie deaktiviere ich ALT+TAB und andere Aufgabenwechsel?
Das tun Sie nicht! Spiele müssen in der Lage sein, Aufgabenwechsel elegant zu handhaben, denn es gibt viele Gründe dafür: ALT+TAB, Remote-Desktop-Verbindungen, schneller Benutzerwechsel, Nutzungsbeschränkungen durch die Kindersicherung und viele andere Ereignisse.
Gleichzeitig drücken zwei häufige Quellen für versehentliche Aufgabenwechsel mit Tastatursteuerungsschemas das Drücken der Windows-Logo-Taste und das Aktivieren der Barrierefreiheitsfunktion StickyKeys mit der UMSCHALT-Taste. Informationen zum Beheben dieser Fälle durch Deaktivieren der Funktionalität finden Sie in den in Deaktivieren von Tastenkombinationen in Spielen beschriebenen Techniken.
Gibt es ein empfohlenes Buch, in dem COM erklärt wird?
Inside COM von Dale Rogerson, veröffentlicht von Microsoft Press, ist eine ausgezeichnete Einführung in COM. Für einen detaillierteren Blick auf COM ist das Buch Essential COM von Don Box, veröffentlicht von Longman, ebenfalls dringend zu empfehlen.
Was ist verwalteter Code?
Verwalteter Code ist Code, dessen Ausführung von der .NET Framework Common Language Runtime (CLR) verwaltet wird. Er bezieht sich auf einen Vertrag der Zusammenarbeit zwischen dem nativem Ausführen von Code und der Runtime. Dieser Vertrag gibt an, dass die Runtime an jedem Ausführungspunkt eine ausführende CPU beenden und Informationen abrufen kann, die für die aktuelle CPU-Anweisungsadresse spezifisch sind. Informationen, die abfragefähig sein müssen, beziehen sich im Allgemeinen auf den Runtime-Zustand, z. B. registrieren oder Speicherinhalte stapeln.
Bevor der Code ausgeführt wird, wird die IL in nativen ausführbaren Code kompiliert. Und da diese Kompilierung durch die verwaltete Ausführungsumgebung (oder, richtiger, durch einen laufzeitfähigen Compiler erfolgt, der weiß, wie man auf die verwaltete Ausführungsumgebung abzielt), kann die verwaltete Ausführungsumgebung Garantien dafür machen, was der Code tun wird. Sie kann Traps und geeignete Garbage Collection-Hooks, Ausnahmebehandlung, Typsicherheit, Arraygrenzen und Indexüberprüfung einfügen usw. Ein solcher Compiler stellt z. B. sicher, dass Stapelrahmen und alles genau richtig ausgelegt werden, damit der Garbage Collector im Hintergrund auf einem separaten Thread ausgeführt werden kann, der ständig den aktiven Aufrufstapel durchläuft, alle Stämme findet und alle Liveobjekte verfolgt. Darüber hinaus, da die IL über einen Begriff der Typsicherheit verfügt, wird die Ausführungs-Engine die Garantie der Typsicherheit beibehalten, wodurch eine ganze Klasse von Programmierfehlern beseitigt wird, die häufig zu Sicherheitslöchern führen.
Im Gegensatz dazu die nicht verwaltete Welt: Nicht verwaltete ausführbare Dateien sind im Grunde ein Binärimage-x86-Code, der in den Speicher geladen wird. Der Programmzähler wird dort platziert, und das ist das letzte, was das Betriebssystem weiß. Es gibt Schutzfunktionen rund um die Speicherverwaltung und Port-E/A usw., aber das System weiß nicht, was die Anwendung tut. Daher kann es keine Garantien dafür geben, was geschieht, wenn die Anwendung ausgeführt wird.
Welche Bücher gibt es über allgemeine Windows-Programmierung?
Viele. Die beiden, die dringend empfohlen werden, sind jedoch:
- Programming Windows von Charles Petzold (Microsoft Press)
- Programming Applications for Windows von Jeffrey Richter (Microsoft Press)
Wie kann ich mit den Windows-Symboldateien debuggen?
Microsoft veröffentlicht Stripped-Symbol-Versionen für alle System-DLLs (sowie einige andere). Um auf sie zuzugreifen, fügen Sie Folgendes zu Ihrem Symbolpfad in den Projekteinstellungen in Visual Studio hinzu:
srv*https://msdl.microsoft.com/download/symbols
Verwenden Sie für das lokale Zwischenspeichern von Symbolen die folgende Syntax:
srv*c:\cache*https://msdl.microsoft.com/download/symbols
Dabei ist c:\cache ein lokales Verzeichnis zum Zwischenspeichern von Symboldateien.
Fragen zu Direct3D
Allgemeine Fragen zu Direct3D
Wo finde ich Informationen zu 3D-Grafiktechniken?
Das Standardbuch zum Thema ist „Computer Graphics: Principles and Practice“ von Foley, Van Dam et al. Es ist eine wertvolle Ressource für alle, die die mathematischen Grundlagen von Geometrie, Rasterung und Beleuchtungstechniken verstehen möchten. Die häufig gestellten Fragen für die Usenet-Gruppe comp.graphics.algorithms enthält ebenfalls nützliches Material.
Emuliert Direct3D Funktionen, die nicht von der Hardware bereitgestellt werden?
Das ist unterschiedlich. Direct3D verfügt über eine vollständige Softwarevertexverarbeitungspipeline (einschließlich Unterstützung für benutzerdefinierte Vertex-Shader). Für Vorgänge auf Pixelebene wird jedoch keine Emulation bereitgestellt. Anwendungen müssen die entsprechenden Caps-Bits überprüfen und die ValidateDevice-API verwenden, um die Unterstützung zu ermitteln.
Gibt es einen Softwarerasterizer, der in Direct3D enthalten ist?
Nicht für Leistungsanwendungen. Ein Referenzraster wird für die Treiberüberprüfung bereitgestellt, die Implementierung ist jedoch auf Genauigkeit und nicht auf Leistung ausgelegt. Direct3D unterstützt Plug-In-Softwarerasterizer.
Wie kann ich Colorkeying mit DirectX-Grafiken ausführen?
Colorkeying wird nicht direkt unterstützt, stattdessen müssen Sie die Alphamischung verwenden, um Colorkeying zu emulieren. Die D3DXCreateTextureFromFileEx()-Funktion kann verwendet werden, um dies zu erleichtern. Diese Funktion akzeptiert einen Schlüsselfarbparameter und ersetzt alle Pixel aus dem Quellbild, das die angegebene Farbe enthält, durch transparente schwarze Pixel in der erstellten Textur.
Verwendet der Direct3D-Geometriecode 3DNow! und/oder Intel III SIMD-Anweisungen?
Ja. Die Direct3D-Geometriepipeline verfügt je nach Prozessortyp über mehrere verschiedene Codepfade und verwendet die speziellen Gleitkommavorgänge, die von den 3DNow!- oder Pentium III SIMD-Anweisungen bereitgestellt werden, sofern diese verfügbar sind. Dies umfasst die Verarbeitung von benutzerdefinierten Vertex-Shadern.
Wie kann ich verhindern, dass transparente Pixel in den Z-Puffer geschrieben werden?
Sie können Pixel mit einem Alphawert oberhalb oder unterhalb eines bestimmten Schwellenwerts herausfiltern. Sie steuern dieses Verhalten mithilfe der Renderstates ALPHATESTENABLE, ALPHAREF und ALPHAFUNC.
Was ist ein Schablonenpuffer?
Ein Schablonenpuffer ist ein zusätzlicher Puffer pro Pixel, ähnlich wie ein Z-Puffer. Tatsächlich befindet er sich in einigen der Bits eines Z-Puffers. Allgemeine Schablonen-/Z-Pufferformate sind 15-Bit-Z und 1-Bit-Schablone oder 24-Bit-Z und 8-Bit-Schablone. Es ist möglich, einfache arithmetische Vorgänge für den Inhalt des Schablonenpuffers pro Pixel auszuführen, da Polygone gerendert werden. Beispielsweise kann der Schablonenpuffer inkrementiert oder dekrementiert werden, oder das Pixel kann abgelehnt werden, wenn der Schablonenwert einen einfachen Vergleichstest nicht besteht. Dies ist nützlich für Effekte, die das Markieren eines Bereichs des Framepuffers umfassen und dann nur das Rendern des markierten (oder nicht markierten) Bereichs ausführen. Gute Beispiele sind volumetrische Effekte wie Schattenvolumen.
Wie verwende ich einen Schablonenpuffer zum Rendern von Schattenvolumen?
Der Schlüssel zu diesem und anderen volumetrischen Schablonenpuffereffekten ist die Interaktion zwischen dem Schablonenpuffer und dem Z-Puffer. Eine Szene mit einem Schattenvolumen wird in drei Stufen gerendert. Zunächst wird die Szene ohne Schatten wie gewohnt mithilfe des Z-Puffers gerendert. Als Nächstes wird der Schatten im Schablonenpuffer wie folgt markiert. Die Vorderseiten des Schattenvolumens werden mit unsichtbaren Polygonen gezeichnet, wobei Z-Tests aktiviert sind, aber Z-Schreibvorgänge deaktiviert sind und der Schablonenpuffer bei jedem Pixel erhöht wird, das den Z-Test bestanden hat. Die Rückseiten des Schattenvolumens werden ähnlich gerendert, aber stattdessen wird der Schablonenwert verringert.
Betrachten Sie nun ein einzelnes Pixel. Wenn sich die Kamera nicht im Schattenvolumen befindet, gibt es vier Möglichkeiten für den entsprechenden Punkt in der Szene. Wenn der Strahl von der Kamera bis zum Punkt das Schattenvolumen nicht überschneidet, wurden dort keine Schattenpolygone gezeichnet, und der Schablonenpuffer ist noch null. Andernfalls, wenn der Punkt vor dem Schattenvolumen liegt, werden die Schattenpolygone Z-gepuffert und die Schablone bleibt wieder unverändert. Wenn der Punkt hinter dem Schattenvolumen liegt, wurde die gleiche Anzahl an vorderen Schattenflächen wie an hinteren Flächen gerendert und die Schablone ist Null, da sie so oft inkrementiert wie dekrementiert wurde.
Die letzte Möglichkeit besteht darin, dass sich der Punkt innerhalb des Schattenvolumens befindet. In diesem Fall wird die Rückseite des Schattenvolumens Z-gepuffert, aber nicht die Vorderseite, so dass der Schablonenpuffer einen Wert ungleich Null hat. Das Ergebnis ist, dass Teile des Framepuffers, die im Schatten liegen, einen Schablonenwert ungleich Null haben. Um den Schatten schließlich tatsächlich zu rendern, wird die gesamte Szene mit einem alphanumerisch überblendeten Polygon gewaschen, das so eingestellt ist, dass nur Pixel mit einem Schablonenwert ungleich Null betroffen sind. Ein Beispiel für diese Technik ist im Beispiel „Shadow Volume“ (Schattenvolumen) zu sehen, das im Lieferumfang des DirectX-SDK enthalten ist.
Was sind die Texelausrichtungsregeln? Wie erhalte ich eine 1:1-Zuordnung?
Dies wird in der Direct3D 9-Dokumentation vollständig erläutert. Zusammenfassend lässt sich jedoch sagen, dass Sie Ihre Bildschirmkoordinaten um -0,5 Pixel verzerren sollten, um sie korrekt an den Texeln auszurichten. Die meisten Karten entsprechen jetzt ordnungsgemäß den Texelausrichtungsregeln, es gibt jedoch einige ältere Karten oder Treiber, die dies nicht tun. In diesen Fällen wenden Sie sich am besten an den betreffenden Hardwarehersteller und fordern aktualisierte Treiber oder eine von ihm vorgeschlagene Problemumgehung an. Beachten Sie, dass diese Regel in Direct3D 10 nicht mehr gilt.
Was ist der Zweck des D3DCREATE\_PUREDEVICE-Flags?
Verwenden Sie das D3DCREATE_PUREDEVICE-Flag während der Geräteerstellung, um ein reines Gerät zu erstellen. Ein reines Gerät speichert den aktuellen Zustand nicht (während Zustandsänderungen), wodurch die Leistung häufig verbessert wird. Dieses Gerät erfordert auch hardwarebasierte Vertexverarbeitung. Ein reines Gerät wird in der Regel verwendet, wenn die Entwicklung und das Debuggen abgeschlossen sind und Sie die bestmögliche Leistung erzielen möchten.
Ein Nachteil eines reinen Geräts ist, dass es nicht alle Get*-API-Aufrufe unterstützt; dies bedeutet, dass Sie kein reines Gerät verwenden können, um den Pipelinestatus abzufragen. Dies erschwert das Debuggen beim Ausführen einer Anwendung. Nachfolgend finden Sie eine Liste aller Methoden, die von einem reinen Gerät deaktiviert werden.
- IDirect3DDevice9::GetClipPlane
- IDirect3DDevice9::GetClipStatus
- IDirect3DDevice9::GetLight
- IDirect3DDevice9::GetLightEnable
- IDirect3DDevice9::GetMaterial
- IDirect3DDevice9::GetPixelShaderConstantF
- IDirect3DDevice9::GetPixelShaderConstantI
- IDirect3DDevice9::GetPixelShaderConstantB
- IDirect3DDevice9::GetRenderState
- IDirect3DDevice9::GetSamplerState
- IDirect3DDevice9::GetTextureStageState
- IDirect3DDevice9::GetTransform
- IDirect3DDevice9::GetVertexShaderConstantF
- IDirect3DDevice9::GetVertexShaderConstantI
- IDirect3DDevice9::GetVertexShaderConstantB
Ein zweiter Nachteil eines reinen Geräts besteht darin, dass es keine redundanten Zustandsänderungen filtert. Wenn Sie ein reines Gerät verwenden, sollte Ihre Anwendung die Anzahl der Zustandsänderungen in der Renderschleife auf ein Minimum reduzieren. Dies kann das Filtern von Zustandsänderungen umfassen, um sicherzustellen, dass Zustände nicht mehr als einmal festgelegt werden. Dieser Kompromiss ist von der Anwendung abhängig; wenn Sie mehr als 1000 Set-Aufrufe pro Frame verwenden, sollten Sie erwägen, die Redundanzfilterung zu nutzen, die automatisch von einem nicht reinen Gerät durchgeführt wird.
Wie bei allen Leistungsproblemen besteht die einzige Möglichkeit, zu wissen, ob Ihre Anwendung mit einem reinen Gerät besser funktioniert, darin, die Leistung Ihrer Anwendung mit einem reinen und nicht reinen Gerät zu vergleichen. Ein reines Gerät hat das Potenzial, eine Anwendung zu beschleunigen, indem der CPU-Mehraufwand der API reduziert wird. Aber seien Sie vorsichtig! In einigen Szenarien verlangsamt ein reines Gerät Ihre Anwendung (aufgrund der zusätzlichen CPU-Arbeit, die durch redundante Zustandsänderungen verursacht wird). Wenn Sie nicht sicher sind, welcher Gerätetyp für Ihre Anwendung am besten geeignet ist, und Sie keine redundanten Änderungen in der Anwendung filtern, verwenden Sie ein nicht reines Gerät.
Wie kann ich die Anzeigegeräte in einem Multimonitorsystem aufzählen?
Die Aufzählung kann durch eine einfache Iteration durch die Anwendung unter Verwendung von Methoden der Schnittstelle IDirect3D9 durchgeführt werden. Rufen Sie GetAdapterCount auf, um die Anzahl der Grafikkarten im System zu ermitteln. Rufen Sie GetAdapterMonitor auf, um zu bestimmen, mit welchem physischen Monitor ein Adapter verbunden ist (diese Methode gibt einen HMONITOR zurück, den Sie dann in der Win32-API GetMonitorInfo verwenden können, um Informationen über den physischen Monitor zu ermitteln). Das Ermitteln der Merkmale einer bestimmten Grafikkarte oder das Erstellen eines Direct3D-Geräts auf dieser Grafikkarte ist so einfach wie das Übergeben der entsprechenden Grafikkartennummer anstelle von D3DADAPTER_DEFAULT beim Aufrufen von GetDeviceCaps, CreateDevice oder anderen Methoden.
Was ist mit Fixed Function Bumpmapping in D3D9 passiert?
Ab Direct3D 9 haben wir die Überprüfung von Karten, die nur > 2 gleichzeitige Texturen unterstützen können, verschärft. Bestimmte ältere Karten verfügen nur über 3 Texturstufen, wenn Sie eine bestimmte Alphamodulationsoperation verwenden. Die häufigste Anwendung, für die die 3 Stufen verwendet werden, ist das Emboss-Bumpmapping, und das können Sie auch mit D3D9 machen.
Das Feld „Höhe“ muss im Alphakanal gespeichert werden und wird verwendet, um den Lichtbeitrag zu modulieren, d. h.:
// Stage 0 is the base texture, with the height map in the alpha channel
m_pd3dDevice->SetTexture(0, m_pEmbossTexture );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0 );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
if( m_bShowEmbossMethod )
{
// Stage 1 passes through the RGB channels (SELECTARG2 = CURRENT), and
// does a signed add with the inverted alpha channel.
// The texture coords associated with Stage 1 are the shifted ones, so
// the result is:
// (height - shifted_height) * tex.RGB * diffuse.RGB
m_pd3dDevice->SetTexture( 1, m_pEmbossTexture );
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_ADDSIGNED );
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE|D3DTA_COMPLEMENT );
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
// Set up the alpha blender to multiply the alpha channel
// (monochrome emboss) with the src color (lighted texture)
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ZERO );
}
Dieses Beispiel wird zusammen mit anderen älteren Beispielen nicht mehr in der aktuellen SDK-Version ausgeliefert und wird nicht mehr in zukünftigen SDK-Versionen ausgeliefert.
Geometrie (Vertex)-Verarbeitung
Vertex-Streams verwechseln mich, wie funktionieren sie?
Direct3D assembliert jeden Vertex, der aus einem oder mehreren Vertex-Streams in den Verarbeitungsteil der Pipeline eingespeist wird. Die Verwendung von nur einem Vertex-Stream entspricht dem alten Modell vor DirectX 8, bei dem die Vertexe aus einer einzigen Quelle stammen. Mit DirectX 8 können unterschiedliche Vertexkomponenten aus verschiedenen Quellen stammen. So kann ein Vertex-Puffer beispielsweise Positionen und Normalen enthalten, während ein zweiter Farbwerte und Texturkoordinaten enthält.
Was ist ein Vertex-Shader?
Ein Vertex-Shader ist eine Prozedur für die Verarbeitung eines einzelnen Vertex. Sie wird mithilfe einer einfachen Assembly-ähnlichen Sprache definiert, die von der D3DX-Hilfsprogrammbibliothek in einem Token-Stream zusammengestellt wird, den Direct3D akzeptiert. Der Vertex-Shader verwendet als Eingabe einen einzelnen Vertex und einen Satz konstanter Werte. Er gibt eine Vertexposition (im Clip-Raum) und optional einen Satz von Farben und Texturkoordinaten aus, die in der Rasterung verwendet werden. Beachten Sie, dass bei einem benutzerdefinierten Vertex-Shader die Vertex-Komponenten keine Semantik mehr haben, die von Direct3D auf sie angewandt wird, und dass Vertices einfach beliebige Daten sind, die von dem von Ihnen erstellten Vertex-Shader interpretiert werden.
Führt ein Vertex-Shader perspektivische Division oder Clipping durch?
Nein. Der Vertex-Shader gibt eine homogene Koordinate im Clip-Raum für die transformierte Vertex-Position aus. Perspektivische Division und Clipping werden automatisch nach dem Shader ausgeführt.
Kann ich Geometrie mit einem Vertex-Shader generieren?
Ein Vertex-Shader kann keine Vertices erstellen oder zerstören; er arbeitet jeweils an einem einzelnen Vertex, wobei ein unverarbeiteter Vertex als Eingabe genommen und ein einzelner verarbeiteter Vertex ausgegeben wird. Er kann daher verwendet werden, um bestehende Geometrien zu manipulieren (Verformungen anwenden oder Skinning-Operationen durchführen), aber er kann keine neue Geometrie per se erzeugen.
Kann ich einen benutzerdefinierten Vertex-Shader auf die Ergebnisse der Geometriepipeline mit fester Funktion (oder umgekehrt) anwenden?
Nein. Sie müssen das eine oder das andere auswählen. Wenn Sie einen benutzerdefinierten Vertex-Shader verwenden, sind Sie für die Durchführung der gesamten Vertextransformation verantwortlich.
Kann ich einen benutzerdefinierten Vertex-Shader verwenden, wenn meine Hardware ihn nicht unterstützt?
Ja. Das Direct3D-Software-Vertexverarbeitungsmodul unterstützt benutzerdefinierte Vertex-Shader vollständig mit überraschend hoher Leistung.
Wie kann ich feststellen, ob die Hardware meinen benutzerdefinierten Vertex-Shader unterstützt?
Geräte, die Vertex-Shader in der Hardware unterstützen können, müssen das Feld D3DCAPS9::VertexShaderVersion ausfüllen, um die Versionsebene des von ihnen unterstützten Vertex-Shaders anzugeben. Jedes Gerät, das behauptet, eine bestimmte Ebene des Vertex-Shaders zu unterstützen, muss alle legalen Vertex-Shader unterstützen, die die Spezifikation für diese Ebene oder darunter erfüllen.
Wie viele Konstantenregister sind für Vertex-Shader verfügbar?
Geräte, die vs 1.0 Vertex-Shader unterstützen, müssen mindestens 96 konstante Register unterstützen. Geräte unterstützen möglicherweise mehr als diese Mindestanzahl und können dies über das Feld D3DCAPS9::MaxVertexShaderConst melden.
Kann ich Positionsdaten zwischen Vertices mit unterschiedlichen Texturkoordinaten teilen?
Das übliche Beispiel für diese Situation ist ein Würfel, in dem Sie für jede Seite eine andere Textur verwenden möchten. Leider lautet die Antwort „Nein“, es ist derzeit nicht möglich, die Vertexkomponenten unabhängig voneinander zu indizieren. Auch bei mehreren Vertex-Streams werden alle Streams zusammen indiziert.
Wenn ich eine indizierte Liste von Grundtypen sende, verarbeitet Direct3D alle Vertices im Puffer oder nur die, die ich indiziert habe?
Wenn Sie die Softwaregeometriepipeline verwenden, transformiert Direct3D zunächst alle Vertices im von Ihnen übermittelten Bereich, anstatt sie beim Indizieren „bei Bedarf“ zu transformieren. Bei dicht gepackten Daten (d. h., wo die meisten Vertices verwendet werden) ist dies effizienter, insbesondere, wenn SIMD-Anweisungen verfügbar sind. Wenn Ihre Daten spärlich gepackt sind (d. h. viele Vertices werden nicht verwendet), sollten Sie die Neuanordnung Ihrer Daten in Betracht ziehen, um zu viele redundante Transformationen zu vermeiden. Bei Verwendung der Hardwaregeometriebeschleunigung werden Vertices in der Regel bei Bedarf transformiert.
Was ist ein Indexpuffer?
Ein Indexpuffer ist genau analog zu einem Vertexpuffer, enthält aber stattdessen Indizes für die Verwendung in DrawIndexedPrimitive-Aufrufen. Es wird dringend empfohlen, nach Möglichkeit Indexpuffer anstelle von unformatiertem anwendungszugeteiltem Arbeitsspeicher zu verwenden, aus denselben Gründen wie Vertexpuffer.
Ich stelle fest, dass 32-Bit-Indizes ein unterstützter Typ sind; kann ich sie auf allen Geräten verwenden?
Nein. Sie müssen das Feld D3DCAPS9::MaxVertexIndex überprüfen, um den maximalen Indexwert zu ermitteln, der vom Gerät unterstützt wird. Dieser Wert muss größer als 2 bis zur 16. Potenz -1 (0xffff) sein, damit Indexpuffer vom Typ D3DFMT_INDEX32 unterstützt werden. Beachten Sie außerdem, dass einige Geräte 32-Bit-Indizes unterstützen, aber einen maximalen Indexwert unter 2 bis zur 32. Potenz -1 (0xffffffff) unterstützen; in diesem Fall muss die Anwendung den vom Gerät gemeldeten Grenzwert einhalten.
Unterstützt die S/W-Vertexverarbeitung 64 Bit?
Es gibt eine optimierte S/W-Vertex-Pipeline für x64, aber sie existiert nicht für IA64.
Leistungsoptimierung
Wie kann ich die Leistung meiner Direct3D-Anwendung verbessern?
Im Folgenden sind die wichtigsten Bereiche aufgeführt, die beim Optimieren der Leistung zu beachten sind:
Batchgröße
Direct3D ist für große Batches von Grundtypen optimiert. Je mehr Polygone in einem einzelnen Anruf gesendet werden können, desto besser. Eine gute Faustregel besteht darin, durchschnittlich 1000 Vertices pro Grundtypaufruf zu erreichen. Unterhalb dieses Niveaus erreichen Sie wahrscheinlich keine optimale Leistung, oberhalb dieses Niveaus nehmen die Erträge ab und es kann zu Konflikten mit Parallelitätsüberlegungen kommen (siehe unten).
Zustandsänderungen
Das Ändern des Renderzustands kann ein kostspieliger Vorgang sein, insbesondere beim Ändern der Textur. Aus diesem Grund ist es wichtig, die Anzahl der pro Frame vorgenommenen Zustandsänderungen so weit wie möglich zu minimieren. Versuchen Sie außerdem, Änderungen des Vertex- oder Indexpuffers zu minimieren.
Hinweis
Ab DirectX 8 ist die Kosten für das Ändern des Vertexpuffers nicht mehr so teuer wie bei früheren Versionen, es empfiehlt sich jedoch, nach Möglichkeit Vertexpufferänderungen zu vermeiden.
Parallelität
Wenn Sie das Rendern gleichzeitig mit einer anderen Verarbeitung durchführen können, nutzen Sie die Systemleistung vollständig. Dieses Ziel kann mit dem Ziel in Konflikt geraten, Renderstate-Änderungen zu reduzieren. Sie müssen ein Gleichgewicht finden zwischen der Stapelverarbeitung, um Zustandsänderungen zu reduzieren, und der frühzeitigen Weitergabe von Daten an den Treiber, um Gleichzeitigkeit zu erreichen. Die Verwendung mehrerer Vertex-Puffer im Round-Robin-Verfahren kann bei der Parallelität helfen.
Texturuploads
Das Hochladen von Texturen auf das Gerät verbraucht Bandbreite und verursacht einen Bandbreitenwettbewerb mit Vertexdaten. Daher ist es wichtig, den Texturspeicher zu überanspruchen, da dies Ihr Caching-System dazu zwingen würde, übermäßige Mengen an Texturen pro Frame hochzuladen.
Vertex- und Indexpuffer
Sie sollten immer Vertex- und Indexpuffer verwenden und keine einfachen Blöcke aus dem von der Anwendung zugewiesenen Speicher. Die Sperrsemantik für Vertex- und Indexpuffer kann mindestens einen redundanten Kopiervorgang vermeiden. Bei einigen Treibern kann der Vertex- oder Indexpuffer für den Zugriff durch die Hardware im optimalen Speicher (z. B. im Video- oder AGP-Speicher) platziert werden.
Statusmakroblöcke
Diese wurden in DirectX 7.0 eingeführt. Sie bieten einen Mechanismus zum Aufzeichnen einer Reihe von Zustandsänderungen (einschließlich Beleuchtungs-, Material- und Matrixänderungen) in ein Makro, das dann von einem einzelnen Aufruf wiedergegeben werden kann. Das hat zwei Vorteile:
- Sie reduzieren den Aufruf-Mehraufwand, indem Sie einen Aufruf statt vieler tätigen.
- Ein fähiger Treiber kann die Zustandsänderungen vorab analysieren und vorab kompilieren, sodass sie wesentlich schneller an die Grafikhardware übermittelt werden können.
Zustandsänderungen können weiterhin teuer sein, aber die Verwendung von Zustandsmakros kann dazu beitragen, mindestens einen Teil der Kosten zu reduzieren. Verwenden Sie nur ein einzelnes Direct3D-Gerät. Wenn Sie auf mehrere Ziele rendern müssen, verwenden Sie SetRenderTarget. Wenn Sie eine Fensteranwendung mit mehreren 3D-Fenstern erstellen, verwenden Sie die CreateAdditionalSwapChain-API. Die Runtime ist für ein einzelnes Gerät optimiert und es gibt eine erhebliche Geschwindigkeitsstrafe für die Verwendung mehrerer Geräte.
Welche Grundtypen (Streifen, Fächer, Listen usw.) sollte ich verwenden?
Viele Gittermodelle in echten Datenfeature-Vertices, die von mehreren Polygonen gemeinsam genutzt werden. Um die Leistung zu maximieren, ist es wünschenswert, die Duplizierung in Vertices zu reduzieren, die transformiert und über den Bus an das Renderinggerät gesendet werden. Es ist klar, dass die Verwendung einfacher Dreieckslisten keine Vertexfreigabe erreicht, was sie zur am wenigsten optimalen Methode macht. Die Wahl ist dann zwischen der Verwendung von Streifen und Fächern, die eine bestimmte Konnektivitätsbeziehung zwischen Polygonen und der Verwendung indizierter Listen bedeuten. Wenn die Daten auf natürliche Weise in Streifen und Fächer fallen, sind diese die beste Wahl, da sie die an den Treiber gesendeten Daten minimieren. Die Dekompilierung von Gittermodellen in Streifen und Fächern führt jedoch häufig zu einer großen Anzahl von separaten Teilen, was eine große Anzahl von DrawPrimitive-Aufrufen bedeutet. Aus diesem Grund besteht die effizienteste Methode in der Regel darin, einen einzelnen DrawIndexedPrimitive-Aufruf mit einer Dreiecksliste zu verwenden. Ein weiterer Vorteil der Verwendung einer indizierten Liste besteht darin, dass ein Vorteil auch dann gewonnen werden kann, wenn aufeinander folgende Dreiecke nur einen einzelnen Vertex teilen. Wenn Ihre Daten natürlich in große Streifen oder Fächer fallen, verwenden Sie Streifen oder Fächer; verwenden Sie andernfalls indizierte Listen.
Wie bestimmen Sie den gesamten Texturspeicher, den eine Karte hat, mit Ausnahme des AGP-Speichers?
IDirect3DDevice9::GetAvailableTextureMem gibt den verfügbaren Gesamtspeicher zurück, einschließlich AGP. Das Zuordnen von Ressourcen basierend auf einer Annahme darüber, wie viel Videospeicher Sie haben, ist keine großartige Idee. Was geschieht beispielsweise, wenn die Karte unter einer Unified Memory Architecture (UMA) läuft oder die Texturen komprimieren kann? Möglicherweise steht mehr Platz zur Verfügung, als Sie dachten. Sie sollten Ressourcen erstellen und nach Fehlern wegen Speichermangels suchen und dann die Texturen reduzieren. Sie könnten beispielsweise die obersten Mip-Ebenen Ihrer Texturen entfernen.
Was ist ein gutes Verwendungsmuster für Vertexpuffer, wenn ich dynamische Daten generiere?
- Erstellen Sie einen Vertexpuffer mithilfe der D3DUSAGE_DYNAMIC- und D3DUSAGE_WRITEONLY-Nutzungsflags und des D3DPOOL_DEFAULT-Poolflags. (Geben Sie auch D3DUSAGE_SOFTWAREPROCESSING an, wenn Sie Softwarevertexverarbeitung verwenden.)
- I = 0.
- Legen Sie den Zustand fest (Texturen, Renderstates usw.).
- Überprüfen Sie, ob im Puffer Leerraum vorhanden ist, z. B. I + M <= N? (Dabei ist M die Anzahl neuer Vertices).
- Wenn ja, sperren Sie das VB mit D3DLOCK_NOOVERWRITE. Damit teilen Sie Direct3D und dem Treiber mit, dass Sie neue Vertices hinzufügen und nicht die ändern werden, die Sie zuvor im Batch zusammengefasst haben. Daher wird ein DMA-Vorgang nicht unterbrochen, wenn er ausgeführt wurde. Wenn nein, gehen Sie zu 11.
- Füllen Sie die M-Vertices bei I aus.
- Entsperren.
- Rufen Sie Draw[Indexed]Primitive auf. Bei nicht indizierten Grundtypen verwenden Sie „I“ als StartVertex-Parameter. Stellen Sie für indizierte Grundtypen sicher, dass die Indizes auf den richtigen Teil des Vertexpuffers verweisen (es kann am einfachsten sein, den BaseVertexIndex-Parameter des SetIndices-Aufrufs zu verwenden, um dies zu erreichen).
- I += M.
- Gehen Sie zu 3.
- Ok, wir haben also keinen Platz mehr, also lassen Sie uns mit einem neuen VB anfangen. Wir möchten nicht dasselbe verwenden, da möglicherweise ein DMA-Vorgang ausgeführt wird. Wir kommunizieren dies an Direct3D und den Treiber, indem wir dasselbe VB mit dem D3DLOCK_DISCARD-Flag sperren. Das bedeutet: „Sie können mir einen neuen Zeiger geben, weil ich mit dem alten fertig bin und mir der alte Inhalt nicht mehr wirklich wichtig ist.“
- I = 0.
- Gehen Sie zu 4 (oder 6).
Warum muss ich weitere Informationen in der D3DVERTEXELEMENT9-Struktur angeben?
Ab Direct3D 9 ist die Vertex-Stream-Deklaration nicht mehr nur ein DWORD-Array, sie ist jetzt ein Array von D3DVERTEXELEMENT9-Strukturen. Die Runtime verwendet die zusätzlichen Semantik- und Nutzungsinformationen, um den Inhalt von Vertex-Streams an Vertex-Shader-Eingaberegister/-variablen zu binden. Bei Direct3D 9 werden Vertexdeklarationen von Vertex-Shadern entkoppelt, sodass Shader mit Geometrien unterschiedlicher Formate einfacher verwendet werden können, da die Runtime nur die Daten bindet, die der Shader benötigt.
Die neuen Vertexdeklarationen können entweder mit der Pipeline mit festen Funktionen oder mit Shadern verwendet werden. Für die Pipeline mit festen Funktionen muss „SetVertexShader“ nicht aufgerufen werden. Wenn Sie jedoch zur Pipeline mit festen Funktionen wechseln möchten und zuvor einen Vertex-Shader verwendet haben, rufen Sie SetVertexShader(NULL) auf. Wenn dies erfolgt ist, müssen Sie SetFVF weiterhin aufrufen, um den FVF-Code zu deklarieren.
Rufen Sie bei Verwendung von Vertex-Shadern SetVertexShader mit dem Vertex-Shaderobjekt auf. Rufen Sie außerdem SetFVF auf, um eine Vertexdeklaration einzurichten. Dies verwendet die im FVF impliziten Informationen. SetVertexDeclaration kann anstelle von SetFVF aufgerufen werden, da sie Vertexdeklarationen unterstützt, die nicht mit einem FVF ausgedrückt werden können.
D3DX-Hilfsprogrammbibliothek
Welche Dateiformate werden von den D3DX-Bilddateiladefunktionen unterstützt?
Die D3DX-Bilddateiladefunktionen unterstützen BMP-, TGA-, JPG-, DIB-, PPM- und DDS-Dateien.
Die Textrenderingfunktionen in D3DX scheinen nicht zu funktionieren, was mache ich falsch?
Ein häufiger Fehler bei der Verwendung der ID3DXFont::DrawText-Funktionen besteht darin, eine Null-Alpha-Komponente für den Farbparameter anzugeben; dies führt zu vollständig transparentem (d. h. unsichtbarem) Text. Stellen Sie für vollständig undurchsichtigen Text sicher, dass die Alphakomponente des Farbparameters vollständig gesättigt ist (255).
Wie kann ich den Inhalt einer Oberfläche oder Textur in einer Datei speichern?
Das DirectX 8.1 SDK hat der D3DX-Bibliothek zwei Funktionen speziell für diesen Zweck hinzugefügt: D3DXSaveSurfaceToFile() und D3DXSaveTextureToFile(). Diese Funktionen unterstützen das Speichern eines Bilds in einer Datei im BMP- oder DDS-Format. In früheren Versionen müssen Sie die Oberfläche sperren und die Bilddaten lesen und dann in eine Bitmapdatei schreiben. Informationen zum Schreiben einer Funktion zum Speichern von Bitmaps finden Sie unter Speichern eines Bildes.
Alternativ kann GDI+ verwendet werden, um das Bild in einer Vielzahl von Formaten zu speichern, obwohl dies zusätzliche Supportdateien erfordert, die mit Ihrer Anwendung verteilt werden müssen.
Wie kann ich die High Level Shader Language (HLSL) in meinem Spiel verwenden?
Es gibt drei Möglichkeiten, wie die Microsoft High Level Shader Language (HLSL) in Ihre Spielengine integriert werden kann:
- Kompilieren Sie die Shaderquelle in Vertex- oder Pixelschattierungsassembly (mit dem Befehlszeilenprogramm fxc.exe), und verwenden Sie zur Laufzeit D3DXAssembleShader(). Auf diese Weise kann sogar ein DirectX 8-Spiel die Leistungsfähigkeit der HLSL nutzen.
- Verwenden Sie D3DXCompileShader() zum Kompilieren der Shaderquelle in Tokenstream- und Konstantentabellenformular. Laden Sie zur Laufzeit den Token-Stream und die Konstantentabelle herunter und rufen Sie CreateVertexShader() oder CreatePixelShader() auf dem Gerät auf, um Ihre Shader zu erstellen.
- Am einfachsten können Sie das D3DX Effects-System nutzen, indem Sie D3DXCreateEffectFromFile() oder D3DXCreateEffectFromResource() mit Ihrer Effektdatei aufrufen.
Was ist der Zweck des neuen Shadercompiler-Flags?
Ab dem Dezember 2006 erschienen DirectX SDK wurde der neue HLSL-Compiler, der für Direct3D 10 entwickelt wurde, für Direct3D 9-Ziele aktiviert. Der neue Compiler unterstützt keine ps_1_x Ziele und ist jetzt der Standardcompiler für alle Direct3D HLSL-Shader. Ein Flag für Abwärtskompatibilität kann verwendet werden, um zu erzwingen, dass ps_1_x Ziele verschwinden und als ps_2_0-Ziele kompiliert werden.
Anwendungen, die den Legacycompiler verwenden möchten, können dies weiterhin tun, indem sie ein Flag zur Laufzeit bereitstellen (siehe Compilerflags) oder einen Switch bei Verwendung von fxc bereitstellen.
Was ist die richtige Methode zum Abrufen von Shadern aus einem Effekt?
Verwenden Sie D3DXCreateEffect, um einen ID3DXEffect zu erstellen, und verwenden Sie dann GetPassDesc, um eine D3DXPASS_DESC abzurufen. Diese Struktur enthält Zeiger auf Vertex- und Pixelshader.
Verwenden Sie ID3DXEffectCompiler::GetPassDesc nicht. Vertex- und Pixelshaderhandles, die von dieser Methode zurückgegeben werden, sind NULL.
Wofür ist das HLSL-Rauschen() intrinsisch?
Die systeminterne Rauschfunktion erzeugt Perlin-Rauschen, wie von Ken Perlin definiert. Die HLSL-Funktion kann derzeit nur verwendet werden, um Texturen in Texturshadern auszufüllen, da die aktuelle h/w die Methode nicht nativ unterstützt. Texturshader werden in Verbindung mit den D3DXFill*Texture()-Funktionen verwendet, die nützliche Hilfsfunktionen sind, um prozedural definierte Texturen während der Ladezeit zu generieren.
Wie kann ich feststellen, ob das Pixelshadermodell 2.0 oder 2.a verwendet werden soll?
Sie können die Funktionen D3DXGetPixelShaderProfile() und D3DXGetPixelShaderProfile() verwenden, die eine Zeichenfolge zurückgeben, die bestimmt, welches HLSL-Profil am besten für das ausgeführte Gerät geeignet ist.
Wie kann ich auf die Parameter in meinen vorkompilierten Effekt-Shadern zugreifen?
Über die ID3DXConstantTable-Schnittstelle, die für den Zugriff auf die Konstantentabelle verwendet wird. Diese Tabelle enthält die Variablen, die von allgemeinen Sprachshadern und Effekten verwendet werden.
Gibt es eine Möglichkeit, Benutzerdaten zu einem Effekt oder einer anderen Ressource hinzuzufügen?
Ja, um private Daten festzulegen, rufen Sie SetPrivateData auf (pReal ist das D3D-Texturobjekt, pSpoof ist das mit einem Wrapper versehene Texturobjekt).
hr = pReal->SetPrivateData(IID_Spoof, &pSpoof,
sizeof(IDirect3DResource9*), 0)));
So suchen Sie den mit einem Wrapper versehenen Zeiger:
IDirect3DResource9* pSpoof;
DWORD dwSize = sizeof(pSpoof);
hr = pReal->GetPrivateData(IID_Spoof, (void*) &pSpoof, &dwSize);
Warum verlangsamt sich das Rendern eines ID3DXMesh-Objekts erheblich, nachdem ich Teilmengen definiert habe?
Sie haben das Gittermodell wahrscheinlich nicht optimiert, nachdem Sie die Seitenattribute definiert haben. Wenn Sie Attribute angeben und dann ID3DXMesh::DrawSubset() aufrufen, muss diese Methode eine Suche des Gittermodells für alle Seiten ausführen, die die angeforderten Attribute enthalten. Darüber hinaus befinden sich die gerenderten Seiten wahrscheinlich in einem Muster für den zufälligen Zugriff, wodurch kein Vertexcache verwendet wird. Nachdem Sie die Seitenattribute für Ihre Untergruppen definiert haben, rufen Sie die Methoden ID3DXMesh::Optimize oder ID3DXMesh::OptimizeInPlace auf und geben eine Optimierungsmethode von D3DXMESHOPT_ATTRSORT oder höher an. Beachten Sie, dass Sie für eine optimale Leistung mit dem Flag D3DXMESHOPT_VERTEXCACHE optimieren sollten, wodurch Vertices auch für eine optimale Vertexcacheauslastung neu angeordnet werden. Das für ein D3DX-Gittermodell generierte Adjacency-Array weist drei Einträge pro Seite auf, einige Seiten weisen jedoch möglicherweise keine angrenzenden Seiten an allen drei Kanten auf. Wie ist dies codiert? Einträge, bei denen keine angrenzenden Seiten vorhanden sind, werden als 0xffffffff codiert.
Ich habe viel über Pre-computed Radiance Transfer (PRT) gehört, wo kann ich mehr erfahren?
PRT ist ein neues Feature von D3DX, das im Summer 2003 SDK Update hinzugefügt wurde. Es ermöglicht das Rendern komplexer Beleuchtungsszenarien wie globale -Llumination, weiche Schattierung und Suboberflächenstreuung in Echtzeit. Das SDK enthält Dokumentationen und Beispiele für die Integration der Technologie in Ihr Spiel. In den Beispielen PRT Demo Sample und LocalDeformablePRT Sample wird veranschaulicht, wie der Simulator für Szenarien pro Vertex und pro Pixelbeleuchtung verwendet wird. Weitere Informationen dazu und zu anderen Themen finden Sie auch auf der Webseite von Peter Pike Sloan.
Wie kann ich in einer Textur rendern und Antialiasing verwenden?
Erstellen Eines Multisampling-Renderziels mit Direct3DDevice9::CreateRenderTarget. Nachdem die Szene in dieses Renderziel gerendert wurde, führen Sie StretchRect von ihr zu einer Renderzieltextur aus. Wenn Sie Änderungen am Offscreentexter vorgenommen haben (z. B. Verschwimmen oder Blooming), kopieren Sie sie wieder in den Hintergrundpuffer, bevor Sie präsentieren().
Fragen zu DirectSound
Warum erhalte ich beim Starten meiner Anwendung einen Burst von Rauschen? Ich bemerke dieses Problem auch mit anderen Anwendungen.
Wahrscheinlich haben Sie die Debug-DirectX-Runtime installiert. Die Debugversion der Runtime füllt Puffer mit Rauschen, damit Entwickler Fehler mit nicht initialisierten Puffern erkennen können. Sie können den Inhalt eines DirectSound-Puffers nach der Erstellung nicht garantieren; insbesondere können Sie nicht davon ausgehen, dass ein Puffer auf Null gesetzt wird.
Warum habe ich eine Verzögerung zwischen dem Ändern von Effektparametern und dem Hören der Ergebnisse?
Änderungen in Effektparametern erfolgen nicht immer sofort auf DirectX 8. Aus Effizienzgründen verarbeitet DirectSound 100 Millisekunden an Sounddaten in einem Puffer, beginnend mit dem Wiedergabecursor, bevor der Puffer wiedergegeben wird. Diese Vorverarbeitung erfolgt nach allen folgenden Aufrufen:
IDirectSoundBuffer8::SetCurrentPosition
IDirectSoundBuffer8::SetFX
IDirectSoundBuffer8::Stop
IDirectSoundBuffer8::Unlock
Ab DirectX 9 widmet sich ein neuer FX-Verarbeitungsalgorithmus, der Effekte just-in-time verarbeitet, diesem Problem und hat die Latenz verringert. Der Algorithmus wurde dem IDirectSoundBuffer8::Play()-Aufruf zusammen mit einem zusätzlichen Thread hinzugefügt, der Effekte direkt vor dem Schreibcursor verarbeitet. Sie können Parameter jederzeit festlegen, und sie funktionieren wie erwartet. Beachten Sie jedoch, dass bei einem Wiedergabepuffer eine kleine Verzögerung (in der Regel 100 ms) vorhanden ist, bevor Sie die Parameteränderung hören, da die Audiowiedergabe zwischen dem Wiedergabe- und dem Schreibcursor (und ein bisschen mehr Abstand) zu diesem Zeitpunkt bereits verarbeitet wurden.
Wie kann ich erkennen, ob DSound installiert ist?
Wenn Sie DirectSoundEnumerate() nicht verwenden müssen, um die verfügbaren DSound-Geräte auflisten zu können, verknüpfen Sie Ihre Anwendung nicht mit dsound.lib und verwenden Sie sie stattdessen über COMs CoCreateInstance (CLSID_DirectSound ...) und initialisieren Sie dann das DSound-Objekt mit Initialize(NULL). Wenn Sie DirectSoundEnumerate() verwenden müssen, können Sie „dsound.dll“ dynamisch mit LoadLibrary("dsound.dll") laden und auf seine Methoden mit GetProcAddress("DirectSoundEnumerateA/W") und GetProcAddress("DirectSoundCreateA/W") usw. zugreifen.
Wie erstelle ich Mehrkanalaudio mit WAVEFORMATEXTENSIBLE?
Wenn Sie in den DirectSound-Hilfedateien keine Antwort auf Ihre Frage finden können, finden Sie einen guten Artikel mit weiteren Informationen unter „Mehrkanalige Audiodaten und WAVE-Dateien“.
Wie kann ich den DirectSound Voice Manager mit Eigenschaftensätzen wie EAX verwenden?
In DirectSound 9.0, wenn Sie einen Puffer duplizieren, ist es jetzt möglich, die IDirectSoundBuffer8-Schnittstelle im doppelten Puffer abzurufen, wodurch Sie Zugriff auf die AcquireResources-Methode erhalten. Damit können Sie einen Puffer mit dem Flag DSBCAPS_LOCDEFER mit einer Hardware-Ressource verknüpfen. Anschließend können Sie Ihre EAX-Parameter für diesen Puffer festlegen, bevor Sie Play() aufrufen müssen.
Ich habe Probleme mit dem unzuverlässigen Verhalten bei Verwendung von Cursor-Positions-Benachrichtigungen. Wie erhalte ich genauere Informationen?
Es gibt einige subtile Fehler in verschiedenen Versionen von DirectSound, dem zentralen Windows-Audiostapel und Audiotreibern, die Benachrichtigungen über Cursor-Positionen unzuverlässig machen. Wenn Sie nicht auf eine bekannte HW/SW-Konfiguration abzielen, für die Sie wissen, dass Benachrichtigungen sich ordnungsgemäß verhalten, vermeiden Sie Cursor-Positions-Benachrichtigungen. Für die Positionsverfolgung ist GetCurrentPosition() eine sicherere Technik.
Bei Verwendung von GetCurrentPosition() verzeichne ich Leistungsbeeinträchtigungen. Was kann ich tun, um die Leistung zu verbessern?
Jeder GetCurrentPosition()-Aufruf für jeden Puffer verursacht einen Systemaufruf, und Systemaufrufe sollten minimiert werden, da sie eine große Komponente der CPU-Belastung von DSound sind. Bei NT (Win2K und XP) bewegen sich die Cursor in SW-Puffern (und auf einigen Geräten HW-Puffern) in Schritten von 10 ms, sodass das Aufrufen von GetCurrentPosition() alle 10 ms ideal ist. Wenn Sie sie häufiger als alle 5 ms aufrufen, wird eine Leistungsbeeinträchtigung verursacht.
Meine DirectSound-Anwendung nimmt zu viel CPU-Zeit in Anspruch oder wird langsam ausgeführt. Gibt es etwas, das ich tun kann, um meinen Code zu optimieren?
Es gibt mehrere Möglichkeiten, die Leistung ihres Audiocodes zu verbessern:
Rufen Sie GetCurrentPosition nicht zu oft auf. Jeder GetCurrentPosition()-Aufruf für jeden Puffer verursacht einen Systemaufruf, und Systemaufrufe sollten minimiert werden, da sie eine große Komponente der CPU-Belastung von DSound sind. Bei NT (Win2K und XP) bewegen sich die Cursor in SW-Puffern (und auf einigen Geräten HW-Puffern) in Schritten von 10 ms, sodass das Aufrufen von GetCurrentPosition() alle 10 ms ideal ist. Wenn Sie sie häufiger als alle 5 ms aufrufen, wird eine Leistungsminderung verursacht.
Verwenden Sie eine separate, niedrigere Framerate für Audio. Heutzutage können viele Windows-Spiele 100 Frames pro Sekunde überschreiten, und es ist in den meisten Fällen nicht erforderlich, Ihre 3D-Audioparameter mit derselben Framerate zu aktualisieren. Durch die Verarbeitung ihrer Audiodaten jeden zweiten oder dritten Grafikframe, oder etwa alle 30 ms, kann die Anzahl der Audioaufrufe in der gesamten Anwendung erheblich reduziert werden, ohne die Audioqualität zu verringern.
Verwenden Sie DS3D_DEFERRED für 3D-Objekte. Die meisten Soundkarten reagieren sofort auf Parameteränderungen, und in einem einzelnen Frame kann sich viel ändern, insbesondere, wenn Sie die Position oder Ausrichtung des Listeners ändern. Dies führt dazu, dass die Soundkarte / CPU viele unnötige Berechnungen durchführt, sodass eine weitere schnelle und universelle Optimierung darin besteht, einige Parameteränderungen zurückzustellen und diese am Ende des Frames zu übernehmen.
oder mindestens SetAllParameters anstelle einzelner Set3DParamX-Aufrufe für Puffer verwenden.
Ebenso sollten Sie mindestens SetAllParamenters-Aufrufe für 3D-Puffer verwenden anstatt die einzelnen Set3DParamX-Aufrufe. Versuchen Sie einfach, Systemaufrufe nach Möglichkeit zu minimieren.
Führen Sie keine redundanten Anrufe durch; speichern und sortieren Sie eine Liste von Wiedergabeaufrufen. Häufig gibt es in einem Audioupdateframe 2 Anforderungen zum Wiedergeben neuer Sounds. Wenn die Anforderungen während der Ankunft verarbeitet werden, könnte der erste neue Sound gestartet und dann sofort den zweiten angeforderten Sound ersetzt werden. Dies führt zu redundanten Berechnungen, einem unnötigen Wiedergabeaufruf und einem unnötigen Stoppaufruf. Es ist besser, eine Liste der Anforderungen für die Wiedergabe neuer Sounds zu speichern, damit die Liste sortiert werden kann, und nur die Stimmen, die mit der Wiedergabe beginnen sollten, tatsächlich wiedergegeben werden.
Außerdem sollten Sie lokale Kopien der 3D- und EAX-Parameter für jede Soundquelle speichern. Wenn eine Anforderung zum Festlegen eines Parameters auf einen bestimmten Wert erfolgt, können Sie überprüfen, ob sich der Wert tatsächlich vom letzten Wertsatz unterscheidet. Ist dies nicht der Fall, muss der Anruf nicht getätigt werden.
Obwohl der Soundkartentreiber dieses Szenario wahrscheinlich erkennt und nicht erneut die (gleiche) Berechnung durchführt, muss der Audioaufruf den Audiotreiber (über einen Ringübergang) erreichen, und dies ist bereits ein langsamer Vorgang.
Wenn ich einen Puffer streame, tendiert er dazu, Störungen aufzuweisen und schlecht zu funktionieren. Was ist die beste Methode zum Streamen eines Puffers?
Beim Streamen von Audio in einen Puffer gibt es zwei grundlegende Algorithmen: After-Write-Cursor (AWC) und Before-Play-Cursor (BPC). AWC minimiert die Latenz auf Kosten von Störungen, während BPC das Gegenteil bewirkt. Da es in der Regel keine interaktiven Änderungen am gestreamten Sound gibt, ist diese Art von Latenz selten ein Problem für Spiele und ähnliche Anwendungen, sodass BPC der passendere Algorithmus ist. Bei jeder Ausführung des Streamingthreads in AWC werden die Daten in den Schleifenpuffern bis zu N ms über die Schreibcursor hinaus (in der Regel N=40 oder so, um Windows-Planungs-Jitter zuzulassen) „oben“ hochzuschlagen. In BPC schreiben Sie immer so viele Daten wie möglich in die Puffer, füllen sie direkt bis zu ihren Wiedergabecursorn aus (oder vielleicht 32 Bytes, bevor Sie Treibern erlauben, die den Wiedergabecursorstatus falsch melden).
Verwenden Sie BPC, um Störungen zu minimieren und Puffer von 100 ms oder größer zu verwenden, auch wenn Ihre Spiele nicht auf der Testhardware glitchen, wird sie auf einem Computer dort glitch.
Ich spiele die gleichen Sounds immer wieder und sehr oft und sehr schnell und manchmal werden sie nicht richtig wiedergegeben, oder der Play()-Aufruf dauert eine lange Zeit. Was soll ich tun?
Die Startlatenz (die sich von der oben erwähnten Streaminglatenz unterscheidet) kann ein Problem sein, wenn es bei einigen Hardwareaufrufen (der Play()-Aufruf) nur eine lange Zeit auf bestimmten Soundkarten dauert. Wenn Sie diese Latenz wirklich reduzieren möchten, können Sie für zuckende Geräusche (Pistolenschüsse, Schritte usw.) einen praktischen Trick anwenden, indem Sie einige Puffer immer in einer Schleife halten und Stille abspielen lassen. Wenn Sie einen zuckenden Ton wiedergeben müssen, wählen Sie einen freien Puffer aus, sehen Sie, wo sich der Schreibcursor befindet, und legen Sie den Ton direkt über den Schreibcursor hinaus in den Puffer. Einige Soundkarten schlagen bei QuerySupport für verzögerte Eigenschaften fehl, von denen ich weiß, dass sie sie unterstützen. Gibt es eine Problemumgehung? Sie könnten nur QuerySupport für die nicht verzögerten Versionen der Eigenschaften verwenden und trotzdem verzögerte Einstellungen verwenden. Die neuesten Soundkartentreiber können dieses Problem möglicherweise auch beheben.
Wie codiere ich WAV-Dateien in WMA?
Weitere Informationen finden Sie in der Dokumentation zum Windows Media Encoder unter: Windows Media Encoder 9 Series.
Wie decodiere ich MP3-Dateien mit DirectSound?
DirectSound unterstützt die MP3-Decodierung nicht nativ. Sie können die Dateien vorab selbst decodieren (mit einem ACM-Codec eines DirectShow-Filters) oder einfach DirectShow selbst verwenden, was die Decodierung für Sie erledigen kann; Anschließend können Sie die resultierenden PCM-Audiodaten in Ihre DirectSound-Puffer kopieren.
DirectX-Erweiterungen für Alias Maya
Warum werden meine NURBS nicht angezeigt?
NURBS werden nicht unterstützt. Sie können sie in Polygongittermodelle konvertieren.
Warum werden meine SUBDs nicht angezeigt?
SUBDs werden nicht unterstützt. Sie können sie in Polygongittermodelle konvertieren.
Warum sieht meine Animation in der X-Datei anders aus als die Animation im Vorschaufenster?
Das Vorschaufenster wird nicht im strengsten Sinne der Angelegenheit animiert. Es wird keine Animation wiedergegeben, sondern stattdessen mit dem aktuellen Zustand der Maya-Szene synchronisiert. Wenn Animation exportiert wird, werden die Matrizen bei jeder Transformation in Skalierung, Drehung (Quaternion) und Übersetzungskomponenten (häufig als SRTs bezeichnet) dekompiliert. SRTs sind wünschenswerter als Matrizen, da sie gut interpolieren, eine kompaktere Form der Daten bereitstellen und unabhängig komprimiert werden können. Nicht alle Matrizen können in SRTs unterteilt werden. Wenn sie nicht dekompilieren können, sind die resultierenden SRTs unbekannt, sodass möglicherweise kleine Fehler in der Animation erkannt werden. Die beiden Features in Maya, die bei der Dekompilierung am häufigsten Probleme verursachen, sind Scheren und Drehungen aus der Mitte oder Skalen. Wenn Sie auf dieses Problem stoßen, weil Sie außermittige Drehungen oder Skalierungen verwenden, sollten Sie zusätzliche Transformationen hinzufügen, die Ihre Hierarchieebene erhöhen.
Wenn D3DX-Animation SRTs unterstützt, sieht es wie folgt aus:
[S]x[R]x[T]
Mayas Matrizen sind viel komplizierter und erfordern einen erheblichen zusätzlichen Prozess, der wie folgt aussieht:
[SpInv]x[S]x[Sh]x[Sp]x[St]x[RpInv]x[Ro]x[R]x[Rp]x[Rt]x[T]
Ich habe mein Gitter mit RigidSkin behandelt, aber das Gittermodell (oder der Teil) bewegt sich nicht. Warum?
Mayas starre Haut wird derzeit nicht unterstützt. Bitte verwenden Sie glatte Haut.
Wohin ist meine IK in der X-Datei verschwunden?
X-Dateien unterstützen IK nicht. Stattdessen werden die IK-Lösungen in die Frames integriert, die in der X-Datei gespeichert sind.
Warum werden keine meiner Materialfarben mit Ausnahme von DirectXShaders angezeigt?
Die DirectX-Erweiterungen für Maya unterstützen derzeit nur DirectXShader-Materialien für Vorschau und Export. In einer zukünftigen Version können andere Materialien unterstützt werden.
XInput-Fragen
Kann ich DirectInput verwenden, um die Trigger zu lesen?
Ja, aber sie fungieren als dieselbe Achse. Sie können die Trigger also nicht unabhängig von DirectInput lesen. Bei Verwendung von XInput geben die Trigger separate Werte zurück.
Weitere Informationen dazu, warum DirectInput die Trigger als eine Achse interpretiert, finden Sie unter Verwenden des Controllers mit DirectInput.
Wie viele Controller unterstützt XInput?
XInput unterstützt jeweils vier angeschlossene Controller.
Unterstützt XInput nicht allgemeine Controller?
Nein, das ist nicht der Fall.
Sind gängige Controller über DirectInput verfügbar?
Ja, Sie können über DirectInput auf gängige Controller zugreifen.
Wie erzwinge ich Feedback zu den allgemeinen Controllern?
Verwenden Sie die XInputSetState-Funktion.
Warum ändert sich mein Standardaudiogerät?
Beim Anschließen des Headsets fungiert das Headset des Controllers als Standard-USB-Audiogerät. Wenn es angeschlossen ist, ändert sich Windows automatisch, um dieses USB-Audiogerät als Standard zu verwenden. Da der Benutzer wahrscheinlich nicht möchte, dass alle Audiodaten über das Headset gehen, muss er sie manuell an die ursprüngliche Einstellung anpassen.
Wie steuere ich die Lichter auf dem Controller?
Die Lichter auf dem Controller sind vom Betriebssystem vordefiniert und können nicht geändert werden.
Wie kann ich in meinen Anwendungen auf die Xbox 360-Schaltfläche zugreifen?
Diese Schaltfläche ist leider für die zukünftige Verwendung reserviert.
Wo bekomme ich Treiber?
Die Treiber werden über Windows Update verfügbar sein.
Wie wird die Controller-ID bestimmt?
Beim XInput-Start wird die ID nicht non-deterministisch vom XInput-Modul und den angeschlossenen Controllern bestimmt. Wenn Controller angeschlossen sind, während eine XInput-Anwendung ausgeführt wird, weist das System dem neuen Controller die niedrigste verfügbare Nummer zu. Wenn ein Controller getrennt ist, wird seine Nummer erneut verfügbar gemacht.
Wie erhalte ich die Audiogeräte für den Controller?
Verwenden Sie die XInputGetDSoundAudioDeviceGuids-Funktion. Details finden Sie unter „Ausführliche Informationen“.
Was sollte ich tun, wenn ein Controller nicht angeschlossen ist?
Wenn der Controller von einem Spieler verwendet wurde, sollten Sie das Spiel anhalten, bis der Controller wieder verbunden ist, und der Spieler eine Taste drückt, um zu signalisieren, dass er bereit ist, die Pause zu beenden.