Festlegen des Effektzustands (Direct3D 10)
Einige Effektkonst constants müssen nur initialisiert werden. Nach der Initialisierung wird der Effektzustand für die gesamte Renderschleife auf das Gerät festgelegt. Andere Variablen müssen jedes Mal aktualisiert werden, wenn die Renderschleife aufgerufen wird. Der grundlegende Code zum Festlegen von Effektvariablen wird unten für jeden Variablentypen gezeigt.
Ein Effekt kapselt den render-Zustand, der für einen Renderingpass erforderlich ist. Im Hinblick auf die API gibt es drei Zustandstypen, die in einem Effekt gekapselt sind.
Konstanter Zustand
Deklarieren Sie zunächst Variablen in einem Effekt mithilfe von HLSL-Datentypen.
//--------------------------------------------------------------------------------------
// 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
Deklarieren Sie zweitens Variablen in der Anwendung, die von der Anwendung festgelegt werden können, und aktualisieren Sie dann die Effektvariablen.
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();
}
Verwenden Sie drittens die Updatemethoden, um den Wert der Variablen in der Anwendung in den Effektvariablen fest zu legen.
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 );
}
Zwei Möglichkeiten zum Erhalten des Zustands in einer Effektvariablen
Es gibt zwei Möglichkeiten, den in einer Effektvariablen enthaltenen Zustand zu erhalten. Bei einem Effekt, der in den Arbeitsspeicher geladen wurde.
Eine Möglichkeit besteht im Erhalten des Samplerzustands aus einer ID3D10EffectVariable-Schnittstelle, die als Samplerschnittstelle castiert wurde.
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 );
}
Die andere Möglichkeit besteht im Erhalten des Samplerzustands aus einer ID3D10SamplerState-Schnittstelle.
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 );
}
}
Shaderzustand
Der Shaderzustand wird in einer Effekttechnik innerhalb eines Durchgangs deklariert und zugewiesen.
technique10 RenderSceneWithTexture1Light
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, RenderSceneVS( 1, true, true ) ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, RenderScenePS( true ) ) );
}
}
Dies funktioniert genauso wie, wenn Sie keinen Effekt verwenden würden. Es gibt drei Aufrufe, einen für jeden Shadertyp (Scheitelpunkt, Geometrie und Pixel). Der erste SetVertexShader ruft ID3D10Device::VSSetShader auf. CompileShader ist eine Spezielle Effektfunktion, die das Shaderprofil (im Vergleich zu 4 0) und den Namen der _ _ Vertexshaderfunktion (RenderVS) verwendet. Anders ausgedrückt: Jeder dieser SetXXXShader-Aufrufe kompiliert die zugehörige Shaderfunktion und gibt einen Zeiger auf den kompilierten Shader zurück.
Texturzustand
Der Texturzustand ist etwas komplexer als das Festlegen einer Variablen, da Texturdaten nicht einfach wie eine Variable gelesen werden, sondern aus einer Textur entnommen werden. Daher müssen Sie die Texturvariable definieren (genau wie eine normale Variable, außer dass sie einen Texturtyp verwendet), und Sie müssen die Samplingbedingungen definieren. Hier ist ein Beispiel für eine Texturvariablendeklaration und die entsprechende Deklaration des Samplingzustands.
Texture2D g_MeshTexture; // Color texture for mesh
SamplerState MeshTextureSampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
Hier ist ein Beispiel für das Festlegen einer Textur aus einer Anwendung. In diesem Beispiel wird die Textur in den Gitternetzdaten gespeichert, die beim Erstellen des Effekts geladen wurden.
Der erste Schritt besteht im Abrufen eines Zeigers auf die Textur aus dem Effekt (aus dem Gitter).
ID3D10EffectShaderResourceVariable* g_ptxDiffuse = NULL;
// Obtain variables
g_ptxDiffuse = g_pEffect10->GetVariableByName( "g_MeshTexture" )->AsShaderResource();
Im zweiten Schritt wird eine Ansicht für den Zugriff auf die Textur angegeben. Die Ansicht definiert eine allgemeine Möglichkeit für den Zugriff auf die Daten aus der Texturressource.
OnD3D10FrameRender()
{
ID3D10ShaderResourceView* pDiffuseRV = NULL;
...
pDiffuseRV = g_Mesh10.GetMaterial(pSubset->MaterialID)->pDiffuseRV10;
g_ptxDiffuse->SetResource( pDiffuseRV );
...
}
Weitere Informationen zum Anzeigen von Ressourcen finden Sie unter Texturansichten (Direct3D 10).