Définir l’état de l’effet (Direct3D 11)
Certaines constantes d’effet doivent uniquement être initialisées. Une fois initialisé, l’état d’effet est défini sur l’appareil pour l’ensemble de la boucle de rendu. D’autres variables doivent être mises à jour chaque fois que la boucle de rendu est appelée. Le code de base pour la définition des variables d’effet est illustré ci-dessous, pour chacun des types de variables.
Un effet encapsule tout l’état de rendu requis pour effectuer une passe de rendu. En termes de l’API, il existe trois types d’état encapsulés dans un effet.
État constant
Tout d’abord, déclarez des variables dans un effet à l’aide de types de données 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
Ensuite, déclarez des variables dans l’application qui peuvent être définies par l’application, puis mettez à jour les variables d’effet.
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();
}
Troisièmement, utilisez les méthodes de mise à jour pour définir la valeur des variables dans l’application dans les variables d’effet.
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 );
}
Deux façons d’obtenir l’état dans une variable d’effet
Il existe deux façons d’obtenir l’état contenu dans une variable d’effet. Compte tenu d’un effet qui a été chargé dans la mémoire.
L’une des méthodes consiste à obtenir l’état de l’échantillonneur à partir d’un ID3DX11EffectVariable qui a été casté en tant qu’interface d’échantillonneur.
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 );
}
L’autre méthode consiste à obtenir l’état de l’échantillonneur à partir d’un 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 );
}
}
État du nuanceur
L’état du nuanceur est déclaré et affecté dans une technique d’effet, au sein d’une passe.
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 ) ) );
}
}
Cela fonctionne comme si vous n’utilisiez pas d’effet. Il existe trois appels, un pour chaque type de nuanceur (vertex, geometry et pixel). Le premier, SetVertexShader, appelle ID3D11DeviceContext::VSSetShader. CompileShader est une fonction d’effet spécial qui prend le profil de nuanceur (vs_4_0) et le nom de la fonction de nuanceur de vertex (RenderVS). En d’autres termes, chacun de ces appels CompileShader compile sa fonction de nuanceur associée et retourne un pointeur vers le nuanceur compilé.
Notez que l’état du nuanceur ne doit pas tous être défini. Ce passage n’inclut pas d’appels SetHullShader ou SetDomainShader, ce qui signifie que les nuanceurs de coque et de domaine actuellement liés sont inchangés.
État de texture
L’état de texture est un peu plus complexe que la définition d’une variable, car les données de texture ne sont pas simplement lues comme une variable, elles sont échantillonnées à partir d’une texture. Par conséquent, vous devez définir la variable de texture (comme une variable normale, sauf qu’elle utilise un type de texture) et vous devez définir les conditions d’échantillonnage. Voici un exemple de déclaration de variable de texture et de déclaration d’état d’échantillonnage correspondante.
Texture2D g_MeshTexture; // Color texture for mesh
SamplerState MeshTextureSampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
Voici un exemple de définition d’une texture à partir d’une application. Dans cet exemple, la texture est stockée dans les données de maillage qui ont été chargées lors de la création de l’effet.
La première étape consiste à obtenir un pointeur vers la texture à partir de l’effet (à partir du maillage).
ID3D11EffectShaderResourceVariable* g_ptxDiffuse = NULL;
// Obtain variables
g_ptxDiffuse = g_pEffect11->GetVariableByName( "g_MeshTexture" )->AsShaderResource();
La deuxième étape consiste à spécifier une vue pour accéder à la texture. La vue définit un moyen général d’accéder aux données à partir de la ressource de texture.
OnD3D11FrameRender()
{
ID3D11ShaderResourceView* pDiffuseRV = NULL;
...
pDiffuseRV = g_Mesh11.GetMaterial(pSubset->MaterialID)->pDiffuseRV11;
g_ptxDiffuse->SetResource( pDiffuseRV );
...
}
Du point de vue de l’application, les vues d’accès non ordonnées sont gérées de la même manière que les vues de ressources du nuanceur. Toutefois, dans les fonctions de nuanceur de pixels d’effet et de nuanceur de calcul, les données de vue d’accès non triées sont lues directement à partir de/écrites dans. Vous ne pouvez pas échantillonner à partir d’un affichage d’accès non ordonné.
Pour plus d’informations sur l’affichage des ressources, consultez Ressources.
Rubriques connexes