在 Direct3D 10 中使用著色器
管線有三個著色器階段,每個階段都是使用 HLSL 著色器進行程式設計。 所有 Direct3D 10 著色器都是以 HLSL 撰寫,以著色器模型 4 為目標。
Direct3D 9 與 Direct3D 10 之間的差異:
- 不同于可使用中繼元件語言撰寫的 Direct3D 9 著色器模型,著色器模型 4.0 著色器只會在 HLSL 中撰寫。 仍支援將著色器離線編譯成裝置消費性位元組程式碼,並建議在大部分情況下使用。
這個範例只會使用頂點著色器。 由於所有著色器都是從常見的著色器核心建置,因此瞭解如何使用頂點著色器與使用幾何或圖元著色器非常類似。
當您撰寫 HLSL 著色器 (此範例使用頂點著色器 HLSLWithoutFX.vsh) 之後,您必須針對將使用它的特定管線階段進行準備。 若要這樣做,您需要:
您必須針對管線中的每個著色器重複這些步驟。
編譯著色器
第一個步驟是編譯著色器,以檢查您是否已正確編碼 HLSL 語句。 這是藉由呼叫 D3D10CompileShader 並提供數個參數來完成,如下所示:
IPD3D10Blob * pBlob;
// Compile the vertex shader from the file
D3D10CompileShader( strPath, strlen( strPath ), "HLSLWithoutFX.vsh",
NULL, NULL, "Ripple", "vs_4_0", dwShaderFlags, &pBlob, NULL );
此函式採用下列參數:
檔案名 (和包含著色器之位元組名稱字串的長度) 。 此範例只會使用 HLSLWithoutFX.vsh 檔案中的頂點著色器 (,其中副檔名 .vsh 是頂點著色器的縮寫) 。
著色器函式名稱。 此範例會從一個輸入來編譯一個頂點著色器,並傳回輸出結構, (函式來自 HLSLWithoutFX 範例) :
VS_OUTPUT Ripple( in float2 vPosition : POSITION )
著色器使用之所有宏的指標。 使用D3D10_SHADER_MACRO來協助定義宏;只要建立名稱字串,其中包含所有宏名稱, (每個名稱都以空格分隔) ,而定義字串 (每個宏主體以空格分隔) 。 這兩個字串都必須以 Null 終止。
要編譯著色器所需的任何其他檔案指標。 這會使用 ID3D10Include 介面,其中包含兩個使用者實作的方法:Open 和 Close。 若要這樣做,您必須實作 Open 和 Close 方法的主體;在 Open 方法中,新增您要用來開啟任何包含檔案的程式碼,請在 Close 函式中新增程式碼,以在完成檔案時關閉檔案。
要編譯的著色器函式名稱。 此著色器會編譯一個一文函式。
編譯時要設為目標的著色器設定檔。 由於您可以將函式編譯成頂點、幾何或圖元著色器,因此設定檔會告知編譯器哪一種著色器類型,以及要比較程式碼與哪一種著色器模型。
著色器編譯器旗標。 這些旗標會告訴編譯器要將哪些資訊放入編譯的輸出中,以及您希望輸出程式碼優化的方式:速度、偵錯等。如需可用旗 標的清單,請參閱效果常數 (Direct3D 10) 。 此範例包含一些程式碼,可用來設定專案的編譯器旗標值 - 這主要是您想要產生偵錯資訊的問題。
緩衝區的指標,其中包含已編譯的著色器程式碼。 緩衝區也包含編譯器旗標所要求的任何內嵌偵錯和符號資料表資訊。
緩衝區的指標,其中包含編譯期間遇到的錯誤和警告清單,這與您在編譯著色器時執行偵錯工具時在偵錯輸出中看到的相同訊息。 當您 不想要將錯誤傳回緩衝區時,Null 是可接受的值。
如果著色器成功編譯,著色器程式碼的指標會以 ID3D10Blob 介面傳回。 它稱為 Blob 介面,因為指標是記憶體中由 DWORD 陣列組成的位置。 提供 介面,讓您可以取得下一個步驟中所需之已編譯著色器的指標。
從 2006 年 12 月 SDK 開始,DirectX 10 HLSL 編譯器現在是 DirectX 9 和 DirectX 10 中的預設編譯器。 如需詳細資訊,請參閱 Effect-Compiler Tool 。
取得已編譯著色器的指標
數個 API 方法需要已編譯著色器的指標。 這個引數通常稱為 pShaderBytecode ,因為它指向以位元組程式碼序清單示的已編譯著色器。 若要取得已編譯著色器的指標,請先呼叫 D3D10CompileShader 或類似的函式來編譯著色器。 如果編譯成功,則會在 ID3D10Blob 介面中傳回已編譯的著色器。 最後,使用 GetBufferPointer 方法來傳回指標。
建立著色器物件
編譯著色器之後,請呼叫 CreateVertexShader 來建立著色器物件:
ID3D10VertexShader ** ppVertexShader
ID3D10Blob pBlob;
// Create the vertex shader
hr = pd3dDevice->CreateVertexShader( (DWORD*)pBlob->GetBufferPointer(),
pBlob->GetBufferSize(), &ppVertexShader );
// Release the pointer to the compiled shader once you are done with it
pBlob->Release();
若要建立著色器物件,請將已編譯著色器的指標傳遞至 CreateVertexShader。 由於您必須先成功編譯著色器,因此除非您電腦上發生記憶體問題,否則此呼叫幾乎會傳遞。
您可以視需要建立許多著色器物件,只要保留它們的指標即可。 當您呼叫編譯方法) 介面名稱時,當您呼叫 create 方法) 時,這個相同的機制適用于幾何和圖元著色器,假設您呼叫編譯方法) ( (著色器設定檔。
設定著色器物件
最後一個步驟是將著色器設定為管線階段。 由於管線中有三個著色器階段,因此您必須進行三個 API 呼叫,每個階段各一個。
// Set a vertex shader
pd3dDevice->VSSetShader( g_pVS10 );
對 VSSetShader 的呼叫會採用步驟 1 中所建立頂點著色器的指標。 這會設定裝置中的著色器。 頂點著色器階段現在已使用其頂點著色器程式碼初始化,所有保留都是初始化任何著色器變數。
針對所有 3 個著色器階段重複
重複這些相同的步驟集,以建置任何頂點或圖元著色器,甚至是輸出至圖元著色器的幾何著色器。