Schreiben eines Effekts (Direct3D 9)

Zum Schreiben eines Effekts müssen Sie die Effektsyntax verstehen und die erforderlichen Zustandsinformationen generieren. Sie können Shaderzustand, Textur- und Samplerzustand sowie den sämtlichen Pipelinezustand hinzufügen, den Ihre Anwendung in einem Effekt erfordert.

Die Effektsyntax wird im Effektformat (Direct3D 9) ausführlich angegeben. Ein Effekt wird in der Regel in einer Effektdatei (.fx) gekapselt, kann aber auch als Textzeichenfolge in einer Anwendung geschrieben werden.

Effect-Beispiel

Effekte enthalten drei Zustandstypen: Shaderzustand, Textur- und Samplerzustand und Pipelinezustand. Hier ist ein Beispiel für einen Effekt aus dem BasicHLSL-Beispiel:

// Global variables
float4 g_MaterialAmbientColor;      // Material's ambient color
float4 g_MaterialDiffuseColor;      // Material's diffuse color
int g_nNumLights;

float3 g_LightDir[3];               // Light's direction in world space
float4 g_LightDiffuse[3];           // Light's diffuse color
float4 g_LightAmbient;              // Light's ambient color

texture g_MeshTexture;              // Color texture for mesh

float    g_fTime;                   // App's time in seconds
float4x4 g_mWorld;                  // World matrix for object
float4x4 g_mWorldViewProjection;    // World * View * Projection matrix
// Texture samplers
sampler MeshTextureSampler = 
sampler_state
{
    Texture = <g_MeshTexture>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};
struct VS_OUTPUT
{
    float4 Position   : POSITION;   // vertex position 
    float2 TextureUV  : TEXCOORD0;  // vertex texture coords 
    float4 Diffuse    : COLOR0;     // vertex diffuse color
};
VS_OUTPUT RenderSceneVS( float4 vPos : POSITION, 
                         float3 vNormal : NORMAL,
                         float2 vTexCoord0 : TEXCOORD0,
                         uniform int nNumLights,
                         uniform bool bTexture,
                         uniform bool bAnimate )
{
    VS_OUTPUT Output;
    float3 vNormalWorldSpace;
  
    float4 vAnimatedPos = vPos;
    
    // Animation the vertex based on time and the vertex's object space position
    if( bAnimate )
        vAnimatedPos += float4(vNormal, 0) * (sin(g_fTime+5.5)+0.5)*5;
    
    // Transform the position from object space to homogeneous projection space
    Output.Position = mul(vAnimatedPos, g_mWorldViewProjection);
    
    // Transform the normal from object space to world space    
    vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld));
    
    // Compute simple directional lighting equation
    float3 vTotalLightDiffuse = float3(0,0,0);
    for(int i=0; i < nNumLights; i++ )
        vTotalLightDiffuse += g_LightDiffuse[i] * max(0,dot(vNormalWorldSpace, g_LightDir[i]));
        
    Output.Diffuse.rgb = g_MaterialDiffuseColor * vTotalLightDiffuse + 
                         g_MaterialAmbientColor * g_LightAmbient;   
    Output.Diffuse.a = 1.0f; 
    
    // Just copy the texture coordinate through
    if( bTexture ) 
        Output.TextureUV = vTexCoord0; 
    else
        Output.TextureUV = 0; 
    
    return Output;    
}
struct PS_OUTPUT
{
    float4 RGBColor : COLOR0;  // Pixel color    
};
PS_OUTPUT RenderScenePS( VS_OUTPUT In,
                         uniform bool bTexture ) 
{ 
    PS_OUTPUT Output;

    // Lookup mesh texture and modulate it with diffuse
    if( bTexture )
        Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV) * In.Diffuse;
    else
        Output.RGBColor = In.Diffuse;

    return Output;
}
technique RenderSceneWithTexture1Light
{
    pass P0
    {          
        VertexShader = compile vs_1_1 RenderSceneVS( 1, true, true );
        PixelShader  = compile ps_1_1 RenderScenePS( true ); 
    }
}

Dieser Effekt enthält:

  • Der Shaderzustand, bei dem es sich um den Zustand handelt, der dem Vertex-Shader und dem Pixel-Shader zugeordnet ist. Dies wird durch die Vertex- und Pixel-Shaderfunktionen, alle benötigten globalen Variablen und ihre Eingabe- und Ausgabedatenstrukturen definiert, die alle hier aufgeführt sind:

    struct VS_OUTPUT
    {  ...  };
    VS_OUTPUT RenderSceneVS( float4 vPos : POSITION, 
                             ...
    {  ...  }
    
    struct PS_OUTPUT
    {  ...  };
    PS_OUTPUT RenderScenePS( VS_OUTPUT In,
                             uniform bool bTexture ) 
    {  ...  }
    
  • Textur- und Samplerzustand, bei denen es sich um die globalen Variablen für das Texturobjekt und das Samplerobjekt handelt:

    texture g_MeshTexture;              // Color texture for mesh
    
    sampler MeshTextureSampler = 
    sampler_state
    {
       ...
    };
    
  • Der andere Effektzustand. In diesem Beispiel wird kein anderer Effektzustand explizit verwendet. Wenn dies der Wäre, wäre dies die Technik innerhalb des Durchgangs, auf den sie angewendet wurde:

    technique RenderSceneWithTexture1Light
    {
        pass P0
        {          
            // Any other effect state can be set here.
    
            VertexShader = compile vs_1_1 RenderSceneVS( 1, true, true );
            PixelShader  = compile ps_1_1 RenderScenePS( true ); 
        }
    }
    
    

Effekte enthalten eine oder mehrere Techniken und Durchläufe

Effektrenderingoptionen werden durch Hinzufügen von Techniken und Durchläufen gesteuert.

Effekte können mit zusätzlichen Durchläufen erstellt werden, um komplexere Renderingeffekte zu ermöglichen. Eine Technik unterstützt eine beliebige Anzahl von Durchläufen:

technique T0
{
    pass P0
    { ... }

    pass P1
    { ... }

    ...

    pass Pn
    { ... }
}

Effekte können auch mit einer beliebigen Anzahl von Techniken erstellt werden.

technique T0
{
    pass P0
    { ... }
}

technique T1
{
    pass P0
    { ... }

    pass P1
    { ... }
}

...

technique Tn
{
    pass P0
    { ... }
}

technique TVertexShaderOnly
{
    pass P0
    {
        VertexShader =
        asm
        {
         // assembly-language shader code goes here
         ...
        };
    }
}

Den Techniken und Durchläufen können beliebige Namen gegeben werden.

Effekte