編輯

共用方式為


DirectX 常見問題

本文包含關於 Microsoft DirectX 的常見問題 (FAQ) 集合。

一般 DirectX 開發問題

遊戲開發人員應該真正關心支援 x64 版本嗎?

當然 x64 技術在市場上廣泛使用。 過去幾年中銷售的大部分新 CPU,以及幾乎所有來自 AMD 和 Intel 開發的處理器線路,都具備 x64 功能。 Windows XP Professional x64 Edition 引進了 2005 年 4 月發行之 x64 的作業系統啟用技術。 因為 x64 版本需要新一代的 64 位原生驅動程式,因此第一個版本僅限於 OEM 發行版本。

透過 Windows Vista,客戶在購買 Windows 電腦時可以選擇 32 位或 64 位版本,而 Windows Vista 的授權適用于 32 位或 64 位版本的作業系統。 此外,在方塊中提供許多 64 位驅動程式,而且需要裝置製造才能同時提供 32 位和 64 位原生驅動程式,作為 Windows 認證計畫的一部分。

所有這些因素都會大幅增加 64 位版本的 Windows 部署。 當新的電腦開始運送超過 2 GB 的實體 RAM 時,使用 32 位作業系統的激勵大幅減少,有利於 64 位版本。 64 位技術完全支援 32 位機器碼,不過需要 64 位原生實作才能充分利用新的 64 位記憶體空間。 每個 32 位應用程式都應該有 64 位相容性作為最低出貨需求,且符合該需求是 Windows Vista 相容性的基準需求。 不相容通常是使用專為 Windows 3.1 作業系統設計的 16 位程式碼,或安裝 32 位和 64 位原生表單中未提供的驅動程式。

如需 64 位技術的詳細資訊,請參閱 遊戲開發人員 的 64 位程式設計。

遊戲開發人員應該仍在發佈適用于 Windows 95、Windows 98 或 Windows ME 的遊戲嗎?

不再有兩個原因:效能和功能集。

如果您的遊戲所需的最小 CPU 速度是 1.2GHz 或更新版本(這在高效能標題中更為常見),則絕大多數合格的電腦將會執行 Windows XP。 當 CPU 速度高於 1.2GHz 的電腦銷售時,幾乎所有制造商都會安裝 Windows XP 作為預設作業系統。 這表示 Windows XP 中發現許多功能,現今的遊戲開發人員應該利用包括:

  • 改善多工處理 - 這會導致視訊、音訊和遊戲的更好、更順暢的體驗。
  • 更穩定的視訊驅動程式模型 - 這可讓您更輕鬆地偵錯、更順暢的遊戲遊戲和更好的效能。
  • 網路設定更容易 - 這可讓您更輕鬆地存取多玩家遊戲。
  • 根據預設,支援硬碟的 DMA 傳輸 - 這會導致更順暢、更快速地載入應用程式。
  • Windows 錯誤報告 - 這會導致更穩定的 OS、驅動程式和應用程式。
  • Unicode 支援 - 大幅簡化當地語系化問題。
  • 更好的安全性和穩定性 - 這會導致更好的消費者體驗。
  • 較佳的新式硬體支援 - 大部分不再使用 Windows 98 驅動程式。
  • 改善的記憶體管理 - 這會導致更好的穩定性和安全性。
  • 改善的 NTFS 檔案系統 - 更能抗拒失敗,且具有較佳的安全性功能效能。

遊戲開發人員應該仍在發行適用于 Windows 2000 的遊戲嗎?

不必再如此。 除了遊戲開發人員是否仍發行適用于 Windows 95、Windows 98 或 Windows ME? 遊戲開發人員的原因 之外,Windows 2000 沒有這些功能:

  • Windows XP 支援進階處理器功能,例如 Hyper-Threading、Multi-Core 和 x64。
  • Windows XP 支援並存元件,可大幅減少應用程式版本控制衝突。
  • Windows XP 支援無執行記憶體保護,有助於防止惡意程式,並可協助偵錯。
  • Windows XP 已改善進階 AGP 和 PCI Express 型視訊卡的支援。
  • Windows XP 支援快速使用者切換、遠端桌面和遠端協助,可協助降低產品支援成本。
  • PIX 等效能工具(在 DirectX 開發人員 SDK 中)不再支援 Windows 2000。

簡言之,Windows 2000 從未設計或行銷為消費者作業系統。

各種 Windows Vista 版本之間的差異為何? 它們如何影響我的 DirectX 應用程式?

Windows Vista 系列包含五個版本:

  • Windows Vista Home Basic
  • Windows Vista Home Premium
  • Windows Vista Business
  • Windows Vista Enterprise
  • Windows Vista Ultimate

家用基本版和家庭進階版是消費者關注的版本,其功能如家庭保管庫(先前稱為家長監護),而家庭進階版包括媒體中心。 商務和企業是以公司為中心的版本,具有加入網域和遠端桌面/終端機服務等功能。 Ultimate 版本會將取用者和公司版的所有功能結合成一個版本。 所有版本都同時包含 32 位 (x86) 和 64 位 (x64) 版本,而且使用者可以同時針對這兩個平臺使用相同的產品識別碼。

各種版本的基礎技術相同,而且它們都有相同版本的 DirectX 執行時間和其他元件。 不過,這些版本在遊戲方面確實有些微差異:

  • 遊戲總管存在於所有版本上,但[開始] 功能表上的遊戲快捷方式只位於 Home Basic、Home 進階版 和 Ultimate 中。 遊戲總管仍可在所有版本上找到(按一下 [開始]、指向 [所有程式],然後按一下 [遊戲],以及所有版本的 IGameExplorer 介面函式。
  • 商務與企業版預設不提供隨附于 Windows 的遊戲,但可由系統管理員啟用。
  • 家庭保管庫和遊戲評等不會顯示或對商務或企業的行為有任何影響,而且當加入網域時,它們會在 Ultimate 上停用。

使用者帳戶控制設定在所有版本上都有相同的預設值,但可由商務、企業和 Ultimate 網域的群組原則設定覆寫。 例如,原則設定使用者帳戶控制:標準使用者提高許可權提示的行為可能設定為 [在許多商務設定中自動拒絕提高許可權要求] 來增強安全性,而且這些環境中的許多使用者一律會以標準使用者身分執行,甚至無法選擇以 管理員istrator 執行。 任何需要系統管理許可權的程式(例如安裝程式),無論是因為舊版安裝偵測或具有資訊清單,將要求的執行層級指定為「require管理員istrator」,一律無法在這類情況下啟動。 其他原則設定,例如使用者帳戶控制:只有提高已簽署和驗證的可執行檔許可權,如果您未使用 Authenticode 簽署可執行檔,也可以防止安裝程式正常運作。

這些類型的原則變更可以套用至任何版本的 Windows Vista,但更有可能在加入網域的電腦上。

各種 Windows 7 版本之間的差異為何? 它們如何影響我的 DirectX 應用程式?

大部分的 Windows 7 使用者可能會有兩種版本之一:Windows 7 家用進階版、適用于家庭使用者或Windows 7 專業版,適用于商務使用者和開發人員。 對於大型公司,有大量授權的 Windows 7 企業版 版本,其中包含所有 Windows 7 功能:Windows 7 旗艦版是該版本的零售對等專案。

Windows 7 簡易版版本可供 OEM 使用,且預期會以網簿、超低功率筆記本電腦為主部署。 Windows 7 家用入門版僅適用于新興市場。

請注意,所有 Windows 7 版本(除了 Starter Edition)都適用于 32 位 (x86) 和 64 位 (x64) 版本,而 Windows 7 的所有零售套件都包含這兩個版本的媒體。 如同 Windows Vista,使用者可以在任一平臺上使用相同的零售產品識別碼。

各種版本的基礎技術相同,而且所有版本都有相同版本的 DirectX 執行時間和其他元件。 在遊戲功能方面,它們確實有一些差異:

  • 遊戲總管存在於所有版本中,但[開始] 功能表上的遊戲快捷方式預設會隱藏在 Windows 7 專業版 和 Enterprise 中。 遊戲總管仍可在[開始] 功能表上找到(按一下 [所有程式],然後按兩下 [遊戲]),而直接遊戲快捷方式可由使用者啟用。
  • Windows 隨附的遊戲預設無法在 Windows 7 專業版 和 Enterprise 上使用,但可由系統管理員啟用。
  • 家庭保管庫和遊戲評等適用于所有版本,但是當作業系統加入網域時,Windows 7 專業版、Enterprise 和 Ultimate 會停用它們。 如同 Windows Vista Ultimate,這項功能可以在已加入網域的電腦上重新啟用。

使用者帳戶控制 (UAC) 設定可能會受到 Windows 7 專業版、Enterprise 和 Ultimate 版本的群組原則設定影響,這與 Windows Vista 非常類似。 如需詳細資訊,請參閱 各種 Windows Vista 版本之間的差異為何?它們如何影響我的 DirectX 應用程式?

DirectX 10 是否可供 Windows XP 使用?

否。 具有 DirectX 10 的 Windows Vista 包含以 Windows XP SP2 (DirectX 9.0c) 執行時間為基礎的更新 DirectX 執行時間,其中包含使用新的 Windows Display Driver Model (WDDM) 和新音訊驅動程式堆疊的變更,以及作業系統中的其他更新。 除了 Direct3D 9 之外,當有正確的視訊硬體和驅動程式時,Windows Vista 還支援兩個新的介面:Direct3D9Ex 和 Direct3D10。

由於這些新介面依賴 WDDM 技術,因此永遠不會在舊版 Windows 上使用。 對適用于 Windows Vista 的 DirectX 技術所做的所有其他變更,也專屬於新版本的 Windows。 DirectX 10 名稱在 DirectX SDK (XACT、XINPUT、D3DX) 中的許多技術並未包含于此版本號碼中。 因此,將 DirectX 執行時間的版本號碼視為整體已失去大部分的意義,即使是 9.0c。 Windows Vista 上的 DirectX 診斷工具 (DXdiag.exe) 會回報 DirectX 10,但這實際上只是指 Direct3D 10。

DirectX 11 是否適用于 Windows Vista 或 Windows XP?

DirectX 11 內建于 Windows 7 中,而且可作為 Windows Vista 的更新提供(請參閱 https://go.microsoft.com/fwlink/p/?linkid=160189 )。 這包括 Direct3D 11 API、DirectX 圖形基礎結構 (DXGI) 1.1、10Level9 功能層級、Windows 進階點陣化平臺 (WARP) 10 軟體轉譯裝置、Direct2D、DirectWrite,以及 Direct3D 10.1 API 的更新,以支援 10Level9 和 WARP 10。

基於上述問題中所述的相同原因( DirectX 10 是否適用于 Windows XP? ),Direct3D 11 和相關 API 無法在 Windows XP 上使用。

DirectShow 發生什麼事? 我在 DirectX SDK 中找不到它。

DirectShow 自 2005 年 4 月起已從 DirectX SDK 中移除。 您可以在 Windows 軟體發展工具組中取得 DirectShow 的標頭、程式庫、工具和範例(先前稱為平臺 SDK)。 DirectX SDK 中的 DirectSetup 會繼續支援 DirectShow 系統元件的轉散發,而且最新的元件已經安裝在下列作業系統上:Microsoft Windows XP Service Pack 2、Windows XP Professional x64 Edition、Windows Server 2003 Service Pack 1 和 Windows Vista。

已對 Windows Vista 的 DirectX 執行時間進行哪些變更?

已進行主要變更以支援新的 WDDM。 如需新驅動程式模型的詳細資料、Direct3D 9 的影響,以及兩個新的圖形介面 Direct3D 9Ex 和 Direct3D 10,請參閱 Windows 中的圖形 API。 適用于 Windows 7 的新圖形 API—Direct3D 11、Direct2D、DirectWrite、DXGI 1.1 和更新的 Direct3D 10.1—可作為 Windows Vista 的更新提供(請參閱 https://go.microsoft.com/fwlink/p/?linkid=160189 )。

Windows Vista Service Pack 1 包含 DirectX 執行時間的更新版本。 此更新可延伸 Windows Vista 的支援,以包含 Direct3D 10.1,公開新的選用硬體功能。 (能夠支援 Direct3D 10.1 的所有硬體也完全支援 Direct3D 10 的所有功能。

DirectSound 已更新,以公開新的 Windows Vista 音訊驅動程式堆疊功能,其支援多通道軟體緩衝區。 Direct3D 保留模式 API 已從 Windows Vista 完全移除。 DirectPlay Voice 也已移除,以及 DirectPlay 的 NAT 協助程式和 DirectInput 的 action-mapper UI。 Windows Vista 不提供 Visual Basic 6.0 的 DirectX 7 和 DirectX 8 介面支援。

對 Windows 7 的 DirectX 執行時間進行了哪些變更?

Windows 7 包含 Windows Vista 中找到的所有 DirectX 執行時間元件,並新增 Direct3D 11、DXGI 1.1、10Level9 功能層級、WARP10 軟體裝置、Direct2D、DirectWrite,以及 Direct3D 10.1 更新以支援 10Level9 和 WARP10。 如需詳細資訊,請參閱 Windows 中的圖形 API。

所有其他元件都與 Windows Vista 相同,並新增與時間戳記 MIDI 相關的核心 DirectMusic API 的 64 位 (x64) 原生支援。 DirectMusic 的效能層級仍然已被取代,而且它僅適用于 Windows 7 上的 32 位應用程式,以取得應用程式相容性。 請注意,Windows Vista 上不提供 DirectMusic 的 64 位原生支援。

我想我找到了一個驅動程式錯誤, 我該怎麼做?

首先,請確定您已使用參考轉譯器檢查結果。 然後使用最新 WHQL 認證的 IHD 驅動程式版本來檢查結果。 您可以在傳遞D3DENUM_WHQL_LEVEL旗標的 IDirect3D9 介面上使用 GetAdapterIdentifier() 方法來以程式設計方式檢查 WHQL 狀態。

當我嘗試編譯範例時,為什麼會收到這麼多錯誤訊息?

您可能沒有正確設定 Include 路徑。 許多編譯器,包括 Microsoft Visual C++,包含舊版的 SDK,因此,如果您的 Include 路徑先搜尋標準編譯器包含目錄,您會收到不正確的標頭檔版本。 若要解決此問題,請確定 Include 路徑和程式庫路徑已設定為先搜尋 Microsoft DirectX include 和程式庫路徑。 另請參閱 SDK 中的 dxreadme.txt 檔案。 如果您安裝 DirectX SDK 並使用 Visual C++,安裝程式可以選擇性地為您設定 Include 路徑。

我收到全域唯一識別碼之多個或遺漏符號的連結器錯誤,我該怎麼做?

您使用的各種 GUID 應該定義一次,而且只能定義一次。 如果您在包含 DirectX 標頭檔之前 #define INITGUID 符號,則會插入 GUID 的定義。 因此,您應該確定這只會針對一個編譯單位發生。 此方法的替代方法是連結 dxguid.lib 程式庫,其中包含所有 DirectX GUID 的定義。 如果您使用此方法(建議使用),則絕對不應該 #define INITGUID 符號。

我可以將指標轉換成較低版本號碼的 DirectX 介面嗎?

否。 DirectX 介面是 COM 介面。 這表示不需要從相對應的較低編號介面衍生較高編號的介面。 因此,取得 DirectX 物件不同介面的唯一安全方法是使用 介面的 QueryInterface 方法。 此方法是標準 IUnknown 介面的一部分,所有 COM 介面都必須從中衍生。

我可以在相同應用程式中混合使用 DirectX 9 元件和 DirectX 8 或更早的元件嗎?

您可以自由混合不同版本的不同元件;例如,您可以在相同的應用程式中搭配 Direct3D 9 使用 DirectInput 8。 不過,您通常無法混合相同應用程式內相同元件的不同版本;例如,您無法將 DirectDraw 7 與 Direct3D 9 混用(因為這些元件實際上與 DirectDraw 一樣,已從 DirectX 8 開始被細分為 Direct3D)。 不過,有例外狀況,例如在同一個應用程式中同時使用 Direct3D 9 和 Direct3D 10,這是允許的。

我可以在相同的應用程式中混合使用 Direct3D 9 和 Direct3D 10 嗎?

是,您可以在相同的應用程式中使用這些版本的 Direct3D。

Release 或 AddRef 方法的傳回值代表什麼意思?

傳回值將是 物件的目前參考計數。 不過,COM 規格指出您不應該依賴此專案,而且值通常僅供偵錯之用。 您觀察到的值可能會非預期,因為其他各種系統物件可能會保存您所建立之 DirectX 物件的參考。 基於這個理由,在參考計數為零之前,您不應該撰寫重複呼叫 Release 的程式碼,因為即使另一個元件仍可能仍在參考該物件,也可以釋放物件。

我發行 DirectX 介面的順序為何?

因為會計算 COM 介面的參考,所以不應該重要。 不過,某些版本的 DirectX 中介面發行順序有一些已知的 Bug。 為了安全起因,建議您盡可能以反向建立順序釋放介面。

什麼是智慧型指標,我應該使用它?

智慧型指標是 C++ 樣板類別,其設計目的是封裝指標功能。 特別是,有標準智慧型指標類別設計來封裝 COM 介面指標。 這些指標會自動執行 QueryInterface,而不是轉換,而且會為您處理 AddRef 和 Release。 你是否應該使用它們在很大程度上是味道的問題。 如果您的程式碼包含許多介面指標的複製,且有多個 AddRefs 和 Releases,則智慧型指標可能會讓您的程式碼更整潔且較不容易出錯。 否則,您可以不需要它們。 Visual C++ 包含標準 Microsoft COM 智慧型指標,定義于 「comdef.h」 標頭檔中(查閱說明中的com_ptr_t)。

我在對 DirectX 應用程式進行偵錯時遇到問題,是否有任何秘訣?

偵錯 DirectX 應用程式最常見的問題是在鎖定 DirectDraw 介面時嘗試偵錯。 這種情況可能會導致 Microsoft Windows 9x 系統上的「Win16 鎖定」,這可防止偵錯工具視窗繪製。 鎖定介面時指定D3DLOCK_NOSYSLOCK旗標通常可以消除此情形。 Windows 2000 不會發生此問題。 開發應用程式時,使用 DirectX 執行時間的偵錯版本執行會很有用(當您安裝 SDK 時選取),這會執行一些參數驗證,並將有用的訊息輸出至偵錯工具輸出。

檢查傳回碼的正確方式為何?

使用 SUCCEEDED 和 FAILED 宏。 DirectX 方法可以傳回多個成功和失敗碼,因此很簡單:

== D3D_OK

或類似的測試不一定足夠。

如何?停用 ALT+TAB 和其他工作切換?

你不! 遊戲必須能夠正常地處理工作切換,因為許多事情會導致它發生:ALT+TAB、遠端桌面連線、快速使用者切換、家長監護使用限制,以及其他許多事件。

同時,使用鍵盤中心控制配置在遊戲上切換意外工作的兩個常見來源是按下 Windows 標誌鍵,並使用 SHIFT 鍵啟用協助工具功能 StickyKeys。 若要停用功能來解決這些情況,請參閱在遊戲 中停用快速鍵中所述 的技術。

是否有建議的書籍說明 COM?

由 Microsoft Press 出版的 Dale Rogerson 內部 COM 是 COM 的絕佳簡介。 如需更詳細的 COM 研究,朗曼出版的《基本 COM by Don Box》一書 也強烈建議您。

什麼是 Managed 程式碼?

Managed 程式碼是由 .NET Framework Common Language Runtime (CLR) 所管理其執行的程式碼。 它是指原生執行程式碼與執行時間之間的合作合約。 此合約指定在任何執行時間點,執行時間可能會停止執行 CPU,並擷取目前 CPU 指令位址的特定資訊。 必須能夠查詢的資訊通常與執行時間狀態有關,例如暫存器或堆疊記憶體內容。

執行程式碼之前,IL 會編譯成原生可執行程式碼。 而且,由於此編譯是由 Managed 執行環境所發生(或更正確地,由知道如何以 Managed 執行環境為目標的執行時間感知編譯器),因此受控執行環境可以保證程式碼將執行的動作。 它可以插入陷阱和適當的垃圾收集攔截、例外狀況處理、型別安全、陣列界限和索引檢查等等。 例如,這類編譯器可確保配置堆疊框架和一切正確,讓垃圾收集行程可以在個別執行緒的背景中執行,不斷走動作用中的呼叫堆疊,尋找所有根目錄,追查所有即時物件。 此外,由於 IL 有型別安全性的概念,因此執行引擎將維持型別安全性的保證,從而消除一系列通常會導致安全性漏洞的程式設計錯誤。

與此非受控世界相反:非受控可執行檔基本上是載入記憶體的二進位映射 x86 程式碼。 程式計數器會放在該處,這是 OS 知道的最後一個。 記憶體管理和埠 I/O 等都有保護,但系統實際上並不知道應用程式正在做什麼。 因此,它無法保證應用程式執行時會發生什麼事。

關於一般 Windows 程式設計有哪些書籍?

很多。 不過,強烈建議使用下列兩項:

  • Charles Petzold 的程式設計 Windows (Microsoft Press)
  • Jeffrey Richter 適用于 Windows 的程式設計應用程式 (Microsoft Press)

如何?使用 Windows 符號檔進行偵錯?

Microsoft 發佈所有系統 DLL 的等量符號(加上一些其他專案)。 若要存取它們,請將下列內容新增至 Visual Studio 內專案設定中的符號路徑:

srv*https://msdl.microsoft.com/download/symbols

若是本機快取符號,請使用下列語法:

srv*c:\cache*https://msdl.microsoft.com/download/symbols

其中 c:\cache 是用於快取符號檔的本機目錄。

Direct3D 問題

一般 Direct3D 問題

哪裡可以找到 3D 圖形技術的相關資訊?

該主題的標準書是電腦圖形:弗利的原則和實踐,范達姆等。對於任何想要瞭解幾何、點陣化和光源技術數學基礎的人來說,這是一個寶貴的資源。 comp.graphics.algorithms Usenet 群組的常見問題也包含實用的資料。

Direct3D 是否模擬硬體未提供的功能?

要看情況而定。 Direct3D 具有功能完整的軟體頂點處理管線(包括自訂頂點著色器的支援)。 不過,不會針對圖元層級作業提供模擬;應用程式必須檢查適當的上限位,並使用 ValidateDevice API 來判斷支援。

Direct3D 是否包含軟體轉譯器?

不適用於效能應用程式。 參考轉譯器會針對驅動程式驗證提供,但實作是針對精確度而非效能所設計。 Direct3D 支援外掛程式軟體轉譯程式。

如何使用 DirectX 圖形執行色彩索引鍵?

色彩索引鍵不直接支援,相反地,您必須使用 Alpha 混合來模擬色彩索引鍵。 D3DXCreateTextureFromFileEx() 函式可用來協助進行這項作業。 此函式會接受索引鍵色彩參數,並將來源影像中的所有圖元取代為所建立紋理中透明黑色圖元的指定色彩。

Direct3D 幾何程式碼是否使用 3DNow! 和/或 Pentium III SIMD 指示?

是。 Direct3D 幾何管線有數個不同的程式碼路徑,視處理器類型而定,它會利用 3DNow 所提供的特殊浮點運算! 或 Pentium III SIMD 指示,這些指示可供使用。 這包括處理自訂頂點著色器。

如何?防止將透明圖元寫入 z 緩衝區?

您可以使用高於或低於指定閾值的 Alpha 值來篩選出圖元。 您可以使用 renderstates ALPHATESTENABLE、ALPHAREF 和 ALPHAFUNC 來控制此行為。

什麼是樣板緩衝區?

樣板緩衝區是每個圖元資訊的額外緩衝區,與 z 緩衝區非常類似。 事實上,它位於 z 緩衝區的一些位。 常見的樣板/z 緩衝區格式為 15 位 z 和 1 位樣板,或 24 位 z 和 8 位樣板。 在轉譯多邊形時,可以針對每個圖元的樣板緩衝區內容執行簡單的算數運算。 例如,樣板緩衝區可以遞增或遞減,或者如果樣板值失敗,則可以拒絕圖元。 這適用于涉及標記框架緩衝區區域,然後只執行轉譯標示 (或未標記) 區域的效果。 良好的範例是陰影磁片區之類的體積效果。

如何?使用樣板緩衝區來轉譯陰影磁片區?

這個和其他體積樣板緩衝區效果的索引鍵是樣板緩衝區與 z 緩衝區之間的互動。 具有陰影磁片區的場景會以三個階段呈現。 首先,不使用陰影的場景會像往常一樣轉譯,使用 z 緩衝區。 接下來,陰影會標示在樣板緩衝區中,如下所示。 陰影磁片區的正面會使用不可見的多邊形繪製,並啟用 z 測試但停用 z 寫入,並在通過 z 測試的每個圖元上遞增樣板緩衝區。 陰影磁片區的背面會以類似的方式轉譯,但改為遞減樣板值。

現在,請考慮單一圖元。 假設相機不在陰影音量中,場景中對應的點有四種可能性。 如果相機到該點的光線沒有與陰影音量交集,則不會在那裡繪製任何陰影多邊形,樣板緩衝區仍然為零。 否則,如果點位於陰影磁片區前方,陰影多邊形會經過 z 緩衝處理,而且樣板會再次維持不變。 如果點位於陰影磁片區後面,則呈現與背面臉部相同的正面陰影臉部數目,樣板將會是零,遞減次數會遞增。

最後的可能性是點位於陰影卷內。 在此情況下,陰影磁片區的後臉會經過 z 緩衝處理,但不是正面,因此樣板緩衝區將是非零值。 結果是陰影中框架緩衝區的一部分具有非零樣板值。 最後,為了實際呈現陰影,整個場景會以 Alpha 混合多邊形來洗過,只影響非零樣板值的圖元。 在 DirectX SDK 隨附的「陰影磁片區」範例中,可以看到這項技術的範例。

什麼是紋素對齊規則? 如何?取得一對一對應嗎?

這在 Direct3D 9 檔中已完整說明。 不過,執行摘要是您應該將螢幕座標偏差為 -0.5 圖元,以便與紋素正確對齊。 大部分卡片現在都符合紋素對齊規則,不過有些較舊的卡片或驅動程式沒有。 若要處理這些案例,最好的建議是連絡有問題的硬體廠商,並要求更新的驅動程式或其建議的因應措施。 請注意,在 Direct3D 10 中,此規則不再保留。

D3DCREATE\_PUREDEVICE 旗標的用途為何?

在裝置建立期間使用D3DCREATE_PUREDEVICE旗標來建立純裝置。 純裝置不會儲存目前的狀態(在狀態變更期間),這通常會改善效能;此裝置也需要硬體頂點處理。 當開發和偵錯完成時,通常會使用純裝置,而您想要達到最佳效能。

純裝置的其中一個缺點是它不支援所有 Get* API 呼叫;這表示您無法使用純裝置來查詢管線狀態。 如此一來,在執行應用程式時就更難進行偵錯。 以下是由純裝置停用的所有方法清單。

純裝置的第二個缺點是它不會篩選任何備援狀態變更。 使用純裝置時,您的應用程式應將轉譯迴圈中的狀態變更數目減少為最小值;這可能包括篩選狀態變更,以確保狀態不會多次設定。 此取捨與應用程式相依;如果您使用每個畫面的 1000 個以上的 Set 呼叫,您應該考慮利用非純裝置自動完成的備援篩選。

與所有效能問題一樣,瞭解應用程式是否使用純裝置執行效能的唯一方式,就是比較應用程式的效能與純裝置與非純裝置。 純裝置有可能藉由減少 API 的 CPU 額外負荷來加速應用程式。 但請小心! 在某些情況下,純裝置會降低應用程式的速度(因為額外的 CPU 工作因備援狀態變更所造成)。 如果您不確定哪種類型的裝置最適合您的應用程式,而且您不會篩選應用程式中的備援變更,請使用非純裝置。

如何?列舉多監視器系統中的顯示裝置?

列舉可以透過應用程式使用 IDirect3D9 介面的方法,透過簡單的反復專案來執行。 呼叫 GetAdapterCount 以判斷系統中的顯示配接器數目。 呼叫 GetAdapterMonitor 以判斷介面卡所連接的實體監視器(這個方法會傳回 HMONITOR,然後您可以在 WIN32 API GetMonitorInfo 中用來判斷實體監視器的相關資訊)。 判斷特定顯示器介面卡或在該介面卡上建立 Direct3D 裝置的特性,就像在呼叫 GetDeviceCaps、CreateDevice 或其他方法時傳遞適當的配接器號碼來取代D3DADAPTER_DEFAULT一樣簡單。

D3D9 中的固定函式凸起對應發生什麼事?

從 Direct3D 9 起,我們在卡片上加強了驗證,該卡片只能支援 > 2 個同時紋理。 當您使用特定的 Alpha 調變運算時,某些較舊的卡片只有 3 個紋理階段可用。 人們最常使用 3 個階段的用法是浮凸凸凸度圖,您仍然可以使用 D3D9 來執行此動作。

高度欄位必須儲存在 Alpha 色板中,並用來調整燈光貢獻,也就是:

// 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 );
}

此範例和其他較舊的範例不再隨附于目前的 SDK 版本中,且不會在未來的 SDK 版本中出貨。

幾何 (頂點) 處理

頂點串流會混淆我如何運作?

Direct3D 會從一或多個頂點串流將管線處理部分饋送至每個頂點。 只有一個頂點資料流程對應到舊的 DirectX 8 模型,其中頂點來自單一來源。 使用 DirectX 8 時,不同的頂點元件可能來自不同來源;例如,一個頂點緩衝區可以保留位置和常態,而第二個頂點緩衝區則保留色彩值和紋理座標。

什麼是頂點著色器?

頂點著色器是處理單一頂點的程式。 它是使用由 D3DX 公用程式程式庫組合成 Direct3D 接受之權杖資料流程的簡單類似元件語言所定義。 頂點著色器接受輸入單一頂點和一組常數值;它會輸出頂點位置(在剪輯空間中),並選擇性地輸出一組色彩和紋理座標,用於點陣化。 請注意,當您有自訂頂點著色器時,頂點元件不再由 Direct3D 套用任何語意,頂點只是您所建立頂點著色器所解譯的任意資料。

頂點著色器是否執行透視除法或裁剪?

否。 頂點著色器會在裁剪空間中輸出已轉換頂點位置的同質座標。 檢視方塊除法和裁剪會自動在著色器後執行。

我可以使用頂點著色器產生幾何嗎?

頂點著色器無法建立或終結頂點;它會一次在單一頂點上運作,以一個未處理的頂點作為輸入,並輸出單一處理的頂點。 因此,它可以用來操作現有的幾何(套用變形或執行皮膚作業),但實際上無法產生新的幾何本身。

我可以將自訂頂點著色器套用至固定函式幾何管線的結果(反之亦然)嗎?

否。 您必須選擇一個或另一個。 如果您使用自訂頂點著色器,您必須負責執行整個頂點轉換。

如果我的硬體不支援,可以使用自訂頂點著色器嗎?

是。 Direct3D 軟體頂點處理引擎完全支援具有令人驚訝的高效能自訂頂點著色器。

如何?判斷硬體是否支援我的自訂頂點著色器?

需要能夠支援硬體頂點著色器的裝置,才能填寫D3DCAPS9::VertexShaderVersion 欄位,以指出其支援的頂點著色器版本層級。 任何聲稱支援特定層級頂點著色器的裝置都必須支援符合該層級或低於該層級規格的所有合法頂點著色器。

頂點著色器可以使用多少常數暫存器?

支援 1.0 頂點著色器的裝置至少需要支援 96 個常數暫存器。 裝置可能支援超過此最小數目,而且可以透過 [D3DCAPS9::MaxVertexShaderConst] 欄位回報此專案。

我可以使用不同的紋理座標在頂點之間共用位置資料嗎?

這種情況的一般範例是一個立方體,您想要針對每個臉部使用不同的紋理。 不幸的是,答案是否,目前無法獨立編制頂點元件的索引。 即使有多個頂點資料流程,所有資料流程都會一起編制索引。

當我提交基本類型的索引清單時,Direct3D 是否會處理緩衝區中的所有頂點,或只處理我編制索引的頂點?

使用軟體幾何管線時,Direct3D 會先轉換您提交範圍中的所有頂點,而不是在編制索引時「視需要」轉換頂點。 對於密集封裝的資料(也就是使用大部分頂點的位置),這會更有效率,尤其是在 SIMD 指令可供使用時。 如果您的資料被疏鬆包裝(也就是未使用許多頂點),則您可能想要考慮重新排列資料,以避免太多多餘的轉換。 使用硬體幾何加速時,頂點通常會視需要視需要轉換。

什麼是索引緩衝區?

索引緩衝區與頂點緩衝區完全相同,但會包含用於 DrawIndexedPrimitive 呼叫的索引。 強烈建議您使用索引緩衝區,而不是盡可能使用原始應用程式佈建的記憶體,因為與頂點緩衝區相同。

我注意到 32 位索引是支援的型別;我可以在所有裝置上使用它們嗎?

否。 您必須檢查 [D3DCAPS9::MaxVertexIndex] 欄位,以判斷裝置支援的索引值上限。 此值必須大於 2 到第 16 個電源 -1 (0xffff),才能支援類型為 D3DFMT_INDEX32的索引緩衝區。 此外,請注意,某些裝置可能支援 32 位索引,但支援小於 2 到第 32 個電源 -1 的最大索引值(0xffffffff):在此情況下,應用程式必須遵守裝置所報告的限制。

S/W 頂點處理是否支援 64 位?

x64 有優化的 s/w 頂點管線,但 IA64 不存在。

效能微調

如何改善 Direct3D 應用程式的效能?

以下是優化效能時要探討的重要領域:

批次大小

Direct3D 已針對大量基本類型進行優化。 單一呼叫中可以傳送的多邊形越多,越好。 良好的經驗法則是的目標是每個基本呼叫平均 1000 個頂點。 低於該層級,您可能不會獲得最佳效能,高於該層級,而且您正因並行考慮而減少傳回和潛在的衝突(請參閱下方)。

狀態變更

變更轉譯狀態可能是昂貴的作業,特別是在變更紋理時。 基於這個理由,請務必盡可能減少每個畫面所做的狀態變更數目。 此外,請嘗試將頂點或索引緩衝區的變更降到最低。

注意

自 DirectX 8 起,變更頂點緩衝區的成本已不再像舊版一樣昂貴,但最好盡可能避免頂點緩衝區變更。

 

併發

如果您可以安排與其他處理同時執行轉譯,則您將充分利用系統效能。 此目標可能會與減少轉譯狀態變更的目標衝突。 您需要在批次處理之間取得平衡,以減少狀態變更,並提前將資料推送至驅動程式,以協助達成並行。 以迴圈配置資源方式使用多個頂點緩衝區有助於平行存取。

紋理上傳

將紋理上傳至裝置會耗用頻寬,並導致與頂點資料的頻寬競爭。 因此,請務必不要過度認可紋理記憶體,這會強制快取配置在每個畫面上傳過多的紋理。

頂點和索引緩衝區

您應該一律使用頂點和索引緩衝區,而不是應用程式佈建記憶體的一般區塊。 頂點和索引緩衝區的鎖定語意至少可以避免重複複製作業。 使用某些驅動程式時,頂點或索引緩衝區可能會放在更理想的記憶體中(可能位於視訊或 AGP 記憶體中),以供硬體存取。

狀態宏區塊

這些是在 DirectX 7.0 中引進的。 它們提供將一系列狀態變更(包括光源、材質和矩陣變更)錄製到宏的機制,然後可由單一呼叫重新執行。 這有兩個優點:

  • 您可以藉由撥打一個呼叫而不是許多來減少通話額外負荷。
  • 感知驅動程式可以預先剖析並預先編譯狀態變更,使其更快速地提交至圖形硬體。

狀態變更仍然可能很昂貴,但使用狀態宏可協助降低至少部分成本。 只使用單一 Direct3D 裝置。 如果您需要轉譯為多個目標,請使用 SetRenderTarget。 如果您要建立具有多個 3D 視窗的視窗化應用程式,請使用 CreateAdditionalSwapChain API。 執行時間已針對單一裝置進行優化,使用多個裝置的速度會大幅降低。

我應該使用哪一種基本類型(帶狀、粉絲、清單等等?

在多個多邊形共用的實際資料特徵頂點中遇到許多網格。 若要將效能最大化,最好減少轉換頂點中的重複,並透過匯流排傳送至轉譯裝置。 很明顯,使用簡單的三角形清單不會實現頂點共用,使其成為最不理想的方法。 接著,選擇是在使用帶狀和風扇之間,這表示多邊形與使用索引清單之間的特定連線關聯性。 資料自然落在帶狀和風扇的位置,這些都是最適當的選擇,因為它們會將傳送至驅動程式的資料降到最低。 不過,將網格分解成帶狀結構,風扇通常會產生大量的個別片段,這表示大量的 DrawPrimitive 呼叫。 因此,最有效率的方法通常是使用具有三角形清單的單一 DrawIndexedPrimitive 呼叫。 使用索引清單的另一個優點是,即使連續三角形只共用單一頂點,也能獲得好處。 總而言之,如果您的資料自然落入大型條紋或風扇,請使用帶狀或風扇;否則,請使用索引清單。

如何判斷卡片擁有的紋理記憶體總計,但不包括 AGP 記憶體?

IDirect3DDevice9::GetAvailableTextureMem 會傳回可用記憶體總數,包括 AGP。 根據假設您擁有多少視訊記憶體來配置資源並不是一個好主意。 例如,如果卡片是在整合記憶體架構 (UMA) 下執行,或能夠壓縮紋理,該怎麼辦? 可用的空間可能比您想像的要多。 您應該建立資源,並檢查是否有「記憶體不足」錯誤,然後在紋理上相應縮小。 例如,您可以移除紋理的最上層 Mip 層級。

如果我產生動態資料,頂點緩衝區的使用模式為何?

  1. 使用D3DUSAGE_DYNAMIC和D3DUSAGE_WRITEONLY使用旗標和D3DPOOL_DEFAULT集區旗標來建立頂點緩衝區。 (如果您使用的是軟體頂點處理,也請指定D3DUSAGE_SOFTWAREPROCESSING。
  2. I = 0。
  3. 設定狀態(紋理、轉譯狀態等等)。
  4. 檢查緩衝區中是否有空格,例如 I + M < = N? (其中 M 是新頂點的數目)。
  5. 如果是,請使用 D3DLOCK_NOOVERWRITE 鎖定 VB。 這會告知 Direct3D 和驅動程式您要新增頂點,而且不會修改您先前批次處理過的頂點。 因此,如果 DMA 作業正在進行中,就不會中斷。 如果沒有,請移至 11。
  6. 在 I 填入 M 頂點。
  7. 解 鎖。
  8. 呼叫 Draw[Indexed]Primitive。 對於未編制索引的基本類型,請使用 I 作為 StartVertex 參數。 針對已編制索引的基本類型,請確定索引指向頂點緩衝區的正確部分(可能最簡單的方式是使用 SetIndices 呼叫的 BaseVertexIndex 參數來達成此目的)。
  9. I += M。
  10. Goto 3.
  11. 好吧,所以我們空間不足,所以讓我們從新的 VB 開始。 我們不想使用相同的作業,因為可能有 DMA 作業進行中。 我們會使用 D3DLOCK_DISCARD 旗標鎖定相同的 VB,來與 Direct3D 和驅動程式通訊。 這意味著「你可以給我一個新的指標,因為我完成了舊的指標,不要真正關心舊內容。
  12. I = 0。
  13. Goto 4 (或 6)。

為什麼我必須指定D3DVERTEXELEMENT9結構中的詳細資訊?

自 Direct3D 9 起,頂點資料流程宣告不再是 DWORD 陣列,它現在是D3DVERTEXELEMENT9結構的陣列。 執行時間會利用額外的語意和使用方式資訊,將頂點資料流程的內容系結至頂點著色器輸入暫存器/變數。 對於 Direct3D 9,頂點宣告會與頂點著色器分離,這可讓您更輕鬆地使用具有不同格式的著色器,因為執行時間只會系結著色器所需的資料。

新的頂點宣告可以搭配固定函式管線或著色器使用。 針對固定函式管線,不需要呼叫 SetVertexShader。 不過,如果您想要切換至固定函式管線,且先前已使用頂點著色器,請呼叫 SetVertexShader(Null)。 完成此動作之後,您仍然需要呼叫 SetFVF 來宣告 FVF 程式碼。

使用頂點著色器時,請使用頂點著色器物件呼叫 SetVertexShader。 此外,請呼叫 SetFVF 來設定頂點宣告。 這會使用 FVF 中隱含的資訊。 您可以呼叫 SetVertexDeclaration 來取代 SetFVF,因為它支援無法使用 FVF 表示的頂點宣告。

D3DX 公用程式程式庫

D3DX 影像檔載入器函式支援哪些檔案格式?

D3DX 影像檔載入器函式支援 BMP、TGA、JPG、DIB、PPM 和 DDS 檔案。

D3DX 中的文字轉譯函式似乎無法運作,我做錯了什麼?

使用 ID3DXFont::D rawText 函式時常見的錯誤是指定色彩參數的零 Alpha 元件;導致完全透明 (也就是看不見) 文字。 對於完全不透明的文字,請確定色彩參數的 Alpha 元件已完全飽和 (255)。

如何將表面或紋理的內容儲存至檔案?

DirectX 8.1 SDK 已特別針對此目的將兩個函式新增至 D3DX 程式庫:D3DXSaveSurfaceToFile() 和 D3DXSaveTextureToFile()。 這些函式支援以 BMP 或 DDS 格式將影像儲存至檔案。 在舊版中,您必須鎖定表面並讀取影像資料,然後將它寫入點陣圖檔案。 如需撰寫函式來儲存點陣圖的資訊,請參閱 儲存影像

或者,GDI+ 可以用來以各種不同的格式儲存影像,不過這需要額外的支援檔案才能與您的應用程式一起散發。

如何在我的遊戲中使用高階著色器語言 (HLSL?

Microsoft 高階著色器語言 (HLSL) 有三種方式可以併入您的遊戲引擎:

  • 將您的著色器來源編譯為頂點或圖元網底元件(使用命令列公用程式 fxc.exe),並在執行時間使用 D3DXAssembleShader()。 如此一來,即使是 DirectX 8 遊戲甚至可以利用 HLSL 的強大功能。
  • 使用 D3DXCompileShader() 將您的著色器來源編譯成權杖資料流程和常數資料表表單。 在執行時間載入權杖資料流程和常數資料表,並在裝置上呼叫 CreateVertexShader() 或 CreatePixelShader()來建立著色器。
  • 啟動並執行的最簡單方式是透過使用效果檔案呼叫 D3DXCreateEffectFromFile() 或 D3DXCreateEffectFromResource() 來利用 D3DX 效果系統。

新著色器編譯器旗標的用途為何?

從 2006 年 12 月 DirectX SDK 開始,針對 Direct3D 10 開發的新 HLSL 編譯器已針對 Direct3D 9 目標啟用。 新的編譯器不支援ps_1_x目標,而且現在是所有 Direct3D HLSL 著色器的預設編譯器。 回溯相容性的旗標可用來強制ps_1_x目標編譯為ps_2_0目標。

想要使用舊版編譯器的應用程式可以在執行時間提供旗標來繼續執行此作業(請參閱 編譯器旗 標),或使用 fxc 時提供參數。

從效果取得著色器的正確方式為何?

使用 D3DXCreateEffect 建立 ID3DXEffect,然後使用 GetPassDesc 擷取D3DXPASS_DESC。 此結構包含頂點和圖元著色器的指標。

請勿使用 ID3DXEffectCompiler::GetPassDesc。 從此方法傳回的頂點和圖元著色器控制碼為 Null。

HLSL 雜訊() 內建的用途為何?

雜訊內建函式會產生 Ken Perlin 所定義的 Perlin 雜訊。 HLSL 函式目前只能用來在紋理著色器中填滿紋理,因為目前的 h/w 不支援原生方法。 紋理著色器會與 D3DXFill*Texture() 函式搭配使用,這是有用的協助程式函式,以在載入期間產生程式定義的紋理。

如何?偵測是否要使用圖元著色器模型 2.0 或 2.a?

您可以使用 D3DXGetPixelShaderProfile() 和 D3DXGetPixelShaderProfile() 函式,其會傳回字串來判斷哪些 HLSL 設定檔最適合執行裝置。

如何?存取預先編譯效果著色器中的參數?

透過 ID3DXConstantTable 介面,用來存取常數資料表。 下表包含高層級語言著色器和效果所使用的變數。

是否有辦法將使用者資料新增至效果或其他資源?

是,若要設定您呼叫 SetPrivateData 的私人資料(pReal 是 D3D 紋理物件,pSpoof 是包裝的紋理物件)。

hr = pReal->SetPrivateData(IID_Spoof, &pSpoof, 
            sizeof(IDirect3DResource9*), 0)));

若要查閱包裝的指標:

    IDirect3DResource9* pSpoof;
    DWORD dwSize = sizeof(pSpoof);
    hr = pReal->GetPrivateData(IID_Spoof, (void*) &pSpoof, &dwSize);

為什麼在定義子集之後,ID3DXMesh 物件的轉譯速度會大幅降低?

在定義臉部屬性之後,您可能尚未優化網格。 如果您指定屬性,然後呼叫 ID3DXMesh::D rawSubset(),這個方法必須針對包含所要求屬性的所有臉部執行網格搜尋。 此外,轉譯的臉部可能處於隨機存取模式,因此不會使用頂點快取。 定義子集的臉部屬性之後,請呼叫 ID3DXMesh::Optimize 或 ID3DXMesh::OptimizeInPlace 方法,並指定D3DXMESHOPT_ATTRSORT或更強的優化方法。 請注意,為了獲得最佳效能,您應該使用 D3DXMESHOPT_VERTEXCACHE 旗標進行優化,這也會重新排序頂點,以獲得最佳頂點快取使用率。 針對 D3DX Mesh 所產生的相鄰陣列每個臉部有三個專案,但有些臉部可能沒有三個邊緣的相鄰臉部。 此編碼方式如何? 沒有相鄰臉部的專案會編碼為0xffffffff。

我聽到了很多關於預先計算輻射傳輸 (PRT), 我可以在哪裡深入瞭解?

PRT 是 D3DX 在 2003 年夏季 SDK 更新中新增的新功能。 它可讓您即時呈現複雜的光源案例,例如全域 -llumination、軟陰影和子表面散佈。 SDK 包含如何將技術整合到遊戲的檔和範例。 PRT 示範範例和 LocalDeformablePRT 範例範例會示範如何分別針對每個頂點和每個圖元光源案例使用模擬器。 如需此主題和其他主題的詳細資訊,請參閱彼得·派克·斯隆的網頁。

如何轉譯為紋理並使用反鋸齒?

使用 Direct3DDevice9::CreateRenderTarget 建立多重取樣轉譯目標。 將場景轉譯為該轉譯目標之後,StretchRect 會從它轉譯到轉譯目標紋理。 如果您對螢幕外文字進行任何變更(例如模糊或開花),請先將它複製到背景緩衝區,再呈現()。

DirectSound 問題

為什麼當我的應用程式啟動時,我會收到靜態的暴增? 我也注意到其他應用程式發生這個問題。

您可能已安裝偵錯 DirectX 執行時間。 執行時間的偵錯版本會以靜態填滿緩衝區,以協助開發人員使用未初始化的緩衝區攔截 Bug。 您無法保證建立後 DirectSound 緩衝區的內容;特別是,您無法假設具有 的緩衝區已歸零。

為什麼我在變更效果參數和聽到結果之間遇到延遲?

效果參數的變更不一定會在 DirectX 8 上立即發生。 為了提高效率,DirectSound 會在緩衝區中處理 100 毫秒的聲音資料,從播放游標開始,再播放緩衝區。 此前置處理會在下列所有呼叫之後發生:

IDirectSoundBuffer8::SetCurrentPosition
IDirectSoundBuffer8::SetFX
IDirectSoundBuffer8::Stop
IDirectSoundBuffer8::Unlock

自 DirectX 9 起,處理影響 Just-In-Time 的新 FX 處理演算法可解決此問題,並降低延遲。 此演算法已新增至 IDirectSoundBuffer8::P lay() 呼叫,以及處理寫入資料指標前效果的額外線程。 因此,您可以隨時設定參數,而且參數會如預期般運作。 不過,請注意,在播放緩衝區上,在聽到參數變更之前,會有一個小延遲(通常是 100 毫秒),因為播放與寫入游標之間的音訊(以及一點更多的填補)已在當時處理。

如何?偵測是否已安裝 DSound?

如果您不需要使用 DirectSoundEnumerate() 來列出可用的 DSound 裝置,請勿將您的應用程式與 dsound.lib 連結,而是透過 COMs CoCreateInstance(CLSID_DirectSound...) 使用它,然後使用 Initialize(Null) 初始化 DSound 物件。 如果您需要使用 DirectSoundEnumerate(),您可以使用 LoadLibrary 動態載入 dsound.dll(「dsound.dll」):並使用 GetProcAddress(「DirectSoundEnumerateA/W」) 和 GetProcAddress(「DirectSoundCreateA/W」) 等方式存取其方法。

如何?使用電壓ATEXTENSIBLE 建立多重通道音訊嗎?

如果您在 DirectSound 說明檔中找不到問題的解答,有一篇好文章,其中包含多個通道音訊資料和 WAVE 檔案中可用的詳細資訊。

如何使用 DirectSound Voice Manager 搭配 EAX 之類的屬性集?

在 DirectSound 9.0 中,當您複製緩衝區時,現在可以在重複的緩衝區上取得 IDirectSoundBuffer8 介面,這可讓您存取 AcquireResources 方法。 這可讓您將緩衝區與DSBCAPS_LOCDEFER旗標與硬體資源產生關聯。 然後,您可以在此緩衝區上設定 EAX 參數,然後才呼叫 Play()。

我在使用游標位置通知時發生不可靠的行為問題。 如何取得更精確的資訊?

各種 DirectSound 版本、核心 Windows 音訊堆疊和音訊驅動程式有一些微妙的錯誤,使得游標位置通知不可靠。 除非您以已知的 HW/SW 設定為目標,否則您知道通知的行為良好,請避免資料指標位置通知。 對於位置追蹤 GetCurrentPosition() 而言,是更安全的技術。

我在使用 GetCurrentPosition() 時遇到效能降低的問題。 如何改善效能?

每個緩衝區上的每個 GetCurrentPosition() 呼叫都會造成系統呼叫,而且系統呼叫應該最小化,因為它們是 DSound CPU 使用量的大型元件。 在 NT (Win2K 和 XP) 上,SW 緩衝區中的資料指標(和某些裝置上的 HW 緩衝區)會以 10 毫秒的增量移動,因此每 10 毫秒呼叫 GetCurrentPosition() 是理想的。 呼叫它的頻率比每 5 毫秒會降低一些效能。

我的 DirectSound 應用程式佔用太多 CPU 時間或執行速度緩慢。 我是否可以執行任何動作來優化程式碼?

您可以執行數件事來改善音訊程式碼的效能:

  • 不要太常呼叫 GetCurrentPosition。 每個緩衝區上的每個 GetCurrentPosition() 呼叫都會造成系統呼叫,而且系統呼叫應該最小化,因為它們是 DSound CPU 使用量的大型元件。 在 NT (Win2K 和 XP) 上,SW 緩衝區中的資料指標(和某些裝置上的 HW 緩衝區)會以 10 毫秒的增量移動,因此每 10 毫秒呼叫 GetCurrentPosition() 是理想的。 呼叫它的頻率比每 5 毫秒會造成一些效能降低。

  • 針對音訊使用個別、較低的畫面播放速率。 現在,許多 Windows 遊戲每秒可以超過 100 個畫面格,在大部分情況下不需要以相同的畫面播放速率更新您的 3D 音訊參數。 每秒或第三個圖形畫面格處理您的音訊,或每 30 毫秒左右,可以大幅減少整個應用程式的音訊撥號數目,而不會降低音訊品質。

  • 針對 3D 物件使用DS3D_DEFERRED。 大部分的音效卡都會立即回應參數變更,而且在單一畫面中可能會變更,特別是當您變更接聽程式的位置或方向時。 這會導致聲音卡/CPU 執行許多不必要的計算,因此另一個快速且通用的優化是延遲某些參數變更,並在畫面結尾認可它們。

    或至少使用 SetAllParameters,而不是緩衝區上的個別 Set3DParamX 呼叫。

    同樣地,您應該至少在 3D 緩衝區上使用 SetAllParamenters 呼叫,而不是個別的 Set3DParamX 呼叫。 只要儘量儘量將系統呼叫降到最低。

  • 不要進行備援呼叫;儲存並排序播放通話清單。 通常,在一個音訊更新畫面中,有 2 個要求播放新音效。 如果要求在抵達時進行處理,則第一個新音效可以啟動,然後立即取代第二個要求的聲音。 這會導致備援計算、不必要的播放呼叫,以及不必要的停止呼叫。 最好儲存要播放的新音效要求清單,以便排序清單,而且只有應該開始播放的語音才會播放。

    此外,您應該為每個音效來源儲存 3D 和 EAX 參數的本機複本。 如果要求將參數設定為特定值,您可以檢查該值是否與最後一個值集實際不同。 如果不是,則不需要進行呼叫。

    雖然音效卡驅動程式可能會偵測到此案例,而不會再次執行 (相同) 計算,但音訊通話必須到達音訊驅動程式(透過環形轉換),這已經是緩慢的作業。

當我串流緩衝區時,它通常會發生問題並執行不佳。 串流緩衝區的最佳方式為何?

將音訊串流至緩衝區時,有兩種基本演算法:After-Write-Cursor (AWC) 和 Before-Play-Cursor (BPC)。 AWC 會以故障的成本將延遲降到最低,而 BPC 則相反。 因為串流音效通常沒有任何互動式變更,所以遊戲和類似的應用程式很少發生這種延遲的問題,因此 BPC 是更適當的演算法。 在 AWC 中,每次串流執行緒執行時,您迴圈緩衝區中的資料最多會超過 N 毫秒,超出其寫入資料指標 (通常是 N=40 左右,以允許 Windows 排程抖動)。 在 BPC 中,您一律會盡可能將資料寫入緩衝區,將資料填滿到其播放資料指標之前(或可能為 32 個位元組,以允許不正確地報告其播放資料指標進度的驅動程式)。

使用 BPC 來 Mimimize 故障,並使用緩衝區 100 毫秒或更大,即使遊戲在測試硬體上沒有故障,也會在部分電腦上發生問題。

我經常和一遍又一遍地播放相同的聲音,有時他們不能正常播放,或者 Play() 通話需要很長的時間。 我該怎麼做?

啟動延遲(與上述串流延遲不同)可能是某些硬體(Play() 呼叫有時在某些音效卡上花費很長的時間的問題。 如果你真的想減少這種延遲,對於抽搐的聲音(槍聲,腳步聲等等。)一個方便的技巧是保持一些緩衝區總是迴圈和播放沉默。 當您需要播放抽動音效時,請挑選一個可用的緩衝區、查看其寫入游標的位置,並將聲音放入緩衝區中,而不只是寫入游標。 某些音效卡會針對我知道其支援的延後屬性而失敗 QuerySupport。 是否有因應措施? 您可以只針對非延遲版本的屬性使用 QuerySupport,並無論如何都使用延後設定。 最新的音效卡驅動程式也可能修正此問題。

如何?將 WAV 檔案編碼為 WMA?

請參閱 Windows 媒體編碼器上的檔:Windows 媒體編碼器 9 系列。

如何?使用 DirectSound 解碼 MP3 檔案嗎?

DirectSound 原生不支援 MP3 解碼。 您可以事先解碼檔案(使用 DirectShow 篩選的 ACM 編解碼器),或者只使用 DirectShow 本身,這可以為您解碼:然後,您可以將產生的 PCM 音訊資料複製到 DirectSound 緩衝區。

別名 Maya 的 DirectX 延伸模組

為什麼我的 NURBS 未顯示?

不支援 NURBS。 您可以將它們轉換成多邊形網格。

為什麼我的 SUBD 不會顯示?

不支援 SUBD。 您可以將它們轉換成多邊形網格。

為什麼 X 檔案中的動畫看起來與預覽視窗中的動畫不同?

預覽視窗在最嚴格的意義上不是動畫。 它不會播放動畫,而是正在同步處理到 Maya 場景的最新狀態。 匯出動畫時,每個轉換的矩陣都會分解成縮放、旋轉(四元數)和翻譯元件(通常稱為 SRT)。 SRT 比矩陣更理想,因為它們插補良好、提供更精簡的資料形式,而且可以獨立壓縮。 並非所有矩陣都可以分解成 SRT。 如果它們無法分解,產生的 SRT 將會未知,因此可能會偵測到動畫中的小錯誤。 Maya 中的兩個特徵最常在分解期間造成問題,是剪力和離中心旋轉或縮放。 如果您遇到此問題,因為您使用的是非中心旋轉或縮放比例,請考慮新增額外的轉換來增加階層層級。

其中 D3DX 動畫支援 SRT,如下所示:

[S]x[R]x[T]

Maya 的矩陣要複雜得多,而且需要大量的額外程式,如下所示:

[SpInv]x[S]x[Sh]x[Sp]x[St]x[RpInv]x[Ro]x[R]x[Rp]x[Rt]x[T]

我用 RigidSkin 縮小網狀結構,但網格(或部分)不會移動。 為何會這樣?

目前不支援瑪雅的剛性皮膚。 請使用平滑皮膚。

我的 IK 在 X 檔案中都去了哪裡?

X 檔案不支援 IK。 相反地,IK 解決方案會製作成儲存在 X 檔案中的畫面格。

為什麼除了 DirectXShaders 之外,我的材質色彩都不會顯示?

Maya 的 DirectX 延伸模組目前僅支援適用于預覽和匯出的 DirectXShader 材質。 未來版本可能會支援其他資料。

XInput 問題

我可以使用 DirectInput 來讀取觸發程式嗎?

是的,但是它們的作用與相同的座標軸。 因此,您無法使用 DirectInput 獨立讀取觸發程式。 使用 XInput,觸發程式會傳回個別的值。

如需為什麼 DirectInput 將觸發程式解譯為一個座標軸的詳細資訊,請參閱 搭配 DirectInput 使用控制器。

XInput 支援多少個控制器?

XInput 支援一次插入 4 個控制器。

XInput 是否支援非通用控制器?

否,它不會。

常見的控制器是否可透過 DirectInput 取得?

是,您可以透過 DirectInput 存取通用控制器。

如何?取得常見控制器的強制意見反應嗎?

為什麼我的預設音訊裝置會變更?

連接頭戴式裝置時,控制器的耳機會作為標準 USB 音訊裝置,因此當它連線時,Windows 會自動變更為使用此 USB 音訊裝置做為預設值。 由於使用者可能不希望所有音訊都通過頭戴式裝置,因此他們需要手動將其調整回原始設定。

如何?控制控制器上的燈光嗎?

控制器上的燈是由作業系統預先決定,無法變更。

如何?我的應用程式中存取 Xbox 360 按鈕?

很抱歉,此按鈕會保留供日後使用。

哪裡可以找到驅動程式?

驅動程式可透過 Windows Update 取得。

如何判斷控制器識別碼?

在 XInput 啟動時,識別碼是由 XInput 引擎和插入的控制器決定不具決定性的。 如果在 XInput 應用程式執行時插入控制器,系統會將新的控制器指派為最低的可用號碼。 如果控制器已中斷連線,則會再次提供其號碼。

如何?取得控制器的音訊裝置嗎?

使用 XInputGetDSoundAudioDeviceGuids 函 式。 如需詳細資訊,請參閱 AudioController 範例。

當控制器未插上時,我該怎麼做?

如果控制器由玩家使用中,您應該暫停遊戲,直到控制器重新連線,玩家按下按鈕來表示他們已準備好取消暫停。