Drawing depth buffer in pixel shader

Started by
10 comments, last by ajithk 8 years, 3 months ago
Hi everyone,

I am trying to draw depth info of a scene into a texture bound as a UAV in pixel shader. I did not bind either render target or depth stencil target. Btw my shader model is 5.0

Below is the pixel shader i used (struct PS_IN not shown for simplicity )

RWTexture2D tex : register(u0)
void PS(PS_IN input)
{
if ( tex[uint(input.pos.xy)] >= input.pos.z )
tex[uint(input.pos.xy)] = input.pos.z;
}

After clearing UAV with float4(1,1,1,1) and binding UAV with OMSetRenderTargetAndUnorderedAccessViews (0,NULL,NULL,0,1,&uav_view,NULL ), I drew the scene. The program crashed promptly and I am not at all surprised :D

I have a couple of doubts.

1. Is that the correct way to use [] operator?(If it is, I have to look somewhere else for bug causing the crash) If operator [] can do both read and write, doesn't that make Load function redundant.
2. This question occurred to me while I was posting this. My UAV texture is 512x512 size. How does Direct3D know to invoke pixel shader 512*512 times. I haven't bound the render target at all. I am not sure if my question makes any sense in the first place.
Advertisement

tex[uint(input.pos.xy)]

You are supposed to use two coordinates uint2(...)

2. This question occurred to me while I was posting this. My UAV texture is 512x512 size. How does Direct3D know to invoke pixel shader 512*512 times. I haven't bound the render target at all. I am not sure if my question makes any sense in the first place.

You have to specify Viewport to let the rasterizer know for which pixels on the screen to call the pixel shader.

What is the format of your output resource?

Do you have debug layer enabled?

In addition to the above answer (set the viewport!), D3D11.1 introduced the "forced sample count" rasterizer state, which lets you specify how many samples exist per viewport pixel.

The program crashed promptly and I am not at all surprised

D3D never crashes, unless you've got a bug in your own code and are passing invalid pointers into D3D. Double check that every function that can fail (e.g. ones that return HRESULT) are accompanied by error checking.

BTW, why not just use a regular depth stencil view? What's up your sleeve? :)
@ _void_

Yeah, I replaced tex[uint(input.pos.xy)] with tex[uint2(input.pos.xy)]. The program didn't crash. Earlier I did not enable debug layer, now I did. The format for my UAV is DXGI_FORMAT_R16_UNORM if that's what you asked. I have set the viewport also btw.

Since I have no way of knowing if the contents of UAV are correct, I bound rendering target this time. It's format is DXGI_FORMAT_R8G8B8A8_UNORM. And I added the below line

return float4(tex[uint2(input.pos.xy)],tex[uint2(input.pos.xy)],tex[uint2(input.pos.xy)],tex[uint2(input.pos.xy)])

with float4 as return type and SV_Target as return semantic (Sorry for bad formatting. Ah! The misery of typing in a tab). I expected to see my scene in black and white colors. The sort of image they show to visualize the depth buffer. But I got only black(blank) screen (no white colors ;) )

@ Hodgman

For using forced sample count, I need to upgrade the driver. I will keep that on mind.

And yeah, you guessed it right. Usually I dont check for HRESULT errors but now that I am getting more and more involved with this, I will.

I am writing depth in pixel shader just to learn using UAVs. But now that you asked, I came to think of it :). For point lights we need 6 depth maps. Instancing geometry shaders 6 times with six different matrices and rendering depth in pixel to an array of Texture2Ds with array index as SV_GSInstanceID will give me 6 depth maps in a single pass. Not sure of performance though.

But I got only black(blank) screen (no white colors ;) )

Which color do you clear your RTV?

Your geometry could be clipped (as it is not inside the clipping volume) or culled away. As a result pixel shader is never invoked.

if your pixel shader does this only line of code return float4(1, 0, 0, 1); Do you get anything red on the screen?

I use black color to clear my RTV. When I return float4(1,0,0,1) the whole screen is red.

Btw, my scene is a room with a chair, bed, table and a lamp. I have a first person camera working. I noticed something here. I replaced the return statement with this
return float4(input.pos.z,input.pos.z,input.pos.z,input.pos.z). The whole screen is white. As i remember the scene, I walked to my lamp and chair. As I approached these, I can see a faint grey outline of lamp, chair etc. The more nearer I approach them the more greyish they appear. Even walls appear greyish when I walk to them.

That's the normal behavior of a visualized depth buffer. The values are distributed hyperbolically, so more values are near 1 (white). If you want better visualization, transform them back to linear depth.

PS: Save yourself some typing: return float4(input.pos.z,input.pos.z,input.pos.z,input.pos.z) is equivalent to return input.pos.zzzz wink.png

Edit: Waaaaait, is that SV_Position ? I don't even know what z means here, never checked myself and the docs are enigmatic. But the effect you're describing sounds like the depth value. Could be worse though, if it's e.g. view space z grey might be even rarer (z can go higher than 1 and will be clamped to one).

My pixel shader is writing to render target but not to UAV. Actually it's not even reading from UAV. Since I clear UAV with float(1.0f) it should atleast show white screen if I return float4(tex1[uint2(input.pos.xy)],....) . I bound it to slot 1 since now I have render target. Not sure how to proceed with further debugging.

How do you check the content of your UAV?

Actually I can't and I don't know how to. That's why I am returning contents of UAV to render target to see it on screen. I just

return float4(tex1[uint2(input.pos.xy)],tex1[uint2(input.pos.xy)],tex1[uint2(input.pos.xy)],tex1[uint2(input.pos.xy)]);

to SV_Target in my pixel shader. Why? Won't this work?

This topic is closed to new replies.

Advertisement