Ogre Version: 1.12.13
Operating System: Windows 10
Render System: Direct3D11
Hello!
I have some questions about the depth buffer in Direct3D11.
I want to use the depth buffer as a texture after the solids have been rendered, to make effects such as SSAO or soft particles.
Currently I do this using my own Z-prepass, but I am now attempting to scrap that and instead use the built-in depth buffer that comes with Direct3D11.
Compositor with color and depth buffer.
I have set up a compositor to be able to use the depth buffer texture.
I followed the example here: viewtopic.php?p=552899&sid=bba7632db5a4 ... f3#p552899.
This is how the compositor then looks:
Code: Select all
compositor Test
{
technique
{
texture scene target_width target_height PF_BYTE_RGBA PF_DEPTH16
// This pass is for solids only (and will write to the depth buffer texture, but not read from it)
target scene
{
pass clear
{
}
pass render_scene
{
first_render_queue 0
last_render_queue 53
}
}
// This pass is for transparents only (and will read the depth buffer texture, but not write to it)
target scene
{
pass render_scene
{
first_render_queue 54
last_render_queue 105
}
}
target_output
{
// This only copies the contents of the scene texture to the screen
pass render_quad
{
material Modulate
input 0 scene 0
}
}
}
}
The problem with the compositor above is that it has some performance issues, where the scene normally has 125 FPS, but when this is enabled it goes down to 108 FPS.
The compositor works (I might have made a change or two, but still same performance issue) and the depth buffer can be used and I have debugged it in a shader that it actually works (by using "content_type compositor Test scene 1" in a material).
Compositor with only color.
So instead of trying to even use depth at all, I just attempted to do it without depth:
Code: Select all
compositor Test
{
technique
{
texture scene target_width target_height PF_R8G8B8
// This pass is for solids only
target scene
{
pass clear
{
}
pass render_scene
{
first_render_queue 0
last_render_queue 53
}
}
// This pass is for transparents only
target scene
{
pass render_scene
{
first_render_queue 54
last_render_queue 105
}
}
target_output
{
// This only copies the contents of the scene texture to the screen
pass render_quad
{
material Modulate
input 0 scene
}
}
}
}
But this had the exact same performance issue, from 125 FPS down to 108 FPS when it is enabled.
This means that just writing to a texture in the compositor makes the FPS go down quite a lot.
Compositor with no intermediate texture.
Making a compositor that writes directly instead of to another texture makes the FPS stay at 125 FPS, removing this performance issue completely:
Code: Select all
compositor Test
{
technique
{
target_output
{
// This pass is for solids only
pass clear
{
}
pass render_scene
{
first_render_queue 0
last_render_queue 53
}
// This here can be used for stuff like SSAO now that the depth buffer exists, but it is not used right now
//pass render_quad
//{
// material SSAO_Modulate
// input 0 occlusion
//}
// This pass is for transparents only
pass render_scene
{
first_render_queue 54
last_render_queue 105
}
}
}
}
This has no depth buffer texture access at all of course, but it shows that rendering to an intermediate texture is much slower than just not doing it.
Here are my questions:
1. How should a compositor look in order to get access to the depth buffer, without having a slowdown of an intermediate texture? Because the compositor above has the best performance, but I am just not sure how to get access to the automatic Direct3D11 depth buffer as a texture in my shaders.
Also, my own Z-prepass texture without an MRT or anything is faster than the current setup here (125 FPS down to 114 FPS), so something is most likely wrong with this process.
2. Can I somehow get access to the Direct3D11 depth buffer as a texture in code and set it to materials after the solids have been rendered without a compositor?
3. When it is working, I am having issues with getting the exact depth of a pixel by using the depth buffer texture.
In my current shader I am getting the depth to the current pixel of an object (say a particle system) with this code:
Code: Select all
float pixelPositionDepth = length(viewPosition) - nearClipDistance;
// viewPosition comes from mul(worldView, position) in the vertex shader
// worldView is worldview_matrix
And then I am getting and comparing the distance with the Z-prepass like this:
Code: Select all
float clipDistance = farClipDistance - nearClipDistance; // Convert it to world space units instead of 0-1
float zPrePassPositionDepth = ZPrePassMap.Sample(ZPrePassMap_state, zPrePassUV).r * clipDistance;
But I am unable to find the same solution for the Direct3D11 depth buffer texture. It is close to right with the code below, but it is not perfect:
Code: Select all
float depth = depthTexture.Sample(depthSampler, texCoord).x;
float linearDepth = (2.0f * nearClipDistance) / (farClipDistance + nearClipDistance - depth * (farClipDistance - nearClipDistance));
float clipDistance = farClipDistance - nearClipDistance;
float realDepth = linearDepth * clipDistance;