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
TAGS.

Comments