(Direct3D 11) 设置效果状态

某些效果常量只需初始化。 初始化后,效果状态将设置为整个呈现循环的设备。 每次调用呈现循环时,都需要更新其他变量。 下面显示了针对每种变量类型的效果变量设置效果变量的基本代码。

效果封装执行呈现传递所需的所有呈现状态。 就 API 而言,效果中封装了三种类型的状态。

常量状态

首先,使用 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

其次,在应用程序中声明可由应用程序设置的变量,然后更新效果变量。

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

第三,使用更新方法在效果变量中设置应用程序中变量的值。

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

在效果变量中获取状态的两种方法

可通过两种方法获取效果变量中包含的状态。 给定已加载到内存中的效果。

一种方法是从已转换为采样器接口的 ID3DX11EffectVariable 获取采样器状态。

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

另一种方法是从 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 );
    }
}

着色器状态

着色器状态是在传递中以效果技术声明和分配的。

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

这与未使用效果时一样。 有三个调用,每种类型的着色器 (顶点、几何图形和像素) 。 第一个,SetVertexShader,调用 ID3D11DeviceContext::VSSetShader。 CompileShader 是一种特殊效果函数,它采用着色器配置文件 (vs_4_0) ,顶点着色器函数的名称 (RenderVS) 。 换句话说,每个 CompileShader 调用都会编译其关联的着色器函数,并返回指向已编译着色器的指针。

请注意,并非所有着色器状态都必须设置。 此传递不包括任何 SetHullShader 或 SetDomainShader 调用,这意味着当前绑定的外壳和域着色器将保持不变。

纹理状态

纹理状态比设置变量复杂一点,因为纹理数据不只是像变量一样读取,而且是从纹理中采样的。 因此,必须像普通变量一样定义纹理变量 (,但它使用纹理类型) 并且必须定义采样条件。 下面是纹理变量声明和相应采样状态声明的示例。

Texture2D g_MeshTexture;            // Color texture for mesh

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

下面是从应用程序设置纹理的示例。 在此示例中,纹理存储在创建效果时加载的网格数据中。

第一步是从网格) 获取指向效果 (纹理的指针。

ID3D11EffectShaderResourceVariable* g_ptxDiffuse = NULL;

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

第二步是指定用于访问纹理的视图。 视图定义了从纹理资源访问数据的常规方法。

   
OnD3D11FrameRender()
{
  ID3D11ShaderResourceView* pDiffuseRV = NULL;

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

从应用程序的角度来看,无序访问视图的处理方式与着色器资源视图类似。 但是,在效果像素着色器和计算着色器函数中,无序访问视图数据直接从中读取/写入。 不能从无序访问视图采样。

有关查看资源的详细信息,请参阅 资源

(Direct3D 11) 呈现效果