8. 깊이 복잡도
후면 버퍼의 특정 항목에 기록되기 위해 경쟁 하는(깊이 판정 통해) 픽셀 단편의 개수
점 P의 깊이 복잡도는 3이고, 해당 픽셀을 두고 경쟁 하는 픽셀 단편이 세개
성능 분석을 위해 장면의 깊이 복잡도 측정
- 겹처 그리기는 성능에 악영향
- 다른 픽셀 단편에 덮어 써서 보이지 않게 될 픽셀을 처리 하면서 시간을 낭비
깊이 복잡도 측정 과정
장면을 렌더링 시 스텐실 버퍼를 계수기로 사용
- 렌더링 시작 시 스텐실 버퍼 0으로 초기화
- 스텐실 연산을 D3D12_STENCIL_OP_INCR 지정해서 각 픽셀 단편이 처리 될 떄마다 해당 스텐실 버퍼 항목 1증가
- 스텐실 판정 D3D12_COMPARISON_FUNC_ALWAYS 지정
- 렌더링 과정 시 스텐실 판정이 일어나면 값이 증가(깊이 복잡도)
깊이 복잡도 시각화 방법
- 깊이 복잡도 수준의 k 에 색상을 지정
- 스텐실 버퍼 연산 설정 하여 스텐실 버퍼 수정 하지 않게 변경
- 스텐실 비교 함수 설정, 스텐실 기준 값 k 지정
- 해당 화면에 직사각형 렌더링 시 깊이 복잡도 k 인 픽셀 들만 색 변화
이른 Z 판정 ( early Z - test)
깊이 판정은 출벽 병합기 단계에서 발생, 픽셀 셰이더 단계 의 다음 단계에서 적용
깊이 판정에서 폐기될 픽셀 단편도 픽셀 셰이더를 거쳐 간다
현세대 그래픽 하드웨어들은 깊이 판정이전에 이른 z 판정을 거쳐서 미리 폐기 하여 픽셀 셰이더에 가지 못하게 한다
최적화 이점에서 장면의 비혼합 물체들을 카메라 기준 앞에서 뒤로 렌더링 하면
카메라의 가장 가까운 물체가 먼저 그려지며 그뒤의 물체들은 이른 z 판정으로 더이상 처리 되지 않는다
9. 깊이 복잡도를 가산 혼합을 이용해서 시각화
깊이 판정을 비활성 화
원본 혼합 계수와 대상 혼합 계수를 설정, D3D12_BLEND_ONE
혼합 연산 설정 D3D12_BLEND_OP_ADD
픽셀 단편의 색상이 누적 되는 현상 발생
깊이 복잡도가 높을 수록 색이 밝아지는게 된다
10. 깊이 판정을 통과한 픽셀들의 개수, 깊이 판정에 실패한 픽셀들의 개수를 세는 방법
밑의 구조체을 이용해서 픽셀들의 개수를 파악 할 수 있다.
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_DESC;
//깊이 판정에 실패한 픽셀 마다 해당 스텐실 값 증가
mirrorDSS.FrontFace.StencilFailOp = D3D12_STENCIL_OP_KEEP;
mirrorDSS.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_INCR ;
mirrorDSS.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP ;
mirrorDSS.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
//깊이 판정에 성공한 픽셀 마다 해당 스텐실 값 증가
mirrorDSS.FrontFace.StencilFailOp = D3D12_STENCIL_OP_KEEP;
mirrorDSS.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_KEEP ;
mirrorDSS.FrontFace.StencilPassOp = D3D12_STENCIL_OP_INCR ;
mirrorDSS.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
11. 두개골 뿐만 아니라 장면의 바닥도 거울에 반사 되도록 거울 예제 수정
1. floor world 좌표의 반사 행렬 생성 후 reflectedfloorRitem 월드 좌표로 지정
2. reflectedfloorRitem 으로 렌더링
RenderItem* mReflectedfloorRitem = nullptr;
void StencilApp::OnKeyboardInput(const GameTimer& gt)
{
// Update reflection world matrix.
XMVECTOR mirrorPlane = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); // xy plane
XMMATRIX R = XMMatrixReflect(mirrorPlane);
XMStoreFloat4x4(&mReflectedSkullRitem->World, skullWorld * R);
// update reflection floor matrix
XMMATRIX floorwrold = XMLoadFloat4x4(&MathHelper::Identity4x4());
XMStoreFloat4x4(&mReflectedfloorRitem->World, floorwrold * R);
//매번 업데이트
mReflectedfloorRitem->NumFramesDirty = gNumFrameResources;
}
void StencilApp::BuildRenderItems()
{
//거울에 반사된 Floor 객체 렌더링
auto reflectedfloorRitem = std::make_unique<RenderItem>();
*reflectedfloorRitem = *floorRitem;
reflectedfloorRitem->ObjCBIndex = 6;
mReflectedfloorRitem = reflectedfloorRitem.get();
mRitemLayer[(int)RenderLayer::Reflected].push_back(reflectedfloorRitem.get());
mAllRitems.push_back(std::move(reflectedfloorRitem));
}
12. 그림자 렌더 항목에서 세계 행렬의 y값을 제거, ( Z 경쟁 발생)
그림자 렌더링 시 Y값을 0.001 정도 증가 후 Z경쟁이 발생하지 않게 해야 깔끔한 그림자가 렌더링 된다.
참고 및 내용 인용
프랭크 D 루나 지음, 류광 옮김
한빛 미디어
Directx 12를 이용한 3D 게임 프로그래밍 입문(2017)
'Directx12 3D 프로그래밍 입문 > 11.스텐실 적용' 카테고리의 다른 글
11.6 요약 및 연습문제 (1) | 2023.12.06 |
---|---|
11. 5 평면 그림자 구현 (1) | 2023.11.18 |
11.4 평면거울 구현 (1) | 2023.11.14 |
11. 1 ~3 깊이 스텐실 버퍼 자료, (0) | 2023.11.07 |