DirectX FAQ 翻譯(Graphics 部分)

 

DirectX Frequently Asked Questions

Microsoft Corporation

August 2005

Introduction

This is a collection of Frequently Asked Questions (FAQ) about Microsoft DirectX.

Contents:

內容:

            一般DX開發事項

            D3D問題

            DirectSound問題

            DX Maya擴展問題

            XInput問題

General DirectX Development Issues

 

一般DX開發事項

Should game developers still be publishing games for Windows 95, Windows 98 or Windows ME?

 

遊戲開發者仍然只能在Win95Win98Win ME上(用DX9)製作遊戲嗎?

Not anymore for two reasons: performance and feature set.

對,有兩個原因:性能和特性集合。

If the minimum CPU speed required for your game is 1.2GHz or above (which is more common for high performance titles), then the vast majority of these machines will be running Windows XP. By the time machines with CPU speeds above 1.2GHz were being sold, Windows XP was installed as the default operating system by almost all manufacturers. This means that there are many features found in Windows XP that today's game developers should be taking advantage of including:

如果你的遊戲對最小CPU速度要求是1.2GHz或者更高(這對高性能遊戲來說很普遍)那麼這些機器中的大部分會在Windows XP上運行。到現在(2005.4)爲止,當一臺CPU速度高於1.2GHz的機器在售出時,廠商基本上會把Windows XP作爲默認操作系統(吹牛??)。這意味着Windows XP的許多特性會被現在的遊戲開發者採用,包括(吹吧……):

  • Improved multitasking - which results in a better, smoother experience for video, audio and gaming.
  • 改進的多任務-提供對視頻,音頻和遊戲更好的更平穩的體驗
  • More stable video driver model - which allows easier debugging, smoother game play and better performance.
  • 更穩定的視頻驅動模型-調試更容易,遊戲運行更平穩,性能更好
  • Easier configuration for networking - which allows easier access to multi-player games.
  • 對網絡的描述更簡單-對多人遊戲的操作更簡單
  • Support for DMA transfers by default from hard drives - which results in smoother, faster loading applications.
  • 默認對硬件驅動支持DMA傳送-平穩,快速的載入程序
  • Windows error reporting - which results in a more stable OS, drivers and applications.
  • Windows錯誤報告-更穩定的操作系統,驅動和程序
  • Unicode support - which greatly simplifies localization issues.
  • 支持Unicode-簡化多語種支持
  • Better security and stability - which results in better consumer experiences.
  • 更好的安全性和穩定性-更好的客戶體驗
  • Better support for modern hardware - most of which no longer uses Windows 98 drivers.
  • 對當前硬件更好的支持-大多數比Windows98驅動用的更久
  • Improved memory management - which results in better stability and security.
  • 改進內存管理-提供更高的穩定性和安全性
  • Improved NTFS file system - which is more resistant to failure, and has better performance with security features.
  • 改進NTFS文件系統-提供更好的容錯性,保證安全的同時提供更高的性能

Should game developers still be publishing games for Windows 2000?

遊戲開發者仍然需要在Windows 2000上編程嗎?

Not anymore. In addition to the reasons listed in Should game developers still be publishing games for Windows 95, Windows 98 or Windows ME?, Windows 2000 does not have these features:

不需要。作爲對上個問題的補充,Windows 2000不支持這些特性:

  • Windows XP supports advanced processor features such as Hyper-Threading, Multi-Core and x64.
  • XP支持高級處理器特性比如超線程,多內核和64位程序
  • Windows XP supports side-by-side components which significantly reduces application versioning conflicts.
  • XP支持並行組件技術,能夠有效減少程序版本衝突
  • Windows XP supports no-execute memory protection which helps prevent malicious programs and can aid debugging.
  • XP支持未執行程序保護,這能夠阻止惡意程序訪問和輔助調試
  • Windows XP has improved support for advanced AGP and PCI Express based video cards.
  • XP改進了對使用高級AGPPCIE顯卡的支持
  • Windows XP supports fast user switching, remote desktop and remote assistance which can help lower product support costs.
  • XP支持快速用戶切換,遠程桌面和遠程幫助,這能夠幫助降低產品支持消耗
  • Performance tools like Reference (in the DirectX Developer SDK) no longer support Windows 2000.
  • 2000不再支持類似於PIXPIXWIN之類的性能工具

In short, Windows 2000 was never designed or marketed as a consumer operating system.

簡而言之,Windows 2000不再作爲個人用戶操作系統而設計和銷售。

I think I have found a driver bug, what do I do?

我想我找到了一個驅動Bug,應該怎麼辦?

First, ensure you have checked the results with the Reference Rasterizer. Then check the results with the latest WHQL certified version of the IHVs driver. You can programmatically check the WHQL status using the GetAdapterIdentifier() method on the IDirect3D9 interface passing the D3DENUM_WHQL_LEVEL flag. With a WHQL certified driver issue, send a description of the bug, the output from dxdiag and a repro case to [email protected] with a note in the subject line "WHQL Driver Bug".

首先,使用參考光柵化程序檢查你的結果,然後檢查最後一次由WHQLWindows Hardware Quality Labs,視窗硬件質量實驗室)認證的IHVsIndependent Hardware Vendors,獨立硬件開發商)驅動運行結果。你可以在程序中使用DX9GetAdapterIdentifier()函數並傳入D3DENUM_WHQL_LEVEL 標記檢查WHQL狀態。發送WHQL認證的驅動,bug的描述、dx窗口的輸出和重現bug的例子到 [email protected],題目標爲"WHQL Driver Bug"

Why do I get so many error messages when I try to compile the samples?

爲什麼我在編譯sample的時候有這麼多的錯誤信息?

You probably don't have your include path set correctly. Many compilers, including Microsoft Visual C++, include an earlier version of the SDK, so if your include path searches the standard compiler include directories first, you'll get incorrect versions of the header files. To remedy this issue, make sure the include path and library paths are set to search the Microsoft DirectX include and library paths first. See also the dxreadme.txt file in the SDK. If you install the DirectX SDK and you are using Visual C++, the installer can optionally set up the include paths for you.

你可能沒有正確設定你的include路徑。許多編譯器,包括MS VC++在內,設定了早期版本的SDK路徑,所以如果你的include路徑在標準編譯器從前設定的路徑下搜尋,你會得到版本不正確的頭文件。爲了解決這個問題,必須首先保證include路徑和lib路徑設置到當前的DX SDK include 目錄和lib目錄。你可以參考SDK中的dxreadme.txt文件。如果你安裝了DX SDK並在使用VC++,安裝程序會可選擇的爲你設定include路徑。

I get linker errors about multiple or missing symbols for globally unique identifiers (GUIDs), what do I do?

我(在編譯過程中)產生一個找不到全局一致標記符(GUIDs)定義的錯誤,應該怎麼辦?

The various GUIDs you use should be defined once and only once. The definition for the GUID will be inserted if you #define the INITGUID symbol before including the DirectX header files. Therefore, you should make sure that this only occurs for one compilation unit. An alternative to this method is to link with the dxguid.lib library, which contains definitions for all of the DirectX GUIDs. If you use this method (which is recommended), then you should never #define the INITGUID symbol.

你使用的大量的GUIDs必須並且只能定義一次。如果你在include DX頭文件之前使用#define定義了宏INITGUID,對GUID的定義會被插入到你的程序中。但是你必須保證在一次編譯中這個定義只出現一次。另一個辦法是在程序中鏈接dxguid.lib 庫文件,這個文件包含所有的DX GUIDs的定義。如果你使用這個(我們推薦的)方法,你就不需要使用 #define INITGUID了。

Can I cast a pointer to a DirectX interface to a lower version number?

我能夠使用低版本號的DX接口指針嗎?

No. DirectX interfaces are COM interfaces. This means that there is no requirement for higher numbered interfaces to be derived from corresponding lower numbered ones. Therefore, the only safe way to obtain a different interface to a DirectX object is to use the QueryInterface method of the interface. This method is part of the standard IUnknown interface, from which all COM interfaces must derive.

不行。DX接口是COM接口,這意味着高版本的接口不是從低版本接口上派生得到。使用不同版本接口唯一安全的辦法是使用該接口QueryInterface函數。這個函數是標準IUnknown接口的一部分,所有的COM接口都從IUnknown派生。

Can I mix the use of DirectX 9 components and DirectX 8 or earlier components within the same application?

我能夠在相同的程序中混合使用DX9組件和DX8(或者更早版本的)組件嗎?

You can freely mix different components of differing version; for example, you could use DirectInput 8 with Direct3D 9 in the same application. However, you generally cannot mix different versions of the same component within the same application; for example, you cannot mix DirectDraw 7 with Direct3D 9 (since these are effectively the same component as DirectDraw has been subsumed into Direct3D as of DirectX 8). There are exceptions, however, such as the use of Direct3D 9 and Direct3D 10 together in the same application, which is allowed.

你能夠自由混合使用不同版本的DX組件。舉個例子說,你能夠在同一個程序中使用DirectInput8D3D9。當然,你不能在同一程序中使用不同版本的相同組件。比如你不能混合使用DirectDraw7Direct3D9(因爲DirectDrawDirectX8起成爲Direct3D的一部分)。當然也有例外,比如在程序中允許同時使用Direct3D9Direct3D10

Can I mix the use of Direct3D 9 and Direct3D 10 within the same application?

我能夠在同一程序中混合使用Direct3D9Direct3D10嗎?

Yes, you may use these versions of Direct3D together in the same application.

是的,豬頭,我剛纔說過了。

What do the return values from the Release or AddRef methods mean?

Release函數和AddRef函數的返回值是什麼意思?

The return value will be the current reference count of the object. However, the COM specification states that you should not rely on this and the value is generally only available for debugging purposes. The values you observe may be unexpected since various other system objects may be holding references to the DirectX objects you create. For this reason, you should not write code that repeatedly calls Release until the reference count is zero, as the object may then be freed even though another component may still be referencing it.

返回值是當前對象的reference數量。當然,COM組件定義中說你不需要用到它,這個值通常用作調試。你看到的值可能不是你所期望的,因爲大量的其他系統對象會保存你創建的DirectX對象的reference。因爲如此,你不能在程序中重複調用Release()知道它的返回值爲0,否則這個對象會被真正釋放,而同時還有其他組件保存有它的reference(要使用它)。

Does it matter in which order I release DirectX interfaces?

我釋放DirectX接口的順序重要嗎?

It shouldn't matter because COM interfaces are reference counted. However, there are some known bugs with the release order of interfaces in some versions of DirectX. For safety, you are advised to release interfaces in reverse creation order when possible.

沒關係,因爲COM接口有reference的計數。當然,在一些版本的DirectX中有一些和釋放順序相關的已知的Bug,爲了安全,你最好儘可能的使用和創建接口相反的順序來釋放。

What is a smart pointer and should I use it?

什麼是smart pointer(智能指針),我必須用它嗎?

A smart pointer is a C++ template class designed to encapsulate pointer functionality. In particular, there are standard smart pointer classes designed to encapsulate COM interface pointers. These pointers automatically perform QueryInterface instead of a cast and they handle AddRef and Release for you. Whether you should use them is largely a matter of taste. If your code contains lots of copying of interface pointers, with multiple AddRefs and Releases, then smart pointers can probably make your code neater and less error prone. Otherwise, you can do without them. Visual C++ includes a standard Microsoft COM smart pointer, defined in the "comdef.h" header file (look up com_ptr_t in the help).

智能指針是一個C++模板類,設計爲封裝指針的功能。通常情況下,我們有專門封裝COM接口指針的的標準智能指針類。這些指針自動執行QueryInterface函數,不需要做類型轉換。它們也會爲爲你執行AddRefRelease函數。你是否使用只能只能完全看你個人喜好。如果你的代碼裏包含大量的接口指針拷貝,同時還有多種AddRefRelease操作,使用智能指針能夠使你的代碼更簡潔和減少出錯。當然你也可以不用它們。VC++包含一個標準MS COM只能指針類,在文件”comdef.h”中定義(在help中查找com_ptr_t

I have trouble debugging my DirectX application, any tips?

我在調試DirectX程序時有問題,有什麼建議嗎?

The most common problem with debugging DirectX applications is attempting to debug while a DirectDraw surface is locked. This situation can cause a "Win16 Lock" on Microsoft Windows 9x systems, which prevents the debugger window from painting. Specifying the D3DLOCK_NOSYSLOCK flag when locking the surface can usually eliminate this. Windows 2000 does not suffer from this problem. When developing an application, it is useful to be running with the debugging version of the DirectX runtime (selected when you install the SDK), which performs some parameter validation and outputs useful messages to the debugger output.

調試DX程序時最常見的問題就是在DirectDraw surface被鎖定的時候嘗試調試。這種情況會導致MS Win 9x系統產生一個“Win16 Lock”的錯誤,阻止調試器窗口繪製。當鎖定surface時定義D3DLOCK_NOSYSLOCK宏通常可以消除這個錯誤。Win 2000沒有這個問題。開發程序時,在dubug模式下運行DirectX runtime(在你安裝SDK時選擇)會很有效,因爲它會做一些參數有效性檢查和輸出有用信息到調試器輸出窗口。

What's the correct way to check return codes?

檢查代碼返回值的正確方法是什麼?

Use the SUCCEEDED and FAILED macros. DirectX methods can return multiple success and failure codes, so a simple:

== D3D_OK

or similar test will not always suffice.

使用SUCCEEDEDFAILED宏檢查。DX函數會返回多個不同的成功和錯誤值,所以一個簡單的 == D3D_OK或者類似的檢查通常是不夠的。

How do I disable ALT+TAB and other task switching?

我怎麼阻止ALT+TAB切換程序和其他任務切換?

You don't!

你丫民工,俺都不希說你!

Is there a recommended book explaining COM?

有解釋COM接口的推薦閱讀材料嗎?

Inside COM by Dale Rogerson, published by Microsoft Press, is an excellent introduction to COM. For a more detailed look at COM, the book Essential COM by Don Box, published by Longman, is also highly recommended.

《深入COM編程》,作者Dale Rogerson,微軟出版社出版。此書是對COM接口最好的一本入門書。想要對COM有深入瞭解,我們強烈推薦《Essential COM》,作者 Don BoxLongman出版社出版。(國內有影印版)

What is managed code?

什麼是Managed code(可控制代碼)?

Managed code is code that has its execution managed by the .NET Framework Common Language Runtime (CLR). It refers to a contract of cooperation between natively executing code and the runtime. This contract specifies that at any point of execution, the runtime may stop an executing CPU and retrieve information specific to the current CPU instruction address. Information that must be query-able generally pertains to runtime state, such as register or stack memory contents.

Managed code是在.NET框架通用語言運行時(CLR)程序管理下執行的代碼。它指的是原始的執行代碼和運行時程序協同工作時之間的協定。該協定定義在程序運行的任何地方,運行時能夠停止CPU工作並獲得當前CPU的指令地址。能夠被查詢的信息通常是那些運行時狀態,比如寄存器狀態或者堆棧內容。

Before the code is run, the IL is compiled into native executable code. And, since this compilation happens by the managed execution environment (or, more correctly, by a runtime-aware compiler that knows how to target the managed execution environment), the managed execution environment can make guarantees about what the code is going to do. It can insert traps and appropriate garbage collection hooks, exception handling, type safety, array bounds and index checking, and so forth. For example, such a compiler makes sure to lay out stack frames and everything just right so that the garbage collector can run in the background on a separate thread, constantly walking the active call stack, finding all the roots, chasing down all the live objects. In addition because the IL has a notion of type safety the execution engine will maintain the guarantee of type safety eliminating a whole class of programming mistakes that often lead to security holes.

在代碼運行前,IL被編譯到可執行的代碼中。因爲編譯在可控制執行環境下(或者,更正確的說法是,在清楚運行時各種信息並知道如何應對可控制執行環境的編譯器)進行,可控制執行環境能夠知道代碼將會做什麼。它能夠插入陷阱、合適的垃圾蒐集鉤子程序(??),異常處理,類型安全性,數據邊界和索引檢查之類的跟蹤程序。這種編譯器保證設置棧幀和其他一切正常,所以垃圾蒐集器可以在另一個線程上在後臺運行,連續訪問激活的堆棧,找到堆棧根部,跟蹤到任意一個激活的對象。因爲IL會做類型安全性工作,執行引擎會得到類型安全的保證,所以會剔除許多經常導致安全漏洞的編程錯誤。

In contrast this to the unmanaged world: Unmanaged executable files are basically a binary image, x86 code, loaded into memory. The program counter gets put there and that's the last the OS knows. There are protections in place around memory management and port I/O and so forth, but the system doesn't actually know what the application is doing. Therefore, it can't make any guarantees about what happens when the application runs.

與此相反的是不可控制的世界:不可控制的執行文件基本上是一個2進制鏡像,x86代碼,載入內存中。程序計數器從裏面讀取指令,最後只有操作系統知道怎麼執行。操作系統會保護內存管理和I/O端口,但是系統不知道應用程序實際做什麼,並且它不保證在應用程序運行時會發生什麼。

What books are there about general Windows programming?

一般Windows編程看什麼參考書?

Lots. However, the two that are highly recommended are:

好多。推薦這兩本:

  • Programming Windows by Charles Petzold (Microsoft Press)
  • Programming Applications for Windows by Jeffrey Richter (Microsoft Press)

How do I debug using the Windows symbol files?

用了Windows符號文件之後怎麼調試?

Microsoft publish stripped symbols for all system DLLs (plus a few others). To access them add the following to your symbol path in the project settings inside Visual Studio:

MS對所有的系統DLL列出了符號定義。爲了得到這些定義,需要把下面路徑加到Visual Studio中項目設置的符號路徑中:

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

for caching symbols locally use the following syntax:

從本地緩存符號使用下列語法:

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

Where c:/cache is a local directory for caching symbol files.

c:/cache代表cache文件的本地路徑。

Direct3D Questions

D3D問題

General Direct3D Questions

一般D3D問題

Where can I find information about 3D graphics techniques?

我怎麼樣才能找到3D圖形技術的信息?

The standard book on the subject is Computer Graphics: Principles and Practice by Foley, Van Dam et al. It is a valuable resource for anyone wanting to understand the mathematical foundations of geometry, rasterization and lighting techniques. The FAQ for the comp.graphics.algorithms Usenet group also contains useful material.

這個方面的標準參考書是:《計算機圖形學:原理與實踐》作者FoleyVan Dam等。對於希望理解圖形學幾何,光柵化和光照技術的數學基礎的人來說,這是本有價值的書。comp.graphics.algorithms Usenet組的FAQ也有很多有用的信息。

Does Direct3D emulate functionality not provided by hardware?

硬件不提供D3D的模擬功能?

It depends. Direct3D has a fully featured software vertex-processing pipeline (including support for custom vertex shaders). However, no emulation is provided for pixel level operations; applications must check the appropriate caps bits and use the ValidateDevice API to determine support.

D3D模擬功能依賴於硬件。D3D有着完整的軟件頂點處理流水線(包括處理用戶的VS)。當然,像素操作沒有提供模擬功能;應用程序必須使用ValidateDevice檢查合適的Caps位,判斷是不是支持像素操作。

Is there a software rasterizer included with Direct3D?

D3D中做軟件光柵化嗎?

Not for performance applications. A reference rasterizer is supplied for driver validation but the implementation is designed for accuracy and not performance. Direct3D does support plug-in software rasterizers.

對性能要求高的程序不做軟件光柵化。D3D提供參考光柵化作爲驅動的參照,但它的設計是爲了精確性而不是爲了性能。D3D支持軟件光柵化插件。

How can I perform color keying with DirectX graphics?

DX中怎麼做顏色索引?

Color keying is not directly supported, instead you will have to use alpha blending to emulate color keying. The D3DXCreateTextureFromFileEx() function can be used to facilitate this. This function accepts a key color parameter and will replace all pixels from the source image containing the specified color with transparent black pixels in the created texture.

顏色索引並沒有直接被支持,但是你可以使用alpha混合來模擬顏色索引。D3DXCreateTextureFromFileEx()函數也可以協助實現這個功能。這個函數接受一個顏色索引參數並在創建的紋理中把所有源圖像中和顏色索引相同的像素替換程黑色。

Does the Direct3D geometry code utilize 3DNow! and/or Pentium III SIMD instructions?

D3D幾何代碼使用了3DNow!或者奔三SIMD指令嗎?

Yes. The Direct3D geometry pipeline has several different code paths, depending on the processor type, and it will utilize the special floating-point operations provided by the 3DNow! or Pentium III SIMD instructions where these are available. This includes processing of custom vertex shaders.

是的。D3D幾何流水線有依賴於處理器類型的幾個不同的代碼路徑,如果可以的話,它會使用3D Now!或者奔三提供的特殊的SIMD浮點處理指令,包括執行用戶的VS在內。

How do I prevent transparent pixels being written to the z-buffer?

我怎麼樣阻止透明像素寫到z緩存中?

You can filter out pixels with an alpha value above or below a given threshold. You control this behavior by using the renderstates ALPHATESTENABLE, ALPHAREF and ALPHAFUNC.

你可以通過設置一個超過閥值的Alpha值濾除像素,這需要設置繪製狀態ALPHATESTENABLE, ALPHAREFALPHAFUNC來控制。

What is a stencil buffer?

什麼是模板緩存?

A stencil buffer is an additional buffer of per-pixel information, much like a z-buffer. In fact, it resides in some of the bits of a z-buffer. Common stencil/z-buffer formats are 15-bit z and 1-bit stencil, or 24-bit z and 8-bit stencil. It is possible to perform simple arithmetic operations on the contents of the stencil buffer on a per-pixel basis as polygons are rendered. For example, the stencil buffer can be incremented or decremented, or the pixel can be rejected if the stencil value fails a simple comparison test. This is useful for effects that involve marking out a region of the frame buffer and then performing rendering only the marked (or unmarked) region. Good examples are volumetric effects like shadow volumes.

模板緩存是一個保存逐像素信息的附加緩存,和Z緩存非常類似。實際上,它使用Z緩存的一些比特位來實現。普通的S/Z緩存格式是15Z值和1S值,或者24Z值和8S值。在繪製多邊形時可以對模板緩存中的數組做逐像素的簡單算術操作。比如說模板緩存可以遞增或者遞減,或者在模板測試失敗的時候剔除像素。這樣操作可以標記屏幕上一塊區域然後值繪製標記好的區域。使用模板緩存最好的例子是Shadow Volumes算法。

How do I use a stencil buffer to render shadow volumes?

我怎麼樣使用模板緩存來繪製Shadow Volume

The key to this and other volumetric stencil buffer effects, is the interaction between the stencil buffer and the z-buffer. A scene with a shadow volume is rendered in three stages. First, the scene without the shadow is rendered as usual, using the z-buffer. Next, the shadow is marked out in the stencil buffer as follows. The front faces of the shadow volume are drawn using invisible polygons, with z-testing enabled but z-writes disabled and the stencil buffer incremented at every pixel passing the z-test. The back faces of the shadow volume are rendered similarly, but decrementing the stencil value instead.

這個問題和其他體素模板緩存效果的關鍵是如何讓模板緩存和Z緩存做交互。使用Shadow Volume繪製場景分三步。首先,打開Z緩存使用無陰影方式繪製一次。接下來使用這樣的手段標記陰影:繪製不可見的Shadow Volume的正面,打開Z測試關閉Z寫入,模板緩存在每個像素通過z測試時加1Shadow Volume的背面使用同樣方法繪製,只是在通過z測試時減1

Now, consider a single pixel. Assuming the camera is not in the shadow volume there are four possibilities for the corresponding point in the scene. If the ray from the camera to the point does not intersect the shadow volume, then no shadow polygons will have been drawn there and the stencil buffer is still zero. Otherwise, if the point lies in front of the shadow volume the shadow polygons will be z-buffered out and the stencil again remains unchanged. If the points lies behind the shadow volume then the same number of front shadow faces as back faces will have been rendered and the stencil will be zero, having been incremented as many times as decremented.

現在考慮單個像素。假設相機不在Shadow Volume中,對於場景中的點有四種可能。如果相機發出的光線沒有和Shadow Volume相交,那麼沒有多邊形被畫到這個像素上,模板緩存值位0。如果點在Shadow Volume之前,那麼在繪製Shadow Volume時它不會通過z測試,因此模板緩存保持爲0。如果點在Shadow Volume之後,那麼模板緩存遞增的次數和遞減的次數相同,因此模板緩存值還是0

 The final possibility is that the point lies inside the shadow volume. In this case the back face of the shadow volume will be z-buffered out, but not the front face, so the stencil buffer will be a non-zero value. The result is portions of the frame buffer lying in shadow have non-zero stencil value. Finally, to actually render the shadow, the whole scene is washed over with an alpha-blended polygon set to only affect pixels with non-zero stencil value. An example of this technique can been seen in the "Shadow Volume" sample that comes with the DirectX SDK.

最後一種可能是在Shadow Volume中的像素點。在這種情況下背面Shadow Volume不通過z測試而正面通過,所以模板緩存是一個非0的值。這樣的結果就是模板緩存不爲0的像素處於陰影中。最後,實際繪製陰影,整個場景用Alpha混合只對陰影中的區域繪製多邊形。這種技術的一個例子參見DX SDK中的Shadow Volume sample程序。

What are the texel alignment rules? How do I get a one-to-one mapping?

什麼是紋理對齊規則?我們怎麼得到11採樣?

This is explained fully in the Direct3D 9 documentation. However, the executive summary is that you should bias your screen coordinates by -0.5 of a pixel in order to align properly with texels. Most cards now conform properly to the texel alignment rules, however there are some older cards or drivers that do not. To handle these cases, the best advice is to contact the hardware vendor in question and request updated drivers or their suggested workaround. Note that in Direct3D 10, this rule no longer holds.

這在D3D9的文檔中已經完全解釋過了。在執行的細節上,你需要注意把你的屏幕座標向左偏移0.5以完成像素的對齊。大部分顯卡現在都支持紋元對齊規則,但是一些老的卡沒有支持。對於這種情況,你最好和硬件製造商聯繫,要求更新驅動或者按照他們的建議設置工作環境。注意在D3D10中,這種規則已經不存在了。

What is the purpose of the D3DCREATE_PUREDEVICE flag?

D3DCREATE_PUREDEVICE標記的作用是什麼?

Use the D3DCREATE_PUREDEVICE flag during device creation to create a pure device. A pure device does not save the current state (during state changes), which often improves performance; this device also requires hardware vertex processing. A pure device is typically used when development and debugging are completed, and you want to achieve the best performance.

在創建設備過程中使用D3DCREATE_PUREDEVICE標記來創建純設備。純設備並(在狀態切換時)不保存當前狀態,這樣能提高性能。這種設備同時也需求硬件頂點處理。純設備在調試和開發結束後使用,用作或者最好性能。

One drawback of a pure device is that it does not support all Get* API calls; this means you can not use a pure device to query the pipeline state. This makes it more difficult to debug while running an application. Below is a list of all the methods that are disabled by a pure device.

純設備的缺點是它不支持Get*API() 調用,這意味着你不能夠使用純設備來查詢設備狀態。在運行調試程序時,這會比一般設備更困難。下面是在使用純設備是不能調用的函數:

  • ID3D10Device9::GetClipPlane
  • ID3D10Device9::GetClipStatus
  • ID3D10Device9::GetLight
  • ID3D10Device9::GetLightEnable
  • ID3D10Device9::GetMaterial
  • ID3D10Device9::GetPixelShaderConstantF
  • ID3D10Device9::GetPixelShaderConstantI
  • ID3D10Device9::GetPixelShaderConstantB
  • ID3D10Device9::GetRenderState
  • ID3D10Device9::GetSamplerState
  • ID3D10Device9::GetTextureStageState
  • ID3D10Device9::GetTransform
  • ID3D10Device9::GetVertexShaderConstantF
  • ID3D10Device9::GetVertexShaderConstantI
  • ID3D10Device9::GetVertexShaderConstantB

A second drawback of a pure device is that it does not filter any redundant state changes. When using a pure device, your application should reduce the number of state changes in the render loop to a minimum; this may include filtering state changes to make sure that states do not get set more than once. This trade-off is application dependent; if you use more than a 1000 Set calls per frame, you should consider taking advantage of the redundancy filtering that is done automatically by a non-pure device.

純設備的第二個缺點是它不會濾除任何冗餘狀態變化。當使用純設備時,應用程序應該把狀態改變減到最少,包括濾除那些對相同狀態設置超過兩次的操作。是否手動設置是依賴於應用程序的,如果你每幀使用超過1000次狀態設置,你應該考慮濾除冗餘狀態設置,雖然這種操作會在使用非純設備時會被自動執行。

As with all performance issues, the only way to know whether or not your application will perform better with a pure device is to compare your application's performance with a pure vs. non-pure device. A pure device has the potential to speed up an application by reducing the CPU overhead of the API. But be careful! For some scenarios, a pure device will slow down your application (due to the additional CPU work caused by redundant state changes). If you are not sure which type of device will work best for your application, and you do not filter redundant changes in the application, use a non-pure device.

和所有的性能問題一樣,唯一知道你的程序在純設備和非純設備下哪個性能更好的方法就是比較它們在兩種設備下的運行速度。純設備具備提高程序性能的潛力,因爲它減少了程序CPU開支。但是要特別注意對於某些場景純設備會減慢你程序的運行速度(因爲由於冗餘狀態改變增加了附加CPU操作)。如果你不知道哪種類型設備效率最高,同時你也不想做應用程序狀態的冗餘狀態改變,你應該使用非純設備。

How do I enumerate the display devices in a multi-monitor system?

我如何在多顯示器系統中列出各個顯示設備?

Enumeration can be performed through a simple iteration by the application using methods of the IDirect3D9 interface. Call GetAdapterCount to determine the number of display adapters in the system. Call GetAdapterMonitor to determine which physical monitor an adapter is connected to (this method returns an HMONITOR, which you can then use in the Win32 API GetMonitorInfo to determine information about the physical monitor). Determining the characteristics of a particular display adapter or creating a Direct3D device on that adapter is as simple as passing the appropriate adapter number in place of D3DADAPTER_DEFAULT when calling GetDeviceCaps, CreateDevice, or other methods.

可以通過使用IDirect3D9接口的函數做一個簡單的遍歷就能夠完成這個操作。調用GetAdapterCount來確定系統的顯卡數目,使用GetAdapterMonitor來確定哪個顯示器和哪塊顯卡連接(這個函數返回一個HMONITOR值,然後你可以使用Win32 API GetMonitorInfo來得到顯示器的信息)。確定某個顯卡特性或者創建D3D設備的過程都很簡單,只要用合適的顯卡編號替換GetDeviceCapsCreateDevice或者其他函數中的D3DADAPTER_DEFAULT參數。

What happened to Fixed Function Bumpmapping in D3D9?

D3D9中固定管線的Bumpmapping做了什麼?

As of Direct3D 9 we tightened the validation on cards that could only support > 2 simultaneous textures. Certain older cards only have 3 texture stages available when you use a specific alpha modulate operation. The most common usage that people use the 3 stages for is emboss bumpmapping, and you can still do this with D3D9,

D3D9中我們嚴格定義了一塊顯卡必須能夠支持同時採樣2張以上紋理。一般老的卡當你打開Alpha乘操作時最多隻有3個紋理階段。最普通的使用3個紋理階段的操作就是凹凸貼圖,在D3D9中你仍然能夠這樣做。

The height field has to be stored in the alpha channel and is used to modulate the lights contribution i.e.:

高度場被保存在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 );
}

This sample, along with other older samples, are no longer shipped in the current SDK release, and will not be shipped in future SDK releases.

這個sample和其他更老的一些sample一樣不會出現在當前的SDK中,也不會在將來發布的SDK中出現。

Geometry (Vertex) Processing

幾何(頂點)處理問題

Vertex streams confuse me how do they work?

頂點流數據讓我覺得有些糊塗,它們是怎麼工作的?

Direct3D assembles each vertex that is fed into the processing portion of the pipeline from one or more vertex streams. Having only one vertex stream corresponds to the old pre-DirectX 8 model, in which vertices come from a single source. With DirectX 8, different vertex components can come from different sources; for example, one vertex buffer could hold positions and normals, while a second held color values and texture coordinates.

D3D把管線中同時操作的多個數據流中的不同數據集中到一起放在同一個數據流中。只使用一個數據流和老的DX8之前的模型相對應,這樣頂點就只源自同一個數據流。舉個例子,一個頂點緩存可能保存位置和法向而另一個保存顏色和紋理座標。

What is a vertex shader?

什麼是頂點渲染器?

A vertex shader is a procedure for processing a single vertex. It is defined using a simple assembly-like language that is assembled by the D3DX utility library into a token stream that Direct3D accepts. The vertex shader takes as input a single vertex and a set of constant values; it outputs a vertex position (in clip-space) and optionally a set of colors and texture coordinates, which are used in rasterization. Notice that when you have a custom vertex shader, the vertex components no longer have any semantics applied to them by Direct3D and vertices are simply arbitrary data that is interpreted by the vertex shader you create.

頂點渲染器(VS)是處理單個頂點的過程。它使用類彙編的語言定義,可以被D3DX使用庫編譯爲D3D接受的符號流數據。VS把單個頂點和一系列常數作爲輸入,輸出頂點位置(在裁減空間中的)和可選的一系列顏色和紋理座標,在光柵化時被使用。注意當你使用自己定義的VS時,頂點數據就不再具備D3D定義的語法屬性,只是作爲你創建的VS的單純數據來解析。

Does a vertex shader perform perspective division or clipping?

VS做透視除法和裁減嗎?

No. The vertex shader outputs a homogenous coordinate in clip-space for the transformed vertex position. Perspective division and clipping is performed automatically post-shader.

不。VS輸出裁減空間中變換後齊次座標。透視除法和裁減在VS之後被自動執行。(嘿嘿,現在未必這樣了^_^

Can I generate geometry with a vertex shader?

我能用VS創建幾何嗎?

A vertex shader cannot create or destroy vertices; it operates on a single vertex at a time, taking one unprocessed vertex as input and outputting a single processed vertex. It can therefore be used to manipulate existing geometry (applying deformations, or performing skinning operations) but cannot actually generate new geometry per se.

VS不能夠創建或者刪除頂點。它每次只是對單個頂點做操作,輸入一個沒輸入的頂點,輸出一個處理過的頂點。它能用作操作已有頂點(做變形或者表面細節操作)但是實際上不能夠實際創建幾何。

Can I apply a custom vertex shader to the results of the fixed-function geometry pipeline (or vice-versa)?

我能夠對固定管線的幾何操作結果使用自己定義的VS嗎(或者相反)?

No. You have to choose one or the other. If you are using a custom vertex shader, then you are responsible for performing the entire vertex transformation.

不。你只能選擇做固定管線或者VS。如果使用VS,你就必須做完整的頂點變換操作。

Can I use a custom vertex shader if my hardware does not support it?

如果我硬件不支持VS,我能使用VS嗎?

Yes. The Direct3D software vertex-processing engine fully supports custom vertex shaders with a surprisingly high level of performance.

是的,D3D軟件頂點處理引擎完全支持用戶VS,性能之高讓人驚奇。

How do I determine if the hardware supports my custom vertex shader?

我怎麼知道硬件是否支持我的VS

Devices capable of supporting vertex shaders in hardware are required to fill out the D3DCAPS9::VertexShaderVersion field to indicate the version level of vertex shader they support. Any device claiming to support a particular level of vertex shader must support all legal vertex shaders that meet the specification for that level or below.

硬件被要求填充D3D設備特性中的D3DCAPS9::VertexShaderVersion域表明它支持的VS版本等級。任何聲稱支持某個等級的VS的設備必須支持所有官方的VS,滿足包括這個等級在內之前的所有特性。

How many constant registers are available for vertex shaders?

VS能夠支持多少個常數寄存器?

Devices supporting vs 1.0 vertex shaders are required to support a minimum of 96 constant registers. Devices may support more than this minimum number and can report this through the D3DCAPS9::MaxVertexShaderConst field.

支持VS1.0的設備要求支持最小96個常數寄存器。設備能夠支持更多的常數寄存器,並通過設置D3DCAPS9::MaxVertexShaderConst域讓用戶知道。

Can I share position data between vertices with different texture coordinates?

我能夠對於有不同紋理座標的頂點共享相同的位置數據嗎?

The usual example of this situation is a cube in which you want to use a different texture for each face. Unfortunately the answer is no, it's not currently possible to index the vertex components independently. Even with multiple vertex streams, all streams are indexed together.

這種情況最普通的一個例子就是繪製每個面有不同紋理的立方體。不幸的是,這個問題的答案是不行。現在對頂點數據獨立進行索引還是不可能的。即使對於多數據流,所有數據流都使用相同的索引。

When I submit an indexed list of primitives, does Direct3D process all of the vertices in the buffer, or just the ones I indexed?

當我提交了圖元的索引列表後,D3D會處理緩存中所有頂點嗎,還是隻處理我的索引列表裏的?

When using the software geometry pipeline, Direct3D first transforms all of the vertices in the range you submitted, rather than transforming them "on demand" as they are indexed. For densely packed data (that is, where most of the vertices are used) this is more efficient, particularly when SIMD instructions are available. If your data is sparsely packed (that is, many vertices are not used) then you may want to consider rearranging your data to avoid too many redundant transformations. When using the hardware geometry acceleration, vertices are typically transformed on demand as they are required.

當你使用軟件幾何處理流水線時,D3D首先處理你提交的所有頂點,而不是按照它們在索引列表裏的順序操作。對於密集打包的數據(就是大部分頂點被使用的緩存)這會更高效,部分因爲SIMD指令在處理它們。如果你的數據被分散打包(許多數據沒有被使用),你可以考慮重新安排數據以避免太多的冗餘變換。當使用夠硬件幾何加速時,硬件只會處理你要求變換的數據。

What is an index buffer?

什麼是索引緩存?

An index buffer is exactly analogous to a vertex buffer, but instead it contains indices for use in DrawIndexedPrimitive calls. It is highly recommended that you use index buffers rather than raw application-allocated memory when possible, for the same reasons as vertex buffers.

索引緩存和頂點緩存類似,但是它保存的是DrawIndexedPrimitive調用需要的索引數據。我們強烈推薦你儘可能使用使用索引緩存而不是直接程序分配內存,同樣也推薦使用頂點緩存。

I notice that 32-bit indices are a supported type; can I use them on all devices?

我注意到32位索引是D3D支持的類型,我能夠用嗎?

No. You must check the D3DCAPS9::MaxVertexIndex field to determine the maximum index value that is supported by the device. This value must be greater than 2 to the 16th power -1 (0xffff) in order for index buffers of type D3DFMT_INDEX32 to be supported. In addition, note that some devices may support 32-bit indices but support a maximum index value less than 2 to the 32nd power -1 (0xffffffff); in this case the application must respect the limit reported by the device.

不,你必須首先檢查D3DCAPS9::MaxVertexIndex域確定設備支持的最大的索引值。這個值必須大於2^161才能真正支持D3DFMT_INDEX32。同時還要注意有些設備支持32位索引但是它的最大索引不是 2^32 1。在這種情況下程序必須遵循設備的限制。

Does S/W vertex processing support 64 bit?

軟件頂點處理支持64位操作嗎?

There is an optimized s/w vertex pipeline for x64, but it does not exist for IA64.

對於x64有優化過的軟件頂點流水線,但是不支持IA64

X64就是基於 x86 架構的64CPU AMD 64CPU 就是用這種的全稱應該是 X86-64

IA64
intel面向高端的新架構 IPF64 CPU 這種CPU 是不能兼容原先的 X86 下使用的程序,也就是說現在的windows程序都無法在這種CPU下面運行。

Performance Tuning

性能問題

How can I improve the performance of my Direct3D application?

我怎麼樣才能提高D3D程序的性能?

The following are key areas to look at when optimizing performance:

下面是提高性能的一些要點:

Batch size

批處理數據量

Direct3D is optimized for large batches of primitives. The more polygons that can be sent in a single call, the better. A good rule of thumb is to aim to average 1000 vertices per primitive call. Below that level you're probably not getting optimal performance, above that and you're into diminishing returns and potential conflicts with concurrency considerations (see below).

D3D對大量圖元數據處理有優化。一次函數調用處理的多邊形越多,效率越高。一個比較好的規則就是平均每次函數調用處理1000個圖元。在這個數量之下你很難優化性能,在此之上你則會減少返回次數以及與其他優化考慮(看下文)的潛在衝突。

State changes

狀態改變

Changing render state can be an expensive operation, particularly when changing texture. For this reason, it is important to minimize as much as possible the number of state changes made per frame. Also, try to minimize changes of vertex or index buffer.

改變繪製狀態會成爲代價昂貴的操作,特別是在改變紋理時。因爲如此,所以要儘可能的減少每幀的狀態改變操作。同樣也要儘量減少頂點緩存或者索引緩存的切換。

Note    As of DirectX 8, the cost of changing vertex buffer is no longer as expensive as it was with previous versions, but it is still good practice to avoid vertex buffer changes where possible.

注意:和DX8一樣,改變頂點緩存不再和從前版本一樣耗時,但是減少頂點緩存切換仍然是良好的操作。

Concurrency

並行操作

If you can arrange to perform rendering concurrently with other processing, then you will be taking full advantage of system performance. This goal can conflict with the goal of reducing renderstate changes. You need to strike a balance between batching to reduce state changes and pushing data out to the driver early to help achieve concurrency. Using multiple vertex buffers in round-robin fashion can help with concurrency.

如果你能夠把繪製操作和其他操作並行執行,你的性能能得到顯著提高。這個目標可能和減少繪製狀態改變相重度。你需要平衡批處理數據量以減少繪製狀態改變,並且在早期就把數據發送到驅動中以獲得並行性。使用多頂點緩存輪流操作能夠促進並行性。

Texture uploads

紋理上傳

Uploading textures to the device consumes bandwidth and causes a bandwidth competition with vertex data. Therefore, it is important to not to over commit texture memory, which would force your caching scheme to upload excessive quantities of textures each frame.

上傳紋理到設備上會消耗帶寬並引起和頂點數據的帶寬衝突。同時還要注意紋理不要超過紋理內存大小,否則你的高速緩存機制會被強迫每幀上傳大量的紋理數據。

Vertex and index buffers

頂點緩存和索引緩存

You should always use vertex and index buffers, rather than plain blocks of application allocated memory. At a minimum, the locking semantics for vertex and index buffers can avoid a redundant copy operation. With some drivers, the vertex or index buffer may be placed in more optimal memory (perhaps in video or AGP memory) for access by the hardware.

你應該儘量使用頂點和索引緩存而不是完全由程序分配內存,因爲至少頂點(索引)緩存的鎖定機制能夠避免冗餘的拷貝操作。在一些驅動中,頂點(索引)緩存會被放到更優化的內存中(可能是在顯存或者AGP內存中)被硬件讀取。

State macro blocks

狀態宏模塊

These were introduced in DirectX 7.0. They provide a mechanism for recording a series of state changes (including lighting, material and matrix changes) into a macro, which can then be replayed by a single call. This has two advantages:

這是在DX7中引入的概念。它提供了一個機制記錄一系列狀態改動(包括光照,材質和矩陣改變)到宏中,並且能用一個函數調用重現。它由兩個優點:

  • You reduce the call overhead by making one call instead of many.
  • 減少了函數調用次數
  • An aware driver can pre-parse and pre-compile the state changes, making it much faster to submit to the graphics hardware.
  • 驅動能夠預解析和編譯狀態改動,使之對硬件效率更高

State changes can still be expensive, but using state macros can help reduce at least some of the cost. Use only a single Direct3D device. If you need to render to multiple targets, use SetRenderTarget. If you are creating a windowed application with multiple 3D windows, use the CreateAdditionalSwapChain API. The runtime is optimized for a single device and there is a considerable speed penalty for using multiple devices.

狀態改動仍然是耗時的,但是使用狀態宏能夠幫助你降低一些代價。儘量使用一個D3D設備,如果你需要繪製到多個對象上就使用SetRenderTarget函數來切換對象。如果你要創建一個擁有多個3D窗口的Windows窗口程序,使用CreateAdditionalSwapChain函數即可完成。對單個設備運行時間會有優化,而使用多個設備還會降低單個運行速度。

Which primitive types (strips, fans, lists and so on) should I use?

我應改使用哪種類型圖元?

Many meshes encountered in real data feature vertices that are shared by multiple polygons. To maximize performance it is desirable to reduce the duplication in vertices transformed and sent across the bus to the rendering device. It is clear that using simple triangle lists achieves no vertex sharing, making it the least optimal method. The choice is then between using strips and fans, which imply a specific connectivity relationship between polygons and using indexed lists. Where the data naturally falls into strips and fans, these are the most appropriate choice, since they minimize the data sent to the driver. However, decomposing meshes into strips and fans often results in a large number of separate pieces, implying a large number of DrawPrimitive calls. For this reason, the most efficient method is usually to use a single DrawIndexedPrimitive call with a triangle list. An additional advantage of using an indexed list is that a benefit can be gained even when consecutive triangles only share a single vertex. In summary, if your data naturally falls into large strips or fans, use strips or fans; otherwise use indexed lists.

許多mesh會相交在一些被多個多邊形共享的頂點上。爲了得到最優性能,應該儘量減少對相同頂點重複的變換和發送到設備的數據總線上。對於沒有共享頂點的數據可以使用簡單的三角形鏈表,它是優化最少的方法。選擇在三角形條帶和三角形扇面和使用索引鏈表之間的展開,條帶和扇面分別默認定義了多邊形之間特殊的連接關係。如果數據自然形成條帶或者扇面,它們分別就是最合適的選擇,因爲這就是送往顯卡的最小數據。當然,把mesh分解爲條帶或者扇形通常會導致大量的小碎片,這意味中大量的DrawPrimitive調用。因爲如此,最有效的方法通常是使用DrawIndexedPrimitive函數調用索引鏈表。使用索引鏈表的另一個好處是當連續的三角形共享一個頂點時能夠被優化。總之,除非你的數據天生就是三角形條帶或者扇形,否則還是使用索引鏈表比較合適。

How do you determine the total texture memory a card has, excluding AGP memory?

怎麼確定一塊顯卡總的紋理顯存是多少,不包括AGP顯存?

IDirect3DDevice9::GetAvailableTextureMem() returns the total available memory, including AGP. Allocating resources based on an assumption of how much video memory you have is not a great idea. For example, what if the card is running under a Unified Memory Architecture (UMA) or is able to compress the textures? There might be more space available than you might have thought. You should create resources and check for 'out of memory' errors, then scale back on the textures. For example, you could remove the top mip-levels of your textures.

IDirect3DDevice9::GetAvailableTextureMem()返回包括AGP顯存在內總的顯存數量。基於有多少顯存來分配資源並不是一個好主意。舉個例子說,如果你的卡使用統一內存架構(UMA)或者能夠壓縮紋理,它的顯存是多少?它會比你想像的多的多。你應該創建資源並判斷它有沒有返回“超出內存”錯誤,然後減少紋理大小,比如移除最高層的Mipmap

What's a good usage pattern for vertex buffers if I'm generating dynamic data?

創建動態數據時,應該按怎麼樣的模式操作?

  1. Create a vertex buffer using the D3DUSAGE_DYNAMIC and D3DUSAGE_WRITEONLY usage flags and the D3DPOOL_DEFAULT pool flag. (Also specify D3DUSAGE_SOFTWAREPROCESSING if you are using software vertex processing.)

使用D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLYD3DPOOL_DEFAULT創建頂點緩存(如果使用軟件頂點緩存的話使用D3DUSAGE_SOFTWAREPROCESSING)

  1. I = 0.
  2. Set state (textures, renderstates and so on).

檢查狀態(紋理狀態,繪製狀態等等)

  1. Check if there is space in the buffer, that is, for example, I + M <= N? (Where M is the number of new vertices).

檢查緩存中是否有多餘空間,比如I+M<=N?(M代表新頂點數據)

  1. If yes, then Lock the VB with D3DLOCK_NOOVERWRITE. This tells Direct3D and the driver that you will be adding vertices and won't be modifying the ones that you previously batched. Therefore, if a DMA operation was in progress, it isn't interrupted. If no, goto 11.

如果有,使用D3DLOCK_NOOVERWRITE鎖定頂點緩存。這告訴D3D和設備你要添加新的頂點到緩存中,但是不改變原有頂點數據。並且如果使用DMA操作的話,它不會被打斷。如果沒有,跳轉到11

  1. Fill in the M vertices at I.

I處填充M個頂點

  1. Unlock.

解除鎖定

  1. Call Draw[Indexed]Primitive. For non-indexed primitives use I as the StartVertex parameter. For indexed primitives, ensure the indices point to the correct portion of the vertex buffer (it may be easiest to use the BaseVertexIndex parameter of the SetIndices call to achieve this).

調用Draw[Indexed]Primitive。對於沒有索引的圖元,使用I作爲開始頂點參數。對於索引數據,保證索引指向VB中正確的位置(最簡單的,使用BaseVertexIndex作爲SetIndeces調用的參數)。

  1. I += M.
  2. Goto 3.
  3. Ok, so we are out of space, so let us start with a new VB. We don't want to use the same one because there might be a DMA operation in progress. We communicate to this to Direct3D and the driver by locking the same VB with the D3DLOCK_DISCARD flag. What this means is "you can give me a new pointer because I am done with the old one and don't really care about the old contents any more."

如果超出範圍,就創建一個新的VB。我們不想用相同的數據因爲當前可能有一個DMA操作。我們使用D3DLOCK_DISCARD標記通知D3D和設備鎖定相同的VB。這告訴它們“你們能夠給我一個新的指針因爲我已經用過了舊的數據並不再需要它們了。”

  1. I = 0.
  2. Goto 4 (or 6).

Why do I have to specify more information in the D3DVERTEXELEMENT9 structure?

我爲什麼在D3DVERTEXELEMENT9結構中要定義更多的信息?

As of Direct3D 9, the vertex stream declaration is no longer just a DWORD array, it is now an array of D3DVERTEXELEMENT9 structures. The runtime makes use of the additional semantic and usage information to bind the contents of vertex streams to vertex shaders input registers/variables. For Direct3D 9, vertex declarations are decoupled from vertex shaders, which makes it easier to use shaders with geometries of different formats as the runtime only binds the data that the shader needs.

D3D9中,頂點數據流申明不再是一組DWORD數組,它現在是一個D3DVERTEXELEMENT9數據結構。運行時程序使用附加的語法和用法信息把頂點數據流內容綁定到VS的數據寄存器和變量上。對於D3D9,頂點申明和VS的申明是對應的,不同格式的幾何能夠僅僅綁定VS需要的數據到shader上,使shader的使用更簡單。

The new vertex declarations can be used with either the fixed function pipeline or with shaders. For the fixed function pipeline, there is no need to call SetVertexShader. If however, you want to switch to the fixed function pipeline and have previously used a vertex shader, call SetVertexShader(NULL). When this is done, you will still need to call SetFVF to declare the FVF code.

新的頂點申明既能被固定管線使用也能被shader使用。對於固定管線就不必調用SetVertexShader。如果你需要在固定管線和VS之前切換,可以調用SetVertexShaderNULL)。如果這樣做的話,你仍然需要調用SetFVF來申明FVF格式。

When using vertex shaders, call SetVertexShader with the vertex shader object. Additionally, call SetFVF to set up a vertex declaration. This uses the information implicit in the FVF. SetVertexDeclaration can be called in place of SetFVF because it supports vertex declarations that cannot be expressed with an FVF.

當使用VS時,調用SetVertexShader設置VS對象。調用SetFVF使用FVF定義的信息設置頂點申明。SetVertexDeclaration能夠替代SetFVF,因爲它能夠支持FVF所不能表達的頂點申明。

D3DX Utility Library

D3DX實用庫問題

What file formats are supported by the D3DX image file loader functions?

D3DX圖像文件導入函數支持那些格式圖像?

The D3DX image file loader functions support BMP, TGA, JPG, DIB, PPM and DDS files.

支持BMPTGAJPGDIBPPMDDS文件。

The text rendering functions in D3DX don't seem to work, what am I doing wrong?

D3DX的文本繪製函數似乎不工作,是我做錯了嗎?

A common mistake when using the ID3DXFont::DrawText functions is to specify a zero alpha component for the color parameter; resulting in completely transparent (that is, invisible) text. For fully opaque text, ensure that the alpha component of the color parameter is fully saturated (255).

使用ID3DXFont::DrawText函數常犯的錯誤就是給顏色參數定義了一個alpha通道爲0的顏色值,導致文本完全透明(也就是不可見)。對於不透明文本,保證顏色參數alpha通道爲最大值(255)。

How can I save the contents of a surface or texture to a file?

我怎麼樣才能保存一個surface或者紋理到文件中?

The DirectX 8.1 SDK added two functions to the D3DX library specifically for this purpose: D3DXSaveSurfaceToFile() and D3DXSaveTextureToFile(). These functions support saving an image to file in either BMP or DDS format. In previous versions you will have to lock the surface and read the image data, then write it to a bitmap file. An article on writing a function to store bitmaps can be found at Windows GDI: Storing an Image.

DX8.1SDKD3DX庫增加兩個庫函數來完整這個操作:D3DXSaveSurfaceToFile()D3DXSaveTextureToFile()。這兩個函數支持保存圖像到BMP或者DDS格式中。在過去的版本中,你不得不鎖定surface然後讀取圖像數據,然後寫入bmp文件中。編寫保存bmp文件的文章可以在GDI: Storing an Image一節中找到。

Alternatively, GDI+ could be used to save the image in a wide variety of formats, though this requires additional support files to be distributed with your application.

同樣的,GDI+能夠用做保存圖像到大量的格式中,雖然這需要你的程序支持文件分發。

How can I make use of the High Level Shader Language (HLSL) in my game?

在我的遊戲中怎麼使用HLSL

There are three ways that the High Level Shading Language can be incorporated into your game engine:

有三種方法支持HLSL在遊戲中插入:

  • Compile your shader source into vertex or pixel shading assembly (using the command line utility fxc.exe) and use D3DXAssembleShader() at run time. This way even a DirectX 8 game can even take advantage of the power of the HLSL.
  • 編譯Shader源代碼成VS或者PS彙編(使用fxc.exe)並在運行時調用D3DXAssembleShader()。這種方法可以使DX8以上的遊戲都能使用HLSL
  • Use D3DXCompileShader() to compile your shader source into token stream and constant table form. At run time load the token stream and constant table and call CreateVertexShader() or CreatePixelShader() on the device to create your shaders.
  • 使用D3DXCompileShader()編譯Shader爲符號流和常數表,在運行時符號流和常數表被CreateVertexShader()或者CreatePixelShader()導入到設備中。
  • The easiest way to get up and running is to take advantage of the D3DX Effects system by calling D3DXCreateEffectFromFile() or D3DXCreateEffectFromResource() with your effect file.
  • 最簡單的方法是使用D3DX Effect系統,調用D3DXCreateEffectFromFile()或者D3DXCreateEffectFromResource()打開效果文件。

What is the correct way to get shaders from an Effect?

Effect中得到shader的正確方法是什麼?

Use D3DXCreateEffect to create an ID3DXEffect and then use GetPassDesc to retrieve a D3DXPASS_DESC. This structure contains pointers to vertex and pixel shaders.

使用D3DXCreateEffect創建ID3DXEffect對象然後使用GetPassDesc獲得D3DXPASS_DESC結構,這個結構包含VSPS指針

Do not use ID3DXEffectCompiler::GetPassDesc. Vertex and pixel shader handles returned from this method are NULL.

不要使用ID3DXEffectCompiler::GetPassDesc,這個函數返回的VSPS指針爲NULL

What is the HLSL noise() intrinsic for?

HLSLnoise()函數是做什麼的?

The noise intrinsic function generates perlin noise as defined by Ken Perlin. The HLSL function can currently only be used to fill textures in texture shaders as current h/w does not support the method natively. Texture shaders are used in conjuction with the D3DXFill*Texture() functions which are useful helper functions to generate procedurally defined textures during load time.

噪音內置函數產生perlin噪音。這個HLSL函數目前只能在紋理shader中用作填充紋理,因爲當前的硬件還沒有直接支持這個函數。紋理shaderD3DXFill*Texture()中使用。這個函數在載入時創建過程紋理非常有用。

How do I detect whether to use pixel shader model 2.0 or 2.a?

我怎麼確定是否使用PS2.0還是PS2.a

You can use the D3DXGetPixelShaderProfile() and D3DXGetPixelShaderProfile() functions which return a string determining what HLSL profile is best suited to the device being ran.

你能夠使用D3DXGetPixelShaderProfile()D3DXGetPixelShaderProfile()函數,它們會返回一個字符串,確定哪個HLSL profile是最適合在設備上運行的。

How do I access the Parameters in my Precompiled Effects Shaders?

在我預編譯好的Effect Shader中怎麼操作參數值?

Through the ID3DXConstantTable interface which is used to access the constant table. This table contains the variables that are used by high-level language shaders and effects.

通過ID3DXConstantTable操作常數表。這個表保存了HLSL shadereffect的變量內容。

Is there a way to add user data to an effect or other resource?

有辦法添加用戶數據到effect或者其他數據上嗎?

Yes, to set private data you call SetPrivateData (pReal is the D3D texture object, pSpoof is the wrapped texture object).

是的,你可以通過調用SetPrivateData設置個人數據(pRealD3D紋理對象,pSpoof是包含用戶數據的紋理對象)

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

To look up the wrapped pointer:

查找用戶數據紋理對象指針:

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

Why does rendering of an ID3DXMesh object slow down significantly after I define subsets?

在我定義了mesh子集之後,爲什麼繪製ID3DXMesh對象會明顯慢下來呢?

You probably have not optimized the mesh after defining the face attributes. If you specify attributes and then call ID3DXMesh::DrawSubset(), this method must perform a search of the mesh for all faces containing the requested attributes. In addition, the rendered faces are likely in a random access pattern, thus not utilizing vertex cache. After defining the face attributes for your subsets, call the ID3DXMesh::Optimize or ID3DXMesh::OptimizeInPlace methods and specifying an optimization method of D3DXMESHOPT_ATTRSORT or stronger. Note that for optimum performance you should optimize with the D3DXMESHOPT_VERTEXCACHE flag, which will also reorder vertices for optimum vertex cache utilization. The adjacency array generated for a D3DX Mesh has three entries per face, but some faces may not have adjacent faces on all three edges. How is this encoded? Entries where there are no adjacent faces are encoded as 0xffffffff.

你可能在定義了面屬性之後沒有優化mesh。如果你定義了屬性後就調用ID3DXMesh::DrawSubset(),這個函數就會搜索mesh的所有表面找到擁有所需的屬性的表面。同時,這些表面也是隨機被繪製,很難利用vertex cache加速。在定義了表面子集屬性後,調用ID3DXMesh::OptimizeID3DXMesh::OptimizeInPlace並使用D3DXMESHOPT_ATTRSORT或者更好的排序準則來優化。注意要得到最優性能的話,你必須D3DXMESHOPT_VERTEXCACHE優化,這樣可以充分利用vertex cache。一個D3DX mesh的鄰接數據對每個表面有三個頂點,但是一些表面可能在所有三條邊上都沒有鄰接頂點。這種情況下怎麼編碼呢?那麼對於沒有鄰接頂點的表面鄰接值設置爲0xffffffff

I've heard a lot about Pre-computed Radiance Transfer (PRT), where can I learn more?

俺聽說PRT很牛叉,咋整的吶?

PRT is a new feature of D3DX added in the Summer 2003 SDK Update. It enables rendering of complex lighting scenarios such as global -llumination, soft shadowing and sub-surface scatter in real time. The SDK contains documentation and samples of how to integrate the technology into your game. The PRT Demo Sample and LocalDeformablePRT Sample samples demonstrate how to use the simulator for per vertex and per pixel lighting scenarios respectively. Further information about this and other topics can also be found at Peter Pike Sloan's Web page.

PRTMS的鎮派絕學,閒雜人等一概迴避,要學先投個簡歷先。

How can I render to a texture and make use of Anti Aliasing?

我怎麼樣才能繪製到一張紋理上,並且用上反走樣?

Create a multisampled render target using Direct3DDevice9::CreateRenderTarget. After rendering the scene to that render target, StretchRect from it to a render target texture. If you make any changed to the offscreen textre (such as blurring or blooming it), copy it back to the back buffer before you present().

使用Direct3DDevice9::CreateRenderTarget創建多采樣RenderTarget。在把場景繪製到這個RenderTarget後,用StretchRet把它拷到一個Rendertarget紋理上。如果你對屏幕外的紋理作合任何操作(比如模糊或者擴散),在你調用persent() 顯示之前把它拷回到back buffer上。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章