평면 그림자

반응형

평면그림자는 일반적으로 렌더링 후에 그림자를 위한 블렌딩을 추가하여 만든다.
그림자가 평면이 아닌 임의의 곡면에 맺히는 경우도 처리하고자 한다면 그림자볼륨을 써야 한다.

D3DXMatrixShadow는 그림자 평면을 정규화 하고 그림자 평면과 광원의 방향으로부터 그림자변환 행렬을 계산한다.
광원타입이 방향광원인지 점광원인지에 따라 인자값이 다르다.
lw(마지막인자)값이 0인것은 방향벡터이며 방향광원이다.
lw(마지막인자)값이 1인것은 위치벡터이며 점광원이다.

장면의 모든 물체들을 일반적인 방법으로 그린다.
그 후에 그림자 변환행렬을 사용하여 삼각형들을 그림자가 맺힐 평면으로 납작하게 변환한다.
변환된 삼각형을 어둡게 반투명 블렌딩하여 그림자를 그린다.

그런데 여러개의 납작하게 변환된 그림자 삼각형들은 그림자 평면에서 겹치게 된다.
이들을 어둡게 반투명 블렌딩하면 겹쳐진 영역들이 더욱 어둡게 나타난다.
그래서 스텐실버퍼를 사용해서 처음으로 그려지는 그림자 픽셀들에 대해서만
스텐실 테스트가 성공하도록 구성
하게 된다.

그림자 변환 행렬을 계산하여 물체를 월드공간에 배치하기 위해서는 아래와 같다.
D3DXVECTOR4 lightDirection(0.707f, -0.707f, 0.707f, 0.0f);
 D3DXPLANE groundPlane(0.0f, -1.0f, 0.0f, 0.0f);
 groundPlane.d +=0.1f;

 D3DXMATRIX matShadow;
 D3DXMatrixShadow(&matShadow, &lightDirection, &groundPlane);
 D3DXMATRIX matTrans;
 D3DXMatrixTranslation(&matTrans, posTeapot.x, posTeapot.y, posTeapot.z);
 matWorld = matTrans * matShadow;

.fx
깊이
DepthStencilState StencilIncreaseOnce {
 DepthEnable = true;
 DepthWriteMask = ALL;
 DepthFunc = LESS_EQUAL;
 
 StencilEnable = true;
 FrontFaceStencilFunc = EQUAL; // 스텐실버퍼의 값이 stencilref값인 0과 같을때만 스텐실 테스트가 성공.
 FrontFaceStencilPass = INCR; // 성공시 버퍼값으 증가
 FrontFaceStencilFail = Keep;
};

블렌드
BlendState BlendAlpha {
 AlphaToCoverageEnable = FALSE;
 BlendEnable[0] = TRUE;
 SrcBlend = SRC_ALPHA ;
 DestBlend = INV_SRC_ALPHA ;
 BlendOp = ADD;
 SrcBlendAlpha = ONE;
 DestBlendAlpha = ZERO;
 BlendOpAlpha = ADD;
 RenderTargetWriteMask[0] = 0x0F;
};

technique10 RenderShadow
{
 pass P0
 {
  SetVertexShader( CompileShader( vs_4_0, VS() ) );
  SetGeometryShader( NULL );
  SetPixelShader( CompileShader( ps_4_0, PS_Shadow() ) );

  SetDepthStencilState( StencilIncreaseOnce, 0x0 );
  SetBlendState( BlendAlpha, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF ); //blendState, blendFactor, sampleMask
 }
}


'Study > Directx 10' 카테고리의 다른 글

반사  (0) 2010.06.04
shadow volume  (0) 2010.06.02
깊이와 스텐실  (0) 2010.06.01
D3D10_SHADER Constants  (0) 2010.05.30
D3D10_BLEND_OP Enumeration  (0) 2010.05.30
TAGS.

Comments