Depth stencil view

ㅋㅋ·2022년 7월 18일
0

DirectX12강의

목록 보기
9/39

Depth stencil view

3d 물체를 표현하기 위한 뷰

깊이 값을 통하여 투영 시 비율을 설정하고

다른 픽셀에 의해 가려질 시 그리지 않는 등 추적


랜더링 파이프라인에서 Rasterizer 단계일 때,

투영 좌표계를 벗어날 경우 clipping하여 표현하고 있었음

(-1 <= x, y <= 1 / 0 <= z <= 1)


깊이 추적 방법

화면의 크기와 같은 크기의 버퍼를 준비하고 해당 버퍼에 가장 가까운 객체의 깊이값을 저장

픽셀화 단계에서 픽셀이 하나 하나 수정될 때마다 해당 좌표의 버퍼와 깊이값을 비교하여

더 가까운 픽셀일 시 픽셀에 적용하고 버퍼를 업데이트 한다.


스텐실

깊이 버퍼가 0.0 ~ 1.0 사이의 float 형식으로 나타낼 때,

float의 바이트 크기를 3바이트로 낮추면서 정밀도를 희생하며 남은 1바이트를 스텐실 값으로 사용

스텐실 값에 따라 표현 하지 않는 등 처리 방법에 대해 저장할 수 있도록 함


class DepthStencilBuffer
{
public:
	void Init(const WindowInfo& window, DXGI_FORMAT dsvFormat = DXGI_FORMAT_D32_FLOAT);
    
    ...

private:
	ComPtr<ID3D12Resource>				_dsvBuffer;
	ComPtr<ID3D12DescriptorHeap>		_dsvHeap;
	D3D12_CPU_DESCRIPTOR_HANDLE			_dsvHandle = {};
	DXGI_FORMAT							_dsvFormat = {};
};

리소스 버퍼와 버퍼에 대해 기술할 Descriptor heap로 구성

버퍼를 깊이 용도로만 사용할 경우 깊이 값으로 4 바이트를 모두 사용하도록 DXGI_FORMAT_D32_FLOAT 포맷으로 설정

스텐실을 사용하려면 DXGI_FORMAT_D24_UNORM_S8_UINT 포맷으로 설정


void DepthStencilBuffer::Init(const WindowInfo& window, DXGI_FORMAT dsvFormat)
{
	...

	D3D12_HEAP_PROPERTIES heapProperty = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

	D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Tex2D(_dsvFormat, window.width, window.height);
	desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;

	D3D12_CLEAR_VALUE optimizedClearValue = CD3DX12_CLEAR_VALUE(_dsvFormat, 1.0f, 0);

	DEVICE->CreateCommittedResource(
		&heapProperty,
		D3D12_HEAP_FLAG_NONE,
		&desc,
		D3D12_RESOURCE_STATE_DEPTH_WRITE,
		&optimizedClearValue,
		IID_PPV_ARGS(&_dsvBuffer));

	D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
	heapDesc.NumDescriptors = 1;
	heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
	heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;

	DEVICE->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_dsvHeap));

	_dsvHandle = _dsvHeap->GetCPUDescriptorHandleForHeapStart();
	DEVICE->CreateDepthStencilView(_dsvBuffer.Get(), nullptr, _dsvHandle);
}

버퍼 타입은 버퍼가 아니라 아니라 Tex2D 타입이다. (CD3DX12_RESOURCE_DESC::Tex2D)

프레임마다 optimizedClearValue를 통하여 해당 버퍼를 특정 값으로 초기화

descriptor heap의 타입은 D3D12_DESCRIPTOR_HEAP_TYPE_DSV으로 설정하고

CreateDepthStencilView 함수를 통하여 생성


void CommandQueue::RenderBegin(const D3D12_VIEWPORT* vp, const D3D12_RECT* rect)
{
	...

	D3D12_CPU_DESCRIPTOR_HANDLE backBufferView = _swapChain->GetBackRTV();
	_cmdList->ClearRenderTargetView(backBufferView, Colors::LightSteelBlue, 0, nullptr);

	D3D12_CPU_DESCRIPTOR_HANDLE depthStencilVeiw = GEngine->GetDepthStencilBuffer()->GetDSVCpuHandle();
	_cmdList->OMSetRenderTargets(1, &backBufferView, FALSE, &depthStencilVeiw);
	_cmdList->ClearDepthStencilView(depthStencilVeiw, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
}

command queue에서 렌더링을 시작하는 부분에서 DSV를 RTV와 묶어서 요청

ClearDepthStencilView 함수를 통하여 DSV 버퍼를 특정 값으로 초기화 요청

스텐실 값을 사용할 시 D3D12_CLEAR_FLAG_STENCIL 플래그를 or 해주고,

초기화 값을 넣어주면 된다.


void Shader::Init(const wstring& path)
{
	...

	_pipelineDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
	_pipelineDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
	//_pipelineDesc.DepthStencilState.DepthEnable = TRUE;
	//_pipelineDesc.DepthStencilState.StencilEnable = FALSE;
	_pipelineDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
	_pipelineDesc.SampleMask = UINT_MAX;
	_pipelineDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
	_pipelineDesc.NumRenderTargets = 1;
	_pipelineDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
	_pipelineDesc.SampleDesc.Count = 1;
    _pipelineDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT;

	DEVICE->CreateGraphicsPipelineState(&_pipelineDesc, IID_PPV_ARGS(&_pipelineState));
}

쉐이더 구현부에서 depth와 stencil 사용 여부를 설정해준다.

CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT)로 설정 시 depth만 사용

또한 깊이를 비교하는 함수 또한 설정할 수 있는데

default는 D3D12_COMPARISON_FUNC_LESS로 0에 가까운 픽셀을 표시하는 것이다.

버퍼 생성시 사용한 DSV의 포맷을 여기서도 동일하게 설정

0개의 댓글