Establecer estado de efecto (Direct3D 11)
Algunas constantes de efecto solo deben inicializarse. Una vez inicializado, el estado del efecto se establece en el dispositivo para todo el bucle de representación. Se deben actualizar otras variables cada vez que se llama al bucle render. A continuación se muestra el código básico para establecer variables de efecto, para cada uno de los tipos de variables.
Un efecto encapsula todo el estado de representación necesario para realizar un pase de representación. En términos de la API, hay tres tipos de estado encapsulados en un efecto.
Estado constante
En primer lugar, declare variables en un efecto mediante tipos de datos 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
En segundo lugar, declare variables en la aplicación que la aplicación puede establecer y, a continuación, actualizará las variables de efecto.
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();
}
En tercer lugar, use los métodos de actualización para establecer el valor de las variables de la aplicación en las variables de efecto.
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 );
}
Dos maneras de obtener el estado en una variable de efecto
Hay dos maneras de obtener el estado contenido en una variable de efecto. Dado un efecto que se ha cargado en la memoria.
Una manera es obtener el estado del sampler de un id3DX11EffectVariable que se ha convertido como una interfaz de muestreo.
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 );
}
La otra manera es obtener el estado del sampler de 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 );
}
}
Estado del sombreador
El estado del sombreador se declara y se asigna en una técnica de efecto, dentro de un paso.
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 ) ) );
}
}
Esto funciona igual que si no estuviera usando un efecto. Hay tres llamadas, una para cada tipo de sombreador (vértice, geometría y píxel). La primera, SetVertexShader, llama a ID3D11DeviceContext::VSSetShader. CompileShader es una función de efecto especial que toma el perfil del sombreador (vs_4_0) y el nombre de la función de sombreador de vértices (RenderVS). En otras palabras, cada una de estas llamadas a CompileShader compila su función de sombreador asociada y devuelve un puntero al sombreador compilado.
Tenga en cuenta que no se debe establecer todo el estado del sombreador. Este pase no incluye ninguna llamada a SetHullShader o SetDomainShader, lo que significa que los sombreadores de dominio y casco enlazados actualmente no se modificarán.
Estado de textura
El estado de textura es un poco más complejo que establecer una variable, ya que los datos de textura no se leen simplemente como una variable, se muestrea a partir de una textura. Por lo tanto, debe definir la variable de textura (al igual que una variable normal, excepto que usa un tipo de textura) y debe definir las condiciones de muestreo. Este es un ejemplo de una declaración de variable de textura y la declaración de estado de muestreo correspondiente.
Texture2D g_MeshTexture; // Color texture for mesh
SamplerState MeshTextureSampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
Este es un ejemplo de configuración de una textura de una aplicación. En este ejemplo, la textura se almacena en los datos de malla, que se cargó cuando se creó el efecto.
El primer paso es obtener un puntero a la textura del efecto (de la malla).
ID3D11EffectShaderResourceVariable* g_ptxDiffuse = NULL;
// Obtain variables
g_ptxDiffuse = g_pEffect11->GetVariableByName( "g_MeshTexture" )->AsShaderResource();
El segundo paso es especificar una vista para acceder a la textura. La vista define una manera general de acceder a los datos desde el recurso de textura.
OnD3D11FrameRender()
{
ID3D11ShaderResourceView* pDiffuseRV = NULL;
...
pDiffuseRV = g_Mesh11.GetMaterial(pSubset->MaterialID)->pDiffuseRV11;
g_ptxDiffuse->SetResource( pDiffuseRV );
...
}
Desde la perspectiva de la aplicación, las vistas de acceso desordenadas se controlan de forma similar a las vistas de recursos del sombreador. Sin embargo, en el sombreador de píxeles de efecto y las funciones de sombreador de proceso, los datos de vista de acceso desordenados se leen o escriben directamente. No se puede muestrear desde una vista de acceso desordenada.
Para obtener más información sobre cómo ver los recursos, consulte Recursos.
Temas relacionados