11. 1 ~3 깊이 스텐실 버퍼 자료,
깊이 스텐실 버퍼 자료 형식과 버퍼 지우기
스텐실 버퍼는 후면 버퍼 및 깊이 버퍼와 같은 해상도를 가지다
특성 픽셀 단편들이 후면 버퍼에 기록 되지 못하게 막는 역할을 한다
예로 들어서 거울의 모습을 구현 할려면 물체의 반사된 이미지를 거울의 평면에 그리는데
거울의 테두리 바깥까지 그려지면 안된다
슽텐실 버퍼를 이용해서 거울 테두리 안에만 반사상이 그려지게 한다
사용 방법
D3D12_DEPTH_STENCIL_DESC 구조체를 채워서 그것을 파이프 라인 상태 객체(PSO)
의 DepthStecilState 필드에 설정
깊이 스텐실 버퍼를 하나의 텍스처로 보고 특정한 자료 형식을 저장 해야 한다
DXGI_FORMAT_D32_FLOAT_S8X24_UINT : 32비트 부동 소수점 깊이 값, 8비트 부호 없는 스텐실 값
채움용으로만 쓰는 24비트 구성
DXGI_FORMAT_D24_UNORM_S8_UINT : 텍셀 [0,1] 사상, 부호 없는 24비트 깊이 값 하나,
[0, 255] 사상되는 부호 없는 8비트 정수 스텐실 값
//깊이 버퍼 생성 할떄 형식을 저장
DXGI_FORMAT depthStencilDesc = DXGI_FORMAT_D24_UNORM_S8_UINT
depthStencilDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
//매 프레임 마다 초기화
mCommandList->ClearDepthStencilView(DepthStencilView(), //뷰 서술자
D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, // 깊이 버퍼만, 스텐실 버퍼만 지울 수 있다
1.0f, //깊이 버퍼 초기화 값
0, // 스텐실 버퍼 초기화 값
0, //pRects 배열의 개수
nullptr);//깊이 스텐실 버퍼의 전체를 지우려면 nullptr
스텐실 판정
스텐실 판정은 픽셀이 레스터화 되는 과정에서 발생( 출력병합기 단계)
스텐실 판정식
if( StencilRef & StencilReadMask ∇ Value & StencilReadMask)
픽셀을 허용(후면 버퍼, 깊이 버퍼에 기록)
else
픽셀을 기각(후면 버퍼, 깊이 버퍼에 기록하지 않는다)
연산자 좌변
- StencilRef : 응용 프로그램이 지정한 스텐실 지정 한 스텐실 기준 값
- & : 비트 논리곱
- StencilReadMask : 응용 프로그램에서 지정한 마스킹 값
연산자 우변
- Value : 스텐실 버퍼에 있는 값
- & : 비트 논리곱
- StencilReadMask : 응용 프로그램에서 지정한 마스킹 값( 위 아래 같은 값)
∇ 은 비교 연산, 다양한 연산자를 사용 가능 항상 참, 항상 거짓, <, >, =, 등이 있다
깊이 스텐실 상태의 서술
typedef struct D3D12_DEPTH_STENCIL_DESC
{
BOOL DepthEnable;
D3D12_DEPTH_WRITE_MASK DepthWriteMask;
D3D12_COMPARISON_FUNC DepthFunc;
BOOL StencilEnable;
UINT8 StencilReadMask;
UINT8 StencilWriteMask;
D3D12_DEPTH_STENCILOP_DESC FrontFace;
D3D12_DEPTH_STENCILOP_DESC BackFace;
} D3D12_DEPTH_STENCIL_DESC;
typedef
enum D3D12_DEPTH_WRITE_MASK
{
D3D12_DEPTH_WRITE_MASK_ZERO = 0,
D3D12_DEPTH_WRITE_MASK_ALL = 1
} D3D12_DEPTH_WRITE_MASK;
DepthEnable : 깊이 버퍼링 여부, 비활성화 시 깊이 판정 하지 않아서 그리는 순서 중요, 깊어 버퍼의 값을 갱신 안함
DepthWriteMask : 깊이 쓰기 여부
- ZERO : 비 활성화 시 깊이 판정은 일어나고 값은 갱신되지 않는다
- ALL : 활성화
DepthFunc : 깊이 판정에 쓰이는 비교 함수 (초기값 : D3D12_COMPARISON_FUNC_LESS )
후면 버퍼에 이미 기록되어 있는 픽셀 깊이 보다 현재 픽셀 깊이가 더 작을 경우만 참
스텐실 설정
StencilEnable : 스텐실 판정 여부
StencilReadMask : 스텐실 판정 시 사용하는 값, 기본 값 0으로 어떤 비트도 마스킹 안한다
StencilWriteMask : 스텐실 버퍼 갱신 떄 특정 비트값을 기록되지 않게 한다, 기본 값 0xff 아무 비트도 막지 않는다
FronFace , BackFace : 전면 후면 삼각형에 대한 스텐실 버퍼 적용 ( D3D12_DEPTH_SETENCILOP_DESC)
- 전면과 후면 삼각형을 스텐실 적용 방식을 따로 적용
- 후면 선별 시 후면 삼각형을 렌더링 하지 않기 때문에 후면 삼각형의 설정은 무시
- 투명 기하구조를 렌더링 시 후면 선별 없이 렌더링 하기 때문에 후면 삼각형 설정 필요
typedef struct D3D12_DEPTH_STENCILOP_DESC
{
//픽셀 단편이 스텐실 판정에 실패 시 갱신 하는 방식 결정
D3D12_STENCIL_OP StencilFailOp;
//픽셀 단편이 스텐실 판정에 성공, 깊이 판정에 실패 시 갱신 하는 방식 결정
D3D12_STENCIL_OP StencilDepthFailOp;
////픽셀 단편이 스텐실 판정에 성공, 깊이 판정에 성공 시 갱신 하는 방식 결정
D3D12_STENCIL_OP StencilPassOp;
//스텐실 판정 비교 함수 결정
D3D12_COMPARISON_FUNC StencilFunc;
} D3D12_DEPTH_STENCILOP_DESC0
typedef
enum D3D12_STENCIL_OP
{
D3D12_STENCIL_OP_KEEP = 1, // 스텐실 버퍼를 변경하지 않는다, 스텐실 버퍼 항목 유지
D3D12_STENCIL_OP_ZERO = 2, //0으로 설정
D3D12_STENCIL_OP_REPLACE = 3, // StencilRef 값으로 갱신
D3D12_STENCIL_OP_INCR_SAT = 4, // 스텐실 버퍼의 항목 값을 1증가 ( 최대 255)
D3D12_STENCIL_OP_DECR_SAT = 5, // 스텐실 버퍼의 항목 값 1 감소 (최소 0)
D3D12_STENCIL_OP_INVERT = 6, // 비트를 뒤집는다(NOT)
D3D12_STENCIL_OP_INCR = 7, // 스텐실 버퍼의 항목 1증가 ( 255 넘기면 0으로 순환)
D3D12_STENCIL_OP_DECR = 8 // 스텐실 버퍼의 항목 1감소 ( 0보다 작으면 최댓값으로 순환)
} D3D12_STENCIL_OP;
깊이 스텐실 상태의 생성 및 묶기
깊이 스텐실 버퍼의 서술 구조체를 채운 후 PSO 의 DepthStencilState 필드에 배정
스텐실 기준값을 설정 mCommandList -> OMSetStencilRef(1);
참고 및 내용 인용
프랭크 D 루나 지음, 류광 옮김
한빛 미디어
Directx 12를 이용한 3D 게임 프로그래밍 입문(2017)