共用方式為


編譯效果 (Direct3D 11)

撰寫效果之後,下一個步驟是編譯器代碼來檢查語法問題。

您可以呼叫其中一個編譯 API (D3DX11CompileFromFileD3DX11CompileFromMemoryD3DX11CompileFromResource ) 。 這些 API 會叫用效果編譯器fxc.exe,以編譯 HLSL 程式碼。 這就是為什麼效果中的程式碼語法看起來非常類似 HLSL 程式碼。 (稍後會處理幾個例外狀況) 。 效果編譯器/hlsl 編譯器fxc.exe可在 [公用程式] 資料夾中的 SDK 中使用,因此如果您選擇的話,著色器 (或效果) 可以離線編譯。 請參閱從命令列執行編譯器的檔。

範例

以下是編譯效果檔案的範例。

WCHAR str[MAX_PATH];
DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"BasicHLSL10.fx" );

hr = D3DX11CompileFromFile( str, NULL, NULL, pFunctionName, pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL, NULL, &pBlob, &pErrorBlob, NULL );

Includes

編譯 API 的其中一個參數是 include 介面。 如果您想要在編譯器讀取 Include 檔案時包含自訂行為,請產生其中一個。 編譯器會在每次建立或編譯使用 include 指標) 的效果 (執行這個自訂行為。 若要實作自訂的 Include 行為,請從 ID3DInclude 介面衍生類別。 這會提供您的類別和兩種方法: OpenClose。 在這些方法中實作自訂行為。

搜尋 Include 檔案

編譯器將 pParentData 參數傳遞至 include 處理常式 Open 方法的指標,可能不會指向包含編譯器編譯器代碼所需#include檔案的容器。 也就是說,編譯器可能會在pParentData中傳遞Null。 因此,我們建議您的 include 處理常式搜尋自己的內容包含位置清單。 您的 Include 處理常式可以在呼叫其 Open 方法時動態新增包含位置。

在下列範例中,假設著色器程式碼的 Include 檔案都儲存在 某處else 目錄中。 當編譯器呼叫 include 處理常式的 Open 方法以開啟並讀取 某處else\foo.h的內容時,include 處理常式可以儲存 某處else 目錄的位置。 稍後,當編譯器呼叫 include 處理常式的Open方法以開啟並讀取bar.h的內容時,include 處理常式可以在bar.h的某處自動搜尋。

Main.hlsl:
#include "somewhereelse\foo.h"

Foo.h:
#include "bar.h"

巨集

效果編譯也可以取得其他位置所定義之宏的指標。 例如,假設您想要修改 BasicHLSL10 中的效果,以使用兩個宏:零和一。 此處會顯示使用兩個宏的效果程式碼。

if( bAnimate )
    vAnimatedPos += float4(vNormal, zero) *  
        (sin(g_fTime+5.5)+0.5)*5;
        
    Output.Diffuse.a = one;         

以下是兩個宏的宣告。

D3D10_SHADER_MACRO Shader_Macros[3] = { "zero", "0", "one", "1.0f", NULL, NULL };

宏是 Null 終止的宏陣列;其中每個宏都是使用 D3D10_SHADER_MACRO 結構來定義。

修改編譯效果呼叫,以取得宏的指標。

D3DX11CompileFromFile( str, Shader_Macros, NULL, pFunctionName, 
                       pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL, 
                       NULL, &pBlob, &pErrorBlob, NULL );    

HLSL 著色器旗標

著色器旗標會將著色器條件約束指定給 HLSL 編譯器。 這些旗標會以下列方式影響著色器編譯器所產生的程式碼:

  • 優化程式碼大小。
  • 包括防止流量控制的偵錯資訊。
  • 影響編譯目標,以及著色器是否可以在舊版硬體上執行。

如果您尚未指定兩個衝突的特性,則可以以邏輯方式結合這些旗標。 如需旗標的清單,請參閱 D3D10_SHADER 常數

FX 旗標

當您建立效果以定義編譯行為或執行時間效果行為時,請使用這些旗標。 如需旗標的清單,請參閱 D3D10_EFFECT 常數

檢查錯誤

如果在編譯期間發生錯誤,API 會傳回包含效果編譯器錯誤的介面。 這個介面稱為 ID3DBlob。 它無法直接讀取;不過,藉由傳回包含資料 (為字串) 緩衝區的指標,您可以看到任何編譯錯誤。

此範例包含 BasicHLSL.fx 中的錯誤,第一個變數宣告會發生兩次。

//-------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------
float4 g_MaterialAmbientColor;      // Material's ambient color

// Declare the same variable twice
float4 g_MaterialAmbientColor;      // Material's ambient color

此錯誤會導致編譯器傳回下列錯誤,如 Microsoft Visual Studio 中 [監看式] 視窗的下列螢幕擷取畫面所示。

visual Studio watch視窗的螢幕擷取畫面,發生0x01997fb8錯誤

因為編譯器會在 LPVOID 指標中傳回錯誤,所以請將它轉換成 [監看式] 視窗中的字元字串。

以下是從失敗編譯傳回錯誤的程式碼。

// Read the D3DX effect file
WCHAR str[MAX_PATH];
ID3DBlob*   l_pBlob_Effect = NULL;
ID3DBlob*   l_pBlob_Errors = NULL;
hr = DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"BasicHLSL10.fx" );
hr = D3DX11CompileFromFile( str, NULL, NULL, pFunctionName, 
                       pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL, 
                       NULL, &pBlob, &pErrorBlob, NULL );      

LPVOID l_pError = NULL;
if( pErrorBlob )
{
    l_pError = pErrorBlob->GetBufferPointer();
    // then cast to a char* to see it in the locals window
}

(Direct3D 11) 轉譯效果