Sdílet prostřednictvím


Nastavit stav efektu (Direct3D 11)

Některé konstanty efektu je potřeba inicializovat pouze. Po inicializaci se stav efektu nastaví na zařízení pro celou smyčku vykreslování. Při každém zavolání smyčky vykreslování je potřeba aktualizovat další proměnné. Základní kód pro proměnné efektu nastavení je uveden níže pro každý z typů proměnných.

Efekt zapouzdřuje veškerý stav vykreslení vyžadovaný k provedení průchodu vykreslování. Z hlediska rozhraní API existují tři typy zapouzdření stavu v efektu.

Konstantní stav

Nejprve deklarujte proměnné v efektu pomocí datových typů 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

Za druhé deklarujte proměnné v aplikaci, které lze nastavit aplikací, a pak aktualizují proměnné efektu.

           
    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();

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

Za třetí použijte metody aktualizace k nastavení hodnoty proměnných v aplikaci v proměnných efektu.

           
OnD3D11FrameRender()
{
    ...
    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 );
}

Dva způsoby, jak získat stav v proměnné efektu

Existují dva způsoby, jak získat stav obsažený v proměnné efektu. Vzhledem k efektu, který byl načten do paměti.

Jedním ze způsobů, jak získat stav sampleru z ID3DX11EffectVariable, který byl přetypován jako rozhraní vzorkovníku.

D3D11_SAMPLER_DESC sampler_desc;
ID3D11EffectSamplerVariable* l_pD3D11EffectVariable = NULL;
if( g_pEffect11 )
{
    l_pD3D11EffectVariable = g_pEffect11->GetVariableByName( "MeshTextureSampler" )->AsSampler();
    if( l_pD3D11EffectVariable->IsValid() )
        hr = (l_pD3D11EffectVariable->GetBackingStore( 0, 
            &sampler_desc );
}

Dalším způsobem je získat stav sampleru z ID3D11SamplerState.

ID3D11SamplerState* l_ppSamplerState = NULL;
D3D11_SAMPLER_DESC sampler_desc;
ID3D11EffectSamplerVariable* l_pD3D11EffectVariable = NULL;
if( g_pEffect11 )
{
    l_pD3D11EffectVariable = g_pEffect11->GetVariableByName( "MeshTextureSampler" )->AsSampler();
    if( l_pD3D11EffectVariable->IsValid )
    {
        hr = l_pD3D11EffectVariable->GetSampler( 0, 
            &l_ppSamplerState );
        if( l_ppSamplerState )
            l_ppSamplerState->GetDesc( &sampler_desc );
    }
}

Stav shaderu

Stav Shaderu je deklarován a přiřazen v technice efektu v rámci průchodu.

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

Funguje to stejně, jako kdybyste nepoužávali efekt. Existují tři volání, jedno pro každý typ shaderu (vrchol, geometrie a pixel). První, SetVertexShader, volá ID3D11DeviceContext::VSSetShader. CompileShader je speciální funkce efektu, která přebírá profil shaderu (vs_4_0) a název funkce shaderu vrcholů (RenderVS). Jinými slovy, každé z těchto volání CompileShader zkompiluje přidruženou funkci shaderu a vrátí ukazatel na zkompilovaný shader.

Všimněte si, že není nutné nastavit všechny stavy shaderu. Tento průchod neobsahuje žádná volání SetHullShader ani SetDomainShader, což znamená, že aktuálně vázané trupu a shadery domény se nezmění.

Stav textury

Stav textury je o něco složitější než nastavení proměnné, protože data textury nejsou jednoduše čtená jako proměnná, je vzorkována z textury. Proto musíte definovat proměnnou textury (stejně jako normální proměnnou s výjimkou použití typu textury) a musíte definovat podmínky vzorkování. Tady je příklad deklarace proměnné textury a odpovídající deklarace stavu vzorkování.

Texture2D g_MeshTexture;            // Color texture for mesh

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

Tady je příklad nastavení textury z aplikace. V tomto příkladu je textura uložena v datech sítě, která byla načtena při vytvoření efektu.

Prvním krokem je získání ukazatele na texturu z efektu (ze sítě).

ID3D11EffectShaderResourceVariable* g_ptxDiffuse = NULL;

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

Druhým krokem je zadání zobrazení pro přístup k texturě. Zobrazení definuje obecný způsob přístupu k datům z prostředku textury.

   
OnD3D11FrameRender()
{
  ID3D11ShaderResourceView* pDiffuseRV = NULL;

  ...
  pDiffuseRV = g_Mesh11.GetMaterial(pSubset->MaterialID)->pDiffuseRV11;
  g_ptxDiffuse->SetResource( pDiffuseRV );
  ...
}   

Z pohledu aplikace se neuspořádaná přístupová zobrazení zpracovávají podobně jako zobrazení prostředků shaderu. Ve funkci shaderu pixelů a výpočetního shaderu se ale neřazená data zobrazení přístupu čtou přímo z nebo zapisují. Nelze vzorek z neuspořádaného zobrazení přístupu.

Další informace o zobrazení prostředků naleznete v tématu Zdroje.

vykreslení efektu (Direct3D 11)