효과 상태 설정(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 );
}

효과 변수에서 상태를 가져오는 두 가지 방법

효과 변수에 포함된 상태를 가져오는 방법에는 두 가지가 있습니다. 메모리에 로드된 효과가 있습니다.

한 가지 방법은 샘플러 인터페이스로 캐스팅된 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 );
}

다른 방법은 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)