일부 효과 상수는 초기화하기만 하면 됩니다. 초기화되면 효과 상태가 전체 렌더링 루프에 대한 디바이스로 설정됩니다. 렌더링 루프가 호출될 때마다 다른 변수를 업데이트해야 합니다. 효과 변수를 설정하기 위한 기본 코드는 각 변수 형식에 대해 아래에 나와 있습니다.
효과는 렌더링 패스를 수행하는 데 필요한 모든 렌더링 상태를 캡슐화합니다. 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 );
...
}
애플리케이션 관점에서 순서가 지정되지 않은 액세스 뷰는 셰이더 리소스 뷰와 유사하게 처리됩니다. 그러나 효과 픽셀 셰이더 및 컴퓨팅 셰이더 함수에서 순서가 지정되지 않은 액세스 뷰 데이터는 직접 읽기/쓰기가 가능합니다. 순서가 지정되지 않은 액세스 보기에서는 샘플링할 수 없습니다.
리소스를 보는 방법에 대한 자세한 내용은 리소스참조하세요.
관련 항목