DirectX 8開發人員常見問題

  1. 目 錄
  2. General
  3. Direct3D
  4. DirectSound
  5. DirectPlay

本文對與Microsoft DirectX 8.0版有關的常見開發問題進行解答,其中包括有關Direct3D、DirectSound及DirectPlay的章節。


1、一般性DirectX開發事宜

問:我在試圖編譯示例時,爲何得到那麼多錯誤消息?

:您可能沒有將 include 路徑設置正確。許多編譯器(Microsoft Visual C++)包含 SDK 的一個較早版本,因此如果您的 include 路徑首先搜索標準的編譯器 include 目錄,則您會得到不正確版本的頭文件。爲解決這一問題,請確保 include 路徑和庫路徑被設爲搜索 DirectX include 和庫路徑。另請參見 SDK 中的dxreadme.txt 文件。如果您安裝 DirectX SDK 而您又在使用 Visual C++,則可以選擇讓安裝程序爲您設置各個 include 路徑。

問:我得到關於全局唯一標識符(GUID)符號重複或缺失的連接器錯誤,怎麼辦?

:您使用的各種 GUID 應該得到一次性定義,且只能定義一次。如果您在插入 DirectX 頭文件之前用 #define 定義 INITGUID 符號,則會插入 GUID 的定義。因此,你應確保只對一個編譯單元進行此類操作。這一方法的一個替代方案就是用 dxguid.lib 庫進行連接,其中包含所有 DirectX GUID 的定義。如果您使用這一方法(建議),則您永遠不要通過 #define 定義 INITGUID 符號。

問:我能否將指針指向一個到較低版本號的 DirectX 接口?

:不能。DirectX 接口屬於 COM 接口 。這意味着不要求將較高版本號的接口從相應的低版本號導出。因此, 獲得到 DirectX 對象的一個不同接口的唯一安全方法就是使用接口的 QueryInterface 方法。該方法是標準的 IUnknown 接口的一部分,所有 COM 接口必須從其導出。

問:我能在同一應用程序中將 DirectX 8 組件和DirectX 7 或更早的組件混用嗎?

:您可以隨意混用不同版本的“不同組件”;例如,您可以在將 DirectPlay 8 和 DirectDraw 7 用在同一應用程序中。但是,您通常不可以將“同一組件”的不同版本混用在同一應用程序中;例如,您不能混用 DirectDraw 7 和 Direct3D 8 (鑑於這些實際上是同一組件,因爲 DirectDraw 已被含入 DirectX 8 的 Direct3D)。

問:Release 或 AddRef 方法的返回值有何含義?

:返回值將是對象的當前參照計數。但是,COM 規範聲明,您不應依賴該返回值;該值通常僅供用於調試目的。您觀察到的值可能並非所期待的,因爲各種其它系統對象可能保持着對你所創建的 DirectX 對象的參照。因此,您不應編寫反覆調用 Release 的代碼,一直到參照計數爲零,因爲此時可以將對象釋放,即使另一組件可能仍舊在對其進行參照。

問:我釋放 DirectX 接口的次序很重要嗎?

:應當沒有問題,因爲 COM 接口是參照計數的。但是,在某些 DirectX 版本中,接口的釋放次序有一些已知的缺陷。安全起見,在可能的情況下,建議您以與創建時相反的次序釋放接口。

問:智能指針是什麼,我要用它們嗎?

:智能指針是一個 C++ 模板類,旨在封裝指針功能。尤其有一些標準智能指針類,用於封裝 COM 接口指針。這些指針自動進行 QueryInterface,而不是進行造型,並替您處理 AddRef 和 Release。您是否使用這些指針,大體上是個人偏好。如果您的代碼包含大量的接口指針複製操作,即使用多重 AddRefs 和 Releases,則智能指針可能會使您的代碼更加簡潔和不易出錯。否則,不用也罷。Visual C++ 包含一個標準的 Microsoft COM 智能指針,是在 "comdef.h" 頭文件中定義的(請在幫助中查找 com_ptr_t)。

問:我在調試 DirectX 應用程序時遇到問題,能提示一下嗎?

:調試 DirectX 應用程序時最常見的問題就是試圖在 DirectDraw 表面被鎖定時進行調試。這一情形會在 Windows 9x 系統上導致 “Win16 Lock”,因此而無法繪製調試窗口。在鎖定表面時指定 D3DLOCK_NOSYSLOCK 標誌,通常會消除該現象。Windows 2000沒有這一問題。在開發一個應用程序時,最好運行調試版本的 DirectX 運行時(在安裝 SDK 時進行選擇);該版本進行某些參數證實, 並將一些有用的消息輸出到調試程序的輸出窗口。

問:如何正確地檢查返回代碼?

:使用 SUCCEEDED 和 FAILED 宏。 DirectX 方法可以返回多個成功和失敗代碼,因此一個簡單的“==D3D_OK”或類似的測試結果不總是夠用的。

問:DirectDraw 有何變化?

:DirectDraw 的大多數功能現已被含入新的 Direct3D8 接口。編制單純 2D 應用程序的開發人員可能會希望繼續使用舊的 DirectX 7 接口。對於編制帶有某些 2D 元素的 3D 應用程序的開發人員,鼓勵其使用 Direct3D 替代程序(例如點對象和公告牌紋理),因爲這會改善性能和靈活性。

問:我如何禁用 ALT+TAB 以及其它的任務切換功能?

:請切勿這樣做。

問:有什麼值得推薦的對 COM 進行解釋的書嗎?

:《Inside COM》,Dale Rogerson編寫,Microsoft Press出版,其中對 COM 進行了很好的介紹。如要詳細考察 COM,《Essential COM》,Don Box編寫,Longman出版,這本書也很值得推薦。

問:有什麼關於一般性 Windows 編程的書嗎?

:很多。但筆者認爲值得推薦的書有:《Programming Windows》,Charles Petzold編寫,Microsoft Press 出版。《Advanced Windows》,Jeffrey Richter編寫,Microsoft Press 出版。


2、Direct3D

2.1 一般問題

問:我在何處可以找到有關 3D 圖形技巧的信息?

:關於這一主題的標準書是《Computer Graphics: Principles and Practice》,Foley、Van Dam等編寫;對於任何想要了解幾何、光柵化以及照明技巧的人來講,這都是一個寶貴的資源。comp.graphics.algorithms 新聞組的常見問題解答也包含有用的資料。

問:Direct3D 能夠仿真硬件未提供的功能嗎?

:這要依具體情況而定。Direct3D 具有一個特性齊全的頂點處理流水線(包含對定製頂點着色器的支持)。但是,沒有爲像素級操作提供任何的仿真功能;應用程序必須檢查相應的特徵位,並使用 ValidateDevice API 來確定是否支持。

問:Direct3D 包含有軟件光柵器嗎?

:沒有。Direct3D 現在支持插件式軟件光柵器。但是,目前並不默認提供任何軟件光柵器。

問:Direct3D 幾何代碼使用 3DNow!或 Pentium III SIMD 指令嗎?

:使用。Direct3D 幾何流水線有多個不同的代碼路徑(具體取決於處理器類型),並將使用 3DNow! 或 Pentium III SIMD 指令所提供的特殊的浮點操作(如果這些指令可用的話)。其中包括定製頂點着色器的處理。

問:我如何防止透明的像素被寫到 z 緩衝區?

:您可以藉助高於或低於某一給定門限的 alpha 值來將像素濾除。您通過描繪狀態 ALPHATESTENABLE、ALPHAREF 和 ALPHAFUNC 來控制這一操作。

問:模板緩衝區是什麼?

:模板緩衝區是一個記錄每個像素信息的附加的緩衝區,很象一個 z 緩衝區。實際上,該緩衝區就駐在 z 緩衝區的某些位中。常見的模板/z 緩衝區格式爲 15 位的 z 和 1 位的模板,或 24 位的 z 和 8 位的模板。在描繪多邊形時,可以針對每個像素,對模板的內容進行簡單的算術操作。例如,可以增加或減少模板緩衝區,或在模板值沒能通過一項簡單的比較測試時,拒絕像素。可以將幀緩衝區的一個區域標出,然後只對標出(或未標出)的區域進行描繪,上述操作對於此類效果十分有用。各種體積效果就是很好的例子,比如陰影量。

問:我如何使用模板緩衝區來描繪陰影量?

:這一效果以及其它體積模板緩衝區效果的關鍵在於模板緩衝區和 z 緩衝區之間的交互作用。帶有陰影量的場景是分三個階段描繪的。首先,照常使用 z 緩衝區來描繪沒有陰影的場景。然後,在模板緩衝區中將陰影標出,如下所示。使用不可見的多邊形繪製陰影量的正面,其中 z 測試被啓用,而 z 寫入被禁用,且在每有一個像素通過 z 測試時,就將模板緩衝區增加一次。以同樣方式描繪陰影量的背面,但是要減少模板值。
現在,請考慮單獨一個像素的情形。假設攝像機不在陰影量中,場景中的相應點就有有四種可能性。如果從攝像機到點的光線不與陰影量相交,則不會繪製任何的陰影多邊形,而模板緩衝區依舊爲零。否則,如果點在陰影量的前面,則陰影多邊形會被輸出 z 緩衝區,而模板依舊保持不變。如果點位於陰影量下面,則會描繪同樣多的正面陰影,而模板爲零,即增加的次數與減少的次數一樣多。
最後一種可能性就是點位於陰影量中。在這種情況下,陰影量的背面會被輸出 z 緩衝區,但正面則不然,因而模板緩衝區會爲非零。結果就是,幀緩衝區位於陰影中的一些部分具有非零的模板值。最後,要實際描繪陰影,整個場景會被一個 alpha 混色的多邊形集充溢一遍,其中僅模板值非零的像素受到影響。在隨 DirectX SDK 一起提供的 “Shadow Volume”示例中有關於該技巧的一個示例。

問:Texel(特塞爾)對齊規則是什麼?我怎樣才能得到一一映射?

:這一點在 DirectX 8 文檔中(Directly Mapping Texels to Pixels)得到了全面的解釋。但是總而言之,您應將屏幕座標偏移一個像素的 –0.5,以便正確地與 Texel 對齊。大多數的插卡正確符合對齊規則,但是有一些較老的插卡或驅動程序則不然。要解決這些問題,建議您最好與相關的硬件廠商取得聯繫,請求得到更新過的應驅動程序或其所建議的變通辦法。

問:D3DCREATE_PUREDEVICE 標誌有何用途?

:如果在創建設備時指定了 D3DCREATE_PUREDEVICE 標誌,則 Direct3D 將創建一個“純粹”的設備。這禁用 Get* 族類的方法,並使頂點處理僅限於硬件。這使得 Direct3D 運行時能夠進行某些優化,以提供到驅動程序的最佳路徑,而不必跟蹤那麼多的內部狀態。也就是說,您使用 PUREDEVICE 時可以見到一定的性能優勢,但卻犧牲了某些便利條件。

問:我如何使用顏色鍵控?

:DirectX 8 並不支持顏色鍵控。您應當換用 alpha 混色/測試,大體上這是一個更加靈活的技巧,沒有與顏色鍵控相關的一些問題。

問:我如何枚舉多監視器系統中的所有顯示設備?

:與其它的枚舉功能相同,該功能已從基於回調變爲由應用程序藉助 IDirect3D8 接口的各種方法來進行簡單的反覆。調用 GetAdapterCount 來確定系統中顯示適配器的數目。調用 GetAdapterMonitor 來確定適配器所連接的物理監視器(該方法返回一個HMONITOR,您然後就可以在 Win32 API GetMonitorInfo 中使用該值,以確定關於物理監視器的信息)。確定某一具體顯示適配器的特徵,或在該適配器上創建一個 Direct3D 設備,簡單到在調用 GetDeviceCaps、CreateDevice 或其它方法時,通過替代 D3DADAPTER_DEFAULT 來傳遞相應的適配器編號。

2.2 幾何(頂點)處理

問:D3DVERTEX 等等頂點類型有何變動?

:不再顯式支持“預罐裝”的頂點類型。多重頂點流系統允許對頂點數據進行更加靈活的裝配。如果您想使用其中一個“傳統”的頂點格式,則您可以建立一套相應的FVF 代碼。

問:我對頂點流不大清楚,其工作原理如何?

:Direct3D 對從一個或多個頂點流饋入流水線的每個頂點進行組裝。只有一個頂點流時,就對應於 DirectX 8 以前的老模型,即頂點來自單獨一個源。藉助 DirectX 8,不同的頂點組件可以來自不同的源;例如,一個頂點緩衝區可能含有位置和法線,而另一個則含有顏色值和紋理座標。

問:頂點着色器是什麼?

:頂點着色器是一個用於處理單一頂點的過程。這是藉助一種類似於彙編的簡單語言來進行定義的,由 D3DX 實用程序彙編爲一個 Direct3D 接受的令牌流。頂點着色器接受單獨一個頂點和一組常量值的輸入,並輸出一個頂點位置(在剪貼空間),還可能輸出一組用於光柵化的顏色和紋理座標。請注意,在您有一個定製的頂點着色器時,頂點組件就不再有任何由 Direct3D 施加給它們的語義,而頂點就只是由您所創建的頂點着色器進行解釋的任意數據。

問:頂點着色器進行透視劃分或剪裁嗎?

:不。頂點着色器在已變換的頂點位置的剪貼空間輸出一個純系座標。透視分割和剪裁是由後着色器自動進行的。

問:我能借助頂點着色器生成幾何圖形嗎?

:頂點着色器無法創建或消滅頂點;其一次只對單一頂點進行操作,即作爲輸入接收一個未經處理的頂點,而輸出單獨一個經過處理的頂點。因此可以將其用於操作已有的幾何圖形(應用變形或進行外觀變換操作),但實際上無法生成新的幾何圖形。

問:我能將一個定製的頂點着色器應用到固定功能幾何流水線(或者進行相反的操作)嗎?

:不能。您必須選擇其一。如果您正在使用一個定製的頂點着色器,則您負責進行整個頂點變換操作。

問:如果我的硬件並不支持定製的頂點着色器,我可以使用嗎?

:可以。Direct3D 軟件頂點處理引擎完全支持定製的頂點着色器,且性能指標出奇的高。

問:我如何確定硬件是否支持我的定製的頂點着色器?

:能夠硬件支持頂點着色器的設備被要求填充 D3DCAPS8::VertexShaderVersion 字段,以指示其所支持的頂點着色器的版本級別。所有聲稱支持某一級別的頂點着色器的設備,必須支持所有合法的頂點着色器,這些頂點着色器符合針對該級別或較低級別的規範。

問:有多少個常量寄存器可以用於頂點着色器?

:要求支持 DX8 頂點着色器的設備至少支持 96 個常量寄存器。設備的支持能力可能會超過這一最低數目,且可以通過 D3DCAPS8::MaxVertexShaderConst 字段進行報告。

問:我可以在帶有不同紋理座標的頂點之間共享位置數據嗎?

:該情形的一個通常示例就是一個立方體,其中您想爲每個面使用一個不同的紋理。很不幸,答案是不行;目前還還不能獨立索引每個頂點組件。即使是多頂點流,也是所有的頂點一起索引。

問:在我提交一列帶索引的原語時,Direct3D是處理緩衝區中所有的頂點,還是隻處理我索引過的頂點?

:在使用軟件幾何流水線時,Direct3D 首先轉換您所提交的範圍中的所有的頂點,而不是“根據要求”按照索引對其進行轉換。這對於密集數據(即其中使用了大多數的頂點)效率更高,尤其是在可以使用 SIMD 指令時。如果您的數據比較鬆散(即很多頂點未被使用),則您可能需要考慮重新排列您的數據,以避免多餘的轉換。在使用硬件幾何加速時,頂點經常是根據需要進行轉換的。

問:索引緩衝區是什麼?

:索引緩衝區與頂點緩衝區極其類似,但其包含的是用於 DrawIndexedPrimitive 調用的索引。強烈建議您儘可能使用索引緩衝區,而不要使用原始的由應用程序分配的內存,其道理與頂點緩衝區相同。
我注意到 32 位的索引現在是一種支持類型;我可以將其用在所有的設備上嗎? 不可以。你必須檢查 D3DCAPS8::MaxVertexIndex 字段,以確定設備所支持的最大索引值。該值必須大於 216-1 (0xffff)才能支持 D3DFMT_INDEX32 類型的索引緩衝區。另外請注意,某些設備可能支持 32 位的索引,但其所支持的最大索引值卻小於 232- 1 (0xffffffff);這樣,應用程序必須遵從設備所報告的限制。

問:將多重頂點流用於固定功能流水線有何限制?

:固定功能流水線要求每條頂點流水線是一個嚴格的 FVF 子集,即根據一個完整的 FVF 聲明預定的。另外請注意,您必須遵從 D3DCAPS8::MaxStreams 字段所報告的流水線數目的限制(現在的許多設備和/或驅動程序僅支持單一流水線)。

2.3 性能調諧

問:我如何能夠改善我的 Direct3D 應用程序的性能?

:在優化性能時,需要考察下列幾個關鍵問題:

·批處理大小
Direct3D 已爲大批量原語進行過優化。一次調用所能發送的多邊形越多,其效果也就越好。憑經驗而論,建議平均每次調用100 個以上的多邊形。低於該水平,您可能不會得到最好的性能,而高於該水平,您收到的效果會遞減,且可能會與並行事項發生衝突(參見下面的論述)。
·狀態更改
更改描繪狀態這種操作可能會很昂貴,尤其是在更改紋理時。因此,每幀所作的狀態更改應儘可能地少,這一點很重要。另外,請儘量降低對頂點或索引緩衝區的更改。注意:在 DirectX 中更改緩衝區已不在象在以前版本中那樣昂貴了,但依舊建議儘量避免更改頂點緩衝區。
·並行
如果能夠安排描繪與其它處理同時進行,則您可以充分利用系統性能。這一目標可能會與降低描繪狀態更改的目標相抵觸。您需要在進行批處理以降低狀態更改和較早將數據推出到驅動程序以達到並行目的之間找到一個平衡點。以循環方式使用多個頂點緩衝區,會有助於並行功能。
·紋理上載
將紋理上載到設備會消耗帶寬並導致與頂點數據爭用帶寬。因此,不要佔用過多的內存這一點很重要,因爲這會強制緩存方案爲每一幀上載過多的紋理。
·頂點緩衝區和索引緩衝區
您應當一直使用頂點緩衝區和索引緩衝區,而不是由應用程序分配的普通內存塊。頂點緩衝區和索引緩衝區的鎖定語義至少可以避免多於的複製操作。對於某些驅動程序,頂點緩衝區和索引緩衝區可能是更理想的存儲器中的某些區域(可能是在視頻或 AGP 存儲器中),供硬件進行訪問。
·狀態宏鎖定
這些是在 DirectX 7.0 中推出的,爲將一系列的狀態更改(包括照明、材質和矩陣更改)記錄成一個宏提供了一個機制,該宏然後就可以通過單一的調用來重放了。這有兩個優勢:
  1. 您進行一次調用而不是多次調用,從而降低調用開銷。
  2. 有感悟能力的驅動程序可以對狀態更改進行預分析和預編譯,從而使到圖形硬件的提交速度快得多。狀態更改可能依舊很昂貴,但使用狀態宏至少會有助於降低部分成本。
·僅使用單獨一個 Direct3D 設備
如果您需要描繪到多個目標,則請使用 SetRenderTarget。如果您是要創建一個帶有多個 3D 窗口的窗口化程序,則請使用 CreateAdditionalSwapChain API。運行時已爲單一設備進行過優化,使用多個設備時會有相當多的速度折扣。

問:我應當使用哪些基本類型(條形、扇形、列表等)?

:在真實數據中遇到的許多網格,都具有多個多邊形共享頂點的特性。爲將性能最大化,最好將所轉換的頂點中的重複率降低,並橫跨總線將其發給描繪設備。使用簡單的三角列表根本實現不了任何頂點共享,因而這是最不理想的方法。這一點已很清楚。然後所要作的選擇就是使用條形和扇形(暗示多邊形之間的具體連接關係),還是使用索引列表。在數據自然歸入各種條形和扇形的情況下,這些就是最爲合適的選擇,因爲發給驅動程序的數據被降至最低。但是,將網格分解條形和扇形經常會造成大量分離塊,暗示有大量的 DrawPrimitive 調用。因此,最富效率的方法通常是使用帶三角列表的單獨一個 DrawIndexedPrimitive 調用。使用索引列表的另一個優勢就是,這在連續三角形僅共享單獨一個頂點時也有益處。總而言之,如果您的數據自然歸入各種較大的條形和扇形,就使用條形和扇形,否則就使用索引列表。

問:如果我要生成動態數據,怎樣纔算是較好地使用頂點緩衝區了呢?

:具體的實施步驟。

  1. 藉助 D3DUSAGE_DYNAMIC 和 D3DUSAGE_WRITEONLY 使用標誌以及 D3DPOOL_DEFAULT 緩衝池標誌來創建一個頂點緩衝區。(如果您正使用軟件頂點處理功能的話,還要指定 D3DUSAGE_SOFTWAREPROCESSING)
  2. I = 0
  3. 設置狀態(紋理、描繪狀態等)
  4. 檢查緩衝區內是否有空間,即 i.e.I + M <= N? (其中 M 是新頂點的數目)
  5. 如果爲真,則藉助 D3DLOCK_NOOVERWRITE 對 VB 進行 Lock (鎖定)。這告知 Direct3D 和驅動程序,您將要添加頂點,而並不修改您先前批處理過的頂點。因此,如果當時正在進行一項DMA 操作,則並不中斷該操作。否則,轉至 11
  6. 在 I 處填充 M 個頂點
  7. 解鎖 (Unlock
  8. 調用 Draw[Indexed]Primitive。對於未經索引的,請將 I 用作 StartVertex 參數。對於已編索的基本類型,請確保索引指向頂點緩衝區的正確部分(要做到這一點,使用 SetIndices 調用的 BaseVertexIndex 參數可能最爲容易)
  9. I + = M
  10. 轉到 3
  11. 好,空間已用盡,就讓我們開始一個新的頂點緩衝區。我們不想使用同一個頂點緩衝區,因爲有可能有一個 DMA 操作正在進行之中。我們將這一情形告知 Direct3D, 方法是藉助 D3DLOCK_DISCARD 標誌,將“同一個”頂點緩衝區鎖定。這意思是,“你可以給我一個新的指針了,因爲我已用完舊的指針,不再在意舊的內容。”
  12. I = 0
  13. 轉至 4(或 6)

2.4 Direct3DX 實用程序庫

問:D3DX 圖象文件加載器函數支持哪些文件格式?

:D3DX 圖象文件加載器函數支持 BMP、TGA、PNG、JPG、DIB、PPM 和 DDS 文件。

問:D3DX 中的文字描繪函數好象失效,我的操作有什麼問題嗎?

:使用 ID3DXFont::DrawText 功能時的一個常見錯誤就是爲顏色參數指定一個零 alpha 組件,從而導致完全透明(即不可見)的文本。對於完全不透明的文本,請確保色彩參數的 alpha 成分完全飽和(255)。

問:對於字體描繪,我應當使用 ID3DXFont 還是 SDK 框架 CD3DFont 類?

:ID3DXFont 類能夠處理字間距,因爲它使用 GDI 來繪製字符串。這可能會有點慢,因爲每次均需要調用GDI。
CD3DFont 設計用於加速和使用紋理化基本類型來繪製字符。它只能處理簡單字體,並不支持 ID3DXFont 可用的全套格式選項,但適用於簡單而快速的顯示,諸如幀速率計數等等。對於產品代碼,您可能需要實施您自己的字形描繪功能,即藉助紋理化基本類型和/或基於GDI 的方案(帶避免重新繪製的緩存功能)。


3、DirectSound

問:我的應用程序啓動時,爲何爲發出一陣淨噪聲?

:我注意到其它應用程序也有這個問題。您可能安裝了調試用 DirectX 運行時。運行時的調試版本用靜噪聲填充緩衝區,以便幫助開發人員捕捉未經初始化緩衝區的缺陷。您無法保證DirectSound 緩衝區在創建後的內容;尤其是您無法將緩衝區清零。


4、DirectPlay

問:我如何確保我的遊戲將能夠與各種網絡地址轉換器和Internet連接共享設置正常工作?

:網絡地址轉換器(Network Address Translator,NAT)和Internet連接共享(Internet Connection Sharing,ICS)是較爲複雜的主題,在 MSDN 上的另一篇文章中有更詳盡的論述。但是,下列提示可以作爲
很好的一般性指導:Nats2-msdn.htm

·通過 IDirectPlay8Client 和 IDirectPlay8Server 接口,使用一種客戶端 — 服務器而不是點對點網絡拓撲。
·將服務器放在清澈的 Internet 上,而不是在一個 NAT 後面。
·直接枚舉遊戲端口,而不是使用 DPNSVR。
·不要在您的消息中內嵌 IP 地址或端口號。

有關點對點遊戲、將服務器駐於 NAT 後面的事宜,以及針對各種不同的 Windows 操作系統上的 ICS 的具體建議,請參考更詳盡的文檔。

問:DPNSVR 是做什麼用的?

:DPNSVR 是一種用於枚舉請求的轉發服務,消除了多個 DirectPlay 應用程序在端口使用上的衝突所導致的各種問題。使用 DPNSVR 使得 DirectPlay 能夠自動選擇要使用的端口,同時又允許客戶端對您的遊戲進行枚舉。默認爲,DirectPlay 會使用 DPNSVR,因爲這通常爲應用程序提供了最大的靈活性;但是,您可以將其禁用,方法是在創建您的會話時指定 DPNSESSION_NODPNSVR 標誌。如果客戶端使用 DPNSVR 端口來枚舉主機,而主機又使用自己的端口來作出響應的話,使用 DPNSVR 可能會導致客戶端一側的 NAT 發生問題;NAT 可能會拒絕將數據包轉遞給客戶端,因爲數據包不是來自請求被髮往的同一端口。

問:IDirectPlay8LobbyClient::Initialize 爲何返回 DPNERR_NOTALLOWED?

:DirectPlay 不允許每個進程有一個以上的前端客戶端或應用程序,因而試圖創建多個客戶端會導致返回這一錯誤。

發佈了35 篇原創文章 · 獲贊 0 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章