Jump to content
  • Advertisement
Sign in to follow this  
JJJohan

DX12 [DX12] (Solved) Depth buffer is rendering backwards?

This topic is 677 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I can't for the life of me figure out why my depth buffer is playing up, and it seems like a simple oversight somewhere.

 

Basically, I'm drawing a series of objects in my scene and can navigate around. What happens is the objects are drawing as if they are behind each-other, with the farthest away objects being drawn through closer ones.

 

I can "solve" this by setting the depth buffer D3D12_CLEAR_VALUE to 0.0 and performing a D3D12_COMPARISON_FUNC_GREATER_EQUAL instead of D3D12_COMPARISON_FUNC_LESS_EQUAL Everything then renders correctly. However rather than being happy with that, I want to know what's causing this - as it's unusual and does not reflect the behaviour of the DirectX Samples.

 

My psuedo render loop:


  1. Set gbuffer as active render targets.

  2. Clear gbuffer render textures.

  3. Clear depth buffer.

  4. Draw objects.

  5. Set backbuffer as active render target.

  6. Draw gbuffer result.


In terms of actual code, I suppose the three useful bits here are my depth buffer creation, depth buffer clearing and PSO setup.

 

Creating the depth buffer:

// Create a resource description for the depth texture.
D3D12_RESOURCE_DESC depthDesc = {};
depthDesc.MipLevels = 1;
depthDesc.Format = DXGI_FORMAT_R32_TYPELESS;
depthDesc.Alignment = 0;
depthDesc.Width = _screenWidth;
depthDesc.Height = _screenHeight;
depthDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
depthDesc.DepthOrArraySize = 1;
depthDesc.SampleDesc.Count = 1;
depthDesc.SampleDesc.Quality = 0;		
depthDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
depthDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;

D3D12_CLEAR_VALUE* clearVal = new D3D12_CLEAR_VALUE();
clearVal->Format = DXGI_FORMAT_D32_FLOAT;
clearVal->DepthStencil.Depth = 1.0f;
clearVal->DepthStencil.Stencil = 0;

// Create a depth stencil view description.
D3D12_DEPTH_STENCIL_VIEW_DESC stencilDesc = {};
stencilDesc.Format = DXGI_FORMAT_D32_FLOAT;
stencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
stencilDesc.Texture2D.MipSlice = 0;

// Create a shader resource view description.
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;

LOGFAILEDCOM(_device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &depthDesc, 
	D3D12_RESOURCE_STATE_DEPTH_READ, clearVal, IID_PPV_ARGS(&_pDepthBuffer)));
		
_device->CreateDepthStencilView(_pDepthBuffer, &stencilDesc, _dsvHeap->GetCPUDescriptorHandleForHeapStart());

DepthBufferIndex = ResourceFactory::GetTextureSlot();
CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(_cbvSrvHeap->GetCPUDescriptorHandleForHeapStart(), DepthBufferIndex, D3DUtils::GetSRVDescriptorSize());
_device->CreateShaderResourceView(_pDepthBuffer, &srvDesc, srvHandle);

Clearing the depth buffer (how difficult can it be?):

_commandList->ClearDepthStencilView(_dsvHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);

PSO (relevant bits):

D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.InputLayout = {&inputLayout[0], UINT(inputLayout.size())};
psoDesc.pRootSignature = _pRootSignature;
psoDesc.VS = {reinterpret_cast<UINT8*>(_pVertexShader->GetBufferPointer()), _pVertexShader->GetBufferSize()};
psoDesc.PS = {reinterpret_cast<UINT8*>(_pPixelShader->GetBufferPointer()), _pPixelShader->GetBufferSize()};
psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT;
psoDesc.BlendState = blendState;
psoDesc.SampleMask = UINT_MAX;
psoDesc.SampleDesc.Count = 1;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
			
psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
psoDesc.DepthStencilState.DepthFunc = _depthCheck;
psoDesc.DepthStencilState.DepthEnable = TRUE;
psoDesc.DepthStencilState.StencilEnable = FALSE;
psoDesc.DepthStencilState.DepthWriteMask = _depthWrite;

psoDesc.NumRenderTargets = GBuffer::GBUFFER_NUM_TEXTURES;			
for (size_t i = 0; i < GBuffer::GBUFFER_NUM_TEXTURES; ++i)
{
	psoDesc.RTVFormats[i] = DXGI_FORMAT_R8G8B8A8_UNORM;
}
Edited by JJJohan

Share this post


Link to post
Share on other sites
Advertisement

How are you constructing your projection matrix? That sounds like the correct behavior for an inverted projection matrix (far and near plane swapped from traditional way).

Share this post


Link to post
Share on other sites

Ah, you're right. I overlooked my projection matrix!

 

I am beginning to recall reversing my projection matrix for the depth buffer accuracy for distant objects. It seems then that a clear value of 0 and reversing the depth functions is indeed correct behaviour.

 

I do feel silly now!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!