본문 바로가기

ETC/Shader

Stencil Buffer

Stencil Buffer


Stencil Buffer는 랜더링시 픽셀이 해당위치에 그려질지 안그려질지를 결정해준다.

기존의 Z Buffer의 경우 픽셀의 Z값을 비교해서 Z값이 더 크면 새로 써지려는 픽셀이 더 가깝다는 의미가되므로

해당 위치에 새로운 픽셀이 그려지게되고 그려진 픽셀의 Z값이 Z Buffer의 기준Z값이 되게 된다.


하지만 Stencil Buffer의 경우 Z값(참조값)의 기준으로 픽셀이 그려지고 안그려지는것을 판단하는게 아닌

사용자가 임의의 기준을 두어 해당 기준을 통과하면 픽셀을 그려주고 해당기준을 통과하지 못하면 그려주지 않는

조건을 임의로 생성할 수 있다.


후면버퍼, 깊이버퍼와 동일한 해상도를 가지게된다.



그림자 부분에서만 검정색 그리기


1. Stencil Buffer를 킨다.

2. 비교함수를 D3DCMP_ALWAYS로 한다.(항상성공한다, 검사 자체를 하지 않고 픽셀을 쓴다는 의미다.)

3. 참조값을 0x01로 설정한다.

4. Pass시 D3DSTENCILOP_REPLACE를 한다. (해당 자리의 Stencil값을 참조값으로 변환한다.)

5. Fail시 D3DSTENCILOP_KEEP을 한다. (해당조건을 만족하지 못하면 해당자리의 Stencil값을 유지한다.)

6. 그림자를 렌더링 한다.(이때 그림자가 그려지는 픽셀 자라에만 Stencil값들이 0x01로 교체된다.)

7. 비교함수를 D3DCMP_EQUAL로 한다. (참조값과 해당자리의 Stencil값이 같아야 한다.)

8. 검정색 텍스쳐를 전체화면 영역으로 해서 그린다.

9. Stencil Mode를 끈다.


    
void RenderShadow()
{
    m_dev->SetRenderState(D3DRS_STENCILENABLE, true); // 1

    m_dev->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); // 2

    m_dev->SetRenderState(D3DRS_STENCILREF, 0x01); // 3

    m_dev->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); // 4

    m_dev->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); // 5

    m_pVertexBuffer[SHADOW]->Render( ); // 6

    m_dev->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); // 7

    m_pVertexBuffer[BLACK_CLIENT].Render( ); // 8

    m_dev->SetRenderState(D3DRS_STENCILENABLE, false); // 1
}


주로 거울, 평면그림자에서 사용되며

거울을 표현하고자 하면 거울 평면에 특정 물체만 반사하도록 하면 되며, 거울에 반사되는 부분에 대해서만 드로잉을 수행하면된다.

이렇게하면 거울에 있지 않은 다른부분이 렌더링되는것을 막을 수 있다.






참고

http://blog.naver.com/PostView.nhn?blogId=ttok13&logNo=60169180202

https://skmagic.tistory.com/414