Freigeben über


Kompilieren eines Effekts (Direct3D 10)

Nachdem ein Effekt erstellt wurde, besteht der erste Schritt darin, den Code zu kompilieren, um auf Syntaxprobleme zu überprüfen. Dazu rufen Sie eine der Kompilierungs-APIs auf (z. B. D3DX10CompileEffectFromFile, D3DX10CompileEffectFromResource, D3DX10CompileEffectFromMemory). Diese API's rufen den Effektcompiler fxc.exe auf, bei dem es sich um den Compiler handelt, der zum Kompilieren von HLSL-Code verwendet wird. Aus diesem Grund sieht die Syntax für Code in einem Effekt sehr ähnlich wie HLSL-Code aus (es gibt einige Ausnahmen, die später behandelt werden). Übrigens befindet sich der Effektcompiler/hlsl-Compiler (fxc.exe) im SDK im Ordner "Hilfsprogramme", sodass Sie Ihre Shader (oder Effekte) nach Bedarf offline kompilieren können. Weitere Informationen finden Sie in der Dokumentation zum Ausführen des Compilers über die Befehlszeile.

Hier sehen Sie ein Beispiel für das Kompilieren einer Effektdatei (aus dem BasicHLSL10-Beispiel).

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

hr = D3DX10CompileEffectFromFile( str, NULL, NULL, "fx_4_0", 
    D3D10_SHADER_ENABLE_STRICTNESS, 0, pd3dDevice, NULL, NULL, 
    &l_pBlob_Effect, &l_pBlob_Errors, NULL );

Includes

Ein Parameter ist eine Include-Schnittstelle. Generieren Sie eines davon, wenn Sie beim Lesen einer Includedatei ein angepasstes Verhalten einschließen möchten. Dieses benutzerdefinierte Verhalten wird jedes Mal ausgeführt, wenn ein Effekt (der den include-Zeiger verwendet) erstellt wird oder wenn ein Effekt (der den Includezeiger verwendet) kompiliert wird. Um angepasstes Include-Verhalten zu implementieren, leiten Sie eine Klasse von der Include-Schnittstelle ab. Dies stellt Ihre zwei Methoden der Klasse bereit: Open und Close. Implementieren Sie das benutzerdefinierte Verhalten in den Open- und Close-Methoden.

Makros

Bei der Effektkompilierung kann auch ein Zeiger auf Makros erfolgen, die an anderer Stelle definiert sind. Angenommen, Sie würden den Effekt in BasicHLSL10 ändern, um zwei Makros zu verwenden: null und eins. Der Effektcode, der die beiden Makros verwendet, wird hier gezeigt.

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

Hier ist die Deklaration für die beiden Makros.

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

Die Makros sind ein NULL-beendetes Array von Makros. wobei jedes Makro mit einer D3D_SHADER_MACRO Struktur definiert ist.

Ändern Sie schließlich den Aufruf des Kompilierungseffekts, um einen Zeiger auf die Makros zu nehmen.

D3DX10CreateEffectFromFile( str, Shader_Macros, NULL, 
    D3D10_SHADER_ENABLE_STRICTNESS, 0, pd3dDevice, NULL, NULL, 
    &g_pEffect10, NULL );

HLSL-Shaderflags

Shaderflags geben Shadereinschränkungen für den HLSL-Compiler an. Diese Flags wirken sich auf den vom Shadercompiler generierten Code aus, einschließlich:

  • Überlegungen zur Größe: Optimieren sie den Code.
  • Debugüberlegungen: Einschließlich Debuginformationen, die die Ablaufsteuerung verhindern.
  • Hardwareüberlegungen: Das Kompilierungsziel und die Angabe, ob ein Shader auf Legacyhardware ausgeführt werden kann.

Im Allgemeinen können diese Flags logisch kombiniert werden, vorausgesetzt, Sie haben nicht zwei widersprüchliche Merkmale angegeben. Eine Auflistung der Flags finden Sie unter Effektkonstanten (Direct3D 10).

FX-Flags

Diese Flags werden beim Erstellen eines Effekts verwendet, um entweder kompilierungs- oder Laufzeiteffektverhalten zu definieren. Eine Auflistung der Flags finden Sie unter Effektkonstanten (Direct3D 10).

Überprüfen von Fehlern

Wenn während der Kompilierung ein Fehler auftritt, gibt die API eine Schnittstelle zurück, die die vom Effektcompiler zurückgegebenen Fehler enthält. Diese Schnittstelle heißt ID3D10Blob. Es ist nicht direkt lesbar. Wenn Sie jedoch einen Zeiger auf den Puffer zurückgeben, der die Daten enthält (bei dem es sich um eine Zeichenfolge handelt), können Sie alle Kompilierungsfehler sehen.

In diesem Beispiel wurde ein Fehler in den Effekt BasicHLSL.fx eingeführt, indem die erste Variablendeklaration zweimal kopiert wurde.

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

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

Dieser Fehler führte dazu, dass der Compiler den folgenden Fehler zurückgibt, wie im folgenden Screenshot des fensters watch in Microsoft Visual Studio gezeigt.

Screenshot des Visual Studio-watch-Fensters

Da der Fehler in einem LPVOID-Zeiger zurückgegeben wird, wandeln Sie ihn im watch Fenster in eine Zeichenfolge um.

Hier ist der Code, der verwendet wird, um den Fehler von der fehlgeschlagenen Kompilierung zurückzugeben.

// Read the D3DX effect file
WCHAR str[MAX_PATH];
ID3D10Blob* l_pBlob_Effect = NULL;
ID3D10Blob* l_pBlob_Errors = NULL;
hr = DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"BasicHLSL10.fx" );
hr = D3DX10CompileEffectFromFile( str, NULL, NULL, 
    D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, 
    &l_pBlob_Effect, &l_pBlob_Errors );

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

Rendern eines Effekts (Direct3D 10)