본문으로 바로가기
728x90
반응형

 

1. 스텐실 버퍼 Stencil Buffer

🔸 특징

  • 스텐실 버퍼는 후면 버퍼 및 깊이 버퍼와 해상도가 같다.
  • 스텐실 버퍼를 지정하면 그 스텐실 버퍼는 깊이 버퍼에 부착된다.
  • 픽셀 단편들이 후면 버퍼에 기록되지 못하게 하는 역할을 한다.
  • CD3DX12_DEPTH_STENCIL_DESC구조체 채우고, D3D12_GRAPHICS_PIPELINE_STATE_DESC 설정한다.

 

 

 

2. 스텐실 판정 

스텐실 버퍼를 이용하면 장면이 후면 버퍼의 특정 영역에만 렌더링되지 않게 만들수 있다. 스텐실을 적용하는 경우, 주어진 한 픽셀이 후면 버퍼에 기록되는지 아닌지는 스텐실 판정의 결과에 따라 결정된다. 스텐실 판정은 픽셀이 래스터화되는 과정에서, 즉 출력 병합기 단계에서 일어난다. 

출저 : directx12를 이용한 3D 게임 프로그래밍 입문 page506

  • 픽셀을 허용 : 후면 버퍼에 그리겠다. 
  • 픽셀을 기각 : 후면 버퍼에서 자르겠다. 
  • value : 스텐실 버퍼에 이미 있던 픽셀의 값
  • stencilRef: 응용 프로그램이 지정한 스탠실 기준값
  • stencilReadMask : 좌변 우변 같은 값으로 마스킹값

 

 

 

3. 거울 그리기 PSO (pipeline_state_object)중요코드 

1) 파이프라인 설정에서 스탠실 상태 만들어주기.

  • 거울 픽셀들을 스텐실 버퍼에 기록하기 위해 거울을 렌더링할때 쓰는 pso

mirrorBlendState.RenderTarget[0].RenderTargetWriteMask = 0;

색상 성분들이 후면 버퍼에 기록되지 않는다. 

mirrorDSS.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;

깊이 버퍼 쓰기가 비활성화 된다. 

mirrorDSS.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;

거울을 스텐실 버퍼에 렌더링할 때에는 스텐실 판정이 항상 성공(통과)하도록 비교함수를 alway로 설정한다. 

mirrorDSS.FrontFace.StencilPassOp = D3D12_STENCIL_OP_REPLACE;

판정 성공시 기존 스텐실 항목이 항상 1로 대체되도록 StencilRef를 1로, 비교연산자를 D3D12_STENCIL_OP_REPLACE로 지정한다. 

mirrorDSS.BackFace.StencilDepthFailOp = D3D12_STENCIL_OP_KEEP;

깊이 판정이 실패해도 스텐실 버퍼는 변하지 않는다. 

 

  • 반사된 오브젝트를 거울의 가시적 부분에만 그릴 때 사용.

reflectionsDSS.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_EQUAL;

스텐실 버퍼 항목이 1인 경우에만 판정이 성공하게 설정한다. 이를 위해 stencilref를 1로 설정하고 비교연산자는 D3D12_COMPARISON_FUNC_EQUAL로 설정한다. 

    drawReflectionsPsoDesc.PS =
	{
		reinterpret_cast<BYTE*>(mShaders["alphaTestedPS"]->GetBufferPointer()),
		mShaders["alphaTestedPS"]->GetBufferSize()
	};

책과 다르게 알파 clip이 이뤄진 상자를 반사시키기 때문에 alphaTestps를 넣어줘서 반사된 물체도 알파처리 될수 있게 해주었다.

 

4. 거울 그리기 Draw 중요코드

auto passCB = mCurrFrameResource->PassCB->Resource();

다음 상수 버퍼로 넘어 갈 수있도록 상수버퍼 사이즈를 알아둔다. 

mCommandList->SetGraphicsRootConstantBufferView(2, passCB->GetGPUVirtualAddress());
// 불투명한 항목 (바닥, 벽, 상자등을 그린다.)
DrawRenderItems(mCommandList.Get(), mRenderItems[(int)RenderLayer::Opaque]);

원래 기본 상수버퍼로 그림을 그린다. 바닥, 벽, 상자, 기둥등등 

mCommandList->OMSetStencilRef(1);
mCommandList->SetPipelineState(mPSOs["markStencilMirrors"].Get());
DrawRenderItems(mCommandList.Get(), mRenderItems[(int)RenderLayer::Mirrors]);

mRenderItems[(int)RenderLayer::Mirrors] 이 아이템 안에는 거울만 있다. OMSetStencilRef 설정으로 판정 성공시 1이 기록된다. 

mCommandList->SetGraphicsRootConstantBufferView(2, passCB->GetGPUVirtualAddress() + 1 * passCBByteSize);
mCommandList->SetPipelineState(mPSOs["drawStencilReflections"].Get());
DrawRenderItems(mCommandList.Get(), mRenderItems[(int)RenderLayer::Reflected]);

반사된 조명으로 넘어가기 위해 상수 버퍼를 바꿔주 반사된 오브젝트를 거울의 가시적 부분에만 그릴 때 사용하는 상태객체로 변경후 반사된 물체를 그린다. 

728x90
반응형