Organizando o estado em um efeito (Direct3D 10)

Com o Direct3D 10, o estado de efeito para determinados estágios de pipeline é organizado pelas seguintes estruturas:

Estado do pipeline Estrutura
Assembler de entrada D3D10_INPUT_ELEMENT_DESC
Rasterization D3D10_RASTERIZER_DESC
Fusão de saída D3D10_BLEND_DESC e D3D10_DEPTH_STENCIL_DESC

 

Para os estágios do sombreador, em que o número de alterações de estado precisa ser mais controlado por um aplicativo, o estado foi dividido em estado de buffer constante, estado do sampler e estado do recurso de sombreador. Isso permite que um aplicativo cuidadosamente projetado atualize apenas o estado que está sendo alterado, o que melhora o desempenho reduzindo a quantidade de dados que precisam ser passados para a GPU.

Então, como organizar o estado do pipeline em um efeito?

A resposta é que a ordem não importa. As variáveis globais não precisam estar localizadas na parte superior. No entanto, todos os exemplos no SDK seguem a mesma ordem, pois é uma boa prática organizar os dados da mesma maneira. Portanto, essa é uma breve descrição da ordenação de dados nos exemplos do SDK do DirectX.

Variáveis globais

Assim como a prática C padrão, as variáveis globais são declaradas primeiro, na parte superior do arquivo. Na maioria das vezes, essas são variáveis que serão inicializadas por um aplicativo e, em seguida, usadas em um efeito . Às vezes, eles são inicializados e nunca alterados, outras vezes são atualizados a cada quadro. Assim como as regras de escopo da função C, as variáveis de efeito declaradas fora do escopo das funções de efeito são visíveis durante todo o efeito; qualquer variável declarada dentro de uma função de efeito só é visível dentro dessa função.

Aqui está um exemplo das variáveis declaradas em BasicHLSL10.fx.

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

Texture2D 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
SamplerState MeshTextureSampler
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

A sintaxe para variáveis de efeito é mais detalhada em Sintaxe variável de efeito (Direct3D 10). A sintaxe para amostradores de textura de efeito é mais detalhada em Tipo de Amostra (DirectX HLSL).

Sombreadores

Sombreadores são pequenos programas executáveis. Você pode pensar em sombreadores como encapsulando o estado do sombreador, já que o código HLSL implementa a funcionalidade do sombreador. O pipeline usa três tipos diferentes de sombreadores.

  • Sombreadores de vértice – operar em dados de vértice. Um vértice em produz um vértice.
  • Sombreadores de geometria – operar em dados primitivos. Um primitivo em pode produzir 0, 1 ou muitos primitivos.
  • Sombreadores de pixel – operar em dados de pixel. Um pixel em produz 1 pixel para fora (a menos que o pixel seja retirado de uma renderização).

Sombreadores são funções locais e seguem regras de função de estilo C. Quando um efeito é compilado, cada sombreador é compilado e um ponteiro para cada função de sombreador é armazenado internamente. Uma interface ID3D10Effect é retornada quando a compilação é bem-sucedida. Neste ponto, o efeito compilado está em um formato intermediário.

Para saber mais sobre os sombreadores compilados, você precisará usar a reflexão do sombreador. Isso é essencialmente como pedir ao runtime para descompilar os sombreadores e retornar informações sobre o código do sombreador.

struct VS_OUTPUT
{
    float4 Position   : SV_POSITION; // vertex position 
    float4 Diffuse    : COLOR0;      // vertex diffuse color
    float2 TextureUV  : TEXCOORD0;   // vertex texture coords 
};

VS_OUTPUT RenderSceneVS( float4 vPos : POSITION,
                         float3 vNormal : NORMAL,
                         float2 vTexCoord0 : TEXCOORD,
                         uniform int nNumLights,
                         uniform bool bTexture,
                         uniform bool bAnimate )
{
    VS_OUTPUT Output;
    float3 vNormalWorldSpace;
 
    ....    
    
    return Output;    
}


struct PS_OUTPUT
{
    float4 RGBColor : SV_Target;  // Pixel color
};

PS_OUTPUT RenderScenePS( VS_OUTPUT In,
                         uniform bool bTexture ) 
{ 
    PS_OUTPUT Output;

    if( bTexture )
        Output.RGBColor = g_MeshTexture.Sample(MeshTextureSampler, In.TextureUV) * In.Diffuse;
    ....

    return Output;
}

A sintaxe para sombreadores de efeito é mais detalhada na Sintaxe da Função de Efeito (Direct3D 10).

Técnicas e passagens

Uma técnica é uma coleção de passes de renderização (deve haver pelo menos uma passagem). Cada passagem de efeito (que é semelhante no escopo a uma única passagem em um loop de renderização) define o estado do sombreador e qualquer outro estado de pipeline necessário para renderizar a geometria.

Aqui está um exemplo de uma técnica (que inclui uma passagem) de BasicHLSL10.fx.

technique10 RenderSceneWithTexture1Light
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, RenderSceneVS( 1, true, true ) ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, RenderScenePS( true ) ) );
    }
}

A sintaxe para sombreadores de efeito é mais detalhada em Sintaxe de Técnica de Efeito (Direct3D 10).

Efeitos (Direct3D 10)