shadow volume
한 광원에 의해 생성되는 그림자 영역.
광원이 여러개일 경우에는 각 광원에 대해서 고려해야 한다.
- 전체장면을 일반적인 기법으로 렌더링
- 주어진 광원에 대해서 물체의 글미자볼륨의 실루엣들을 그린다.
- 렌더타겟에 그리는것이 아니라 스텐실 버퍼를 갱신하기 위해 그리는 것이므로
후면버퍼와 깊이버퍼는 쓰기금지시킨다.
- 실루엣들을 그릴 때에 전면에 대해서는 스텐실값 증가, 후면에 대해서는 스텐실값 감소.
GSShadow_Input VS_Shadow(VSShadow_Input input) // 입력정점을 월드공간으로 변환한다.
{
GSShadow_Input output;
output.pos = mul(float4(input.pos,1), matWorld);
output.pos /= output.pos.w;
return output;
}
기하세이더에서는 정점들이 각 삼각형 단위로 입력된다.
입력삼각형에대해 실루엣을 만들지의 여부는 삼각형의 노말과 정점에서 광원으로의 방향벡터의 각도로 알 수 있다.
실루엣을 생성해야 한다면 삼각형의 각 에지마다 실루엣 면을 생성한다.
3개의 에지(v0,v1), (v1,v2),(v2,v0)에 대해서 각각 사각형면을 생성한다.
하나의 에지로 부터 하나의 실루엣면을 생성하는 함수는 아래와 같다.
void createSilhouette( GSShadow_Input v1, GSShadow_Input v2, inout TriangleStream<PSShadow_Input> ShadowTriangleStream )
{
float ExtrudeBias = 0;
float ExtrudeAmount = 1000;
float3 outpos[4];
float3 extrude1 = normalize(v1.pos - lightPosition);
outpos[0] = v1.pos + ExtrudeBias*extrude1;
outpos[1] = v1.pos + ExtrudeAmount*extrude1;
float3 extrude2 = normalize(v2.pos - lightPosition);
outpos[2] = v2.pos + ExtrudeBias*extrude2;
outpos[3] = v2.pos + ExtrudeAmount*extrude2;
PSShadow_Input output;
for (int v=0; v<4; v++) {
output.pos = mul( mul(float4(outpos[v],1), matView), matProjection);
ShadowTriangleStream.Append( output );
}
ShadowTriangleStream.RestartStrip();
}
기하세이더는 아래와 같다.
[maxvertexcount(12)]
void GS_Shadow( triangle GSShadow_Input In[3], inout TriangleStream<PSShadow_Input> ShadowTriangleStream )
{
float3 N = cross(In[1].pos - In[0].pos, In[2].pos - In[0].pos);
float3 L = lightPosition - In[0].pos;
if ( dot(N, L) > 0.0f ) {
createSilhouette( In[0], In[1], ShadowTriangleStream );
createSilhouette( In[1], In[2], ShadowTriangleStream );
createSilhouette( In[2], In[0], ShadowTriangleStream );
}
}
'Study > Directx 10' 카테고리의 다른 글
IDXGIFactory::MakeWindowAssociation Method (Windows) (0) | 2010.06.05 |
---|---|
반사 (0) | 2010.06.04 |
평면 그림자 (0) | 2010.06.02 |
깊이와 스텐실 (0) | 2010.06.01 |
D3D10_SHADER Constants (0) | 2010.05.30 |