Compartilhar via


Definir estado do efeito (Direct3D 10)

Algumas constantes de efeito só precisam ser inicializadas. Depois de inicializado, o estado de efeito é definido como o dispositivo para todo o loop de renderização. Outras variáveis precisam ser atualizadas sempre que o loop de renderização for chamado. O código básico para definir variáveis de efeito é mostrado abaixo, para cada um dos tipos de variáveis.

Um efeito encapsula todo o estado de renderização necessário para fazer uma passagem de renderização. Em termos da API, há três tipos de estado encapsulados em um efeito.

Estado constante

Primeiro, declare variáveis em um efeito usando tipos de dados HLSL.

//--------------------------------------------------------------------------------------
// 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

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

Em segundo lugar, declare variáveis no aplicativo que podem ser definidas pelo aplicativo e, em seguida, atualizará as variáveis de efeito.

           
    D3DXMATRIX  mWorldViewProjection;
    D3DXVECTOR3 vLightDir[MAX_LIGHTS];
    D3DXVECTOR4 vLightDiffuse[MAX_LIGHTS];
    D3DXMATRIX  mWorld;
    D3DXMATRIX  mView;
    D3DXMATRIX  mProj;

    // Get the projection and view matrix from the camera class
    mWorld = g_mCenterMesh * *g_Camera.GetWorldMatrix();
    mProj = *g_Camera.GetProjMatrix();
    mView = *g_Camera.GetViewMatrix();

    
OnD3D10CreateDevice()
{
  ...
    g_pLightDir = g_pEffect10->GetVariableByName( "g_LightDir" )->AsVector();
    g_pLightDiffuse = g_pEffect10->GetVariableByName( "g_LightDiffuse" )->AsVector();
    g_pmWorldViewProjection = g_pEffect10->GetVariableByName( 
        "g_mWorldViewProjection" )->AsMatrix();
    g_pmWorld = g_pEffect10->GetVariableByName( "g_mWorld" )->AsMatrix();
    g_pfTime = g_pEffect10->GetVariableByName( "g_fTime" )->AsScalar();
    g_pMaterialAmbientColor = g_pEffect10->GetVariableByName("g_MaterialAmbientColor")->AsVector();
    g_pMaterialDiffuseColor = g_pEffect10->GetVariableByName( 
        "g_MaterialDiffuseColor" )->AsVector();
    g_pnNumLights = g_pEffect10->GetVariableByName( "g_nNumLights" )->AsScalar();
}

Em terceiro lugar, use os métodos de atualização para definir o valor das variáveis no aplicativo nas variáveis de efeito.

           
OnD3D10FrameRender()
{
    ...
    g_pLightDir->SetRawValue( vLightDir, 0, sizeof(D3DXVECTOR3)*MAX_LIGHTS );
    g_pLightDiffuse->SetFloatVectorArray( (float*)vLightDiffuse, 0, MAX_LIGHTS );
    g_pmWorldViewProjection->SetMatrix( (float*)&mWorldViewProjection );
    g_pmWorld->SetMatrix( (float*)&mWorld );
    g_pfTime->SetFloat( (float)fTime );
    g_pnNumLights->SetInt( g_nNumActiveLights );
}

Duas maneiras de obter o estado em uma variável de efeito

Há duas maneiras de obter o estado contido em uma variável de efeito. Dado um efeito que foi carregado na memória.

Uma maneira é obter o estado do sampler de uma interface ID3D10EffectVariable que foi convertida como uma interface de sampler.

D3D10_SAMPLER_DESC sampler_desc;
ID3D10EffectVariable* l_pD3D10EffectVariable = NULL;
if( g_pEffect10 )
{
    l_pD3D10EffectVariable = g_pEffect10->GetVariableByName( "MeshTextureSampler" );
    if( l_pD3D10EffectVariable )
        hr = (l_pD3D10EffectVariable->AsSampler())->GetBackingStore( 0, 
            &sampler_desc );
}

A outra maneira é obter o estado do sampler de uma interface ID3D10SamplerState .

ID3D10SamplerState* l_ppSamplerState = NULL;
D3D10_SAMPLER_DESC sampler_desc;
ID3D10EffectVariable* l_pD3D10EffectVariable = NULL;
if( g_pEffect10 )
{
    l_pD3D10EffectVariable = g_pEffect10->GetVariableByName( "MeshTextureSampler" );
    if( l_pD3D10EffectVariable )
    {
        hr = (l_pD3D10EffectVariable->AsSampler())->GetSampler( 0, 
            &l_ppSamplerState );
        if( l_ppSamplerState )
            l_ppSamplerState->GetDesc( &sampler_desc );
    }
}

Estado do sombreador

O estado do sombreador é declarado e atribuído em uma técnica de efeito, dentro de uma passagem.

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

Isso funciona exatamente como faria se você não estivesse usando um efeito. Há três chamadas, uma para cada tipo de sombreador (vértice, geometria e pixel). A primeira, SetVertexShader, chama ID3D10Device::VSSetShader. CompileShader é uma função de efeito especial que usa o perfil de sombreador (vs_4_0) e o nome da função de sombreador de vértice (RenderVS). Em outras palavras, cada uma dessas chamadas SetXXXShader compila sua função de sombreador associada e retorna um ponteiro para o sombreador compilado.

Estado de textura

O estado de textura é um pouco mais complexo do que definir uma variável, pois os dados de textura não são simplesmente lidos como uma variável, são amostrados de uma textura. Portanto, você deve definir a variável de textura (assim como uma variável normal, exceto que ela usa um tipo de textura) e você deve definir as condições de amostragem. Aqui está um exemplo de uma declaração de variável de textura e a declaração de estado de amostragem correspondente.

Texture2D g_MeshTexture;            // Color texture for mesh

SamplerState MeshTextureSampler
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

Aqui está um exemplo de como definir uma textura de um aplicativo. Neste exemplo, a textura é armazenada nos dados de malha, que foram carregados quando o efeito foi criado.

A primeira etapa é obter um ponteiro para a textura do efeito (da malha).

ID3D10EffectShaderResourceVariable* g_ptxDiffuse = NULL;

    // Obtain variables
    g_ptxDiffuse = g_pEffect10->GetVariableByName( "g_MeshTexture" )->AsShaderResource();

A segunda etapa é especificar um modo de exibição para acessar a textura. A exibição define uma maneira geral de acessar os dados do recurso de textura.

   
OnD3D10FrameRender()
{
  ID3D10ShaderResourceView* pDiffuseRV = NULL;

   ...
   pDiffuseRV = g_Mesh10.GetMaterial(pSubset->MaterialID)->pDiffuseRV10;
   g_ptxDiffuse->SetResource( pDiffuseRV );
   ...
}   

Para obter mais informações sobre como exibir recursos, consulte Exibições de Textura (Direct3D 10).

renderizando um efeito (Direct3D 10)