Set Effect State (Direct3D 10)

Некоторые константы эффектов необходимо инициализировать только. После инициализации состояние эффекта устанавливается на устройство для всего цикла отрисовки. Другие переменные необходимо обновлять при каждом вызове цикла отрисовки. Ниже показан базовый код для задания переменных эффекта для каждого типа переменных.

Эффект инкапсулирует все состояние отрисовки, необходимое для передачи отрисовки. С точки зрения 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();

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

В-третьих, используйте методы обновления, чтобы задать значение переменных в приложении в переменных эффекта.

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

Два способа получения состояния в переменной эффекта

Существует два способа получения состояния, содержащегося в переменной эффекта. Учитывая эффект, загруженный в память.

Один из способов — получить состояние sampler из интерфейса ID3D10EffectVariable, который был приведен в качестве интерфейса выборки.

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

Другой способ — получить состояние sampler из интерфейса ID3D10SamplerState.

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

Состояние шейдера

Состояние шейдера объявляется и назначается в методе эффекта в пределах прохода.

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

Это работает так же, как если бы вы не использовали эффект. Существует три вызова: по одному для каждого типа шейдера (вершины, геометрии и пикселя). Первый, SetVertexShader, вызывает ID3D10Device::VSSetShader. CompileShader — это специальная функция эффектов, которая принимает профиль шейдера (vs_4_0) и имя функции шейдера вершин (RenderVS). Другими словами, каждый из этих вызовов SetXXXShader компилирует связанную функцию шейдера и возвращает указатель на скомпилированный шейдер.

Состояние текстуры

Состояние текстуры немного сложнее, чем задание переменной, так как данные текстуры не просто считываются как переменная, они выборки из текстуры. Поэтому необходимо определить переменную текстуры (так же, как обычную переменную, за исключением типа текстуры), и необходимо определить условия выборки. Ниже приведен пример объявления переменной текстуры и соответствующего объявления состояния выборки.

Texture2D g_MeshTexture;            // Color texture for mesh

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

Ниже приведен пример настройки текстуры из приложения. В этом примере текстура хранится в данных сетки, которая была загружена при создании эффекта.

Первым шагом является получение указателя на текстуру из эффекта (из сетки).

ID3D10EffectShaderResourceVariable* g_ptxDiffuse = NULL;

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

Второй шаг — указание представления для доступа к текстуре. Представление определяет общий способ доступа к данным из ресурса текстуры.

   
OnD3D10FrameRender()
{
  ID3D10ShaderResourceView* pDiffuseRV = NULL;

   ...
   pDiffuseRV = g_Mesh10.GetMaterial(pSubset->MaterialID)->pDiffuseRV10;
   g_ptxDiffuse->SetResource( pDiffuseRV );
   ...
}   

Дополнительные сведения о просмотре ресурсов см. в разделе "Представления текстур" (Direct3D 10).

Отрисовка эффекта (Direct3D 10)