Advertisement

DirectX: ShadowMap becomes empty if 'discard' is used in shadow pass

Started by May 12, 2020 04:25 PM
11 comments, last by Calin 4 years, 8 months ago

Following the tutorial in msdn:

https://docs.microsoft.com/en-us/windows/uwp/gaming/render-the-shadow-map-to-the-depth-buffer

The above link is Step 2. You can go to Step 1 if you want from the links to the left in from the above link.

Anyways, it says the following: “The output of this shader is thrown away; it can call discard on every pixel.”

But when I do discard, when I check the graphics debugger and check the shadow map resource, this happens:
 

But if I use 

return input.pos.z / input.pos.w

in the pixel shader in the shadow render pass, I get this in the shader resource view:
 

It results that when I then sample from the ShadowMap, I can detect whether a pixel should be bright or shadowed.

I understand then that of course, since I return a value in the pixel shader, it gets filled with pixel values. That makes sense. So why does MSDN write that “it can call discard” for?
I've sampled the ShadowMap as they wrote in Step 3 like this but with modifications:

lighting = float(shadowMap.SampleCmpLevelZero( shadowSampler, shadowTexCoords, pixelDepth + epsilon ) );
if(lighting > 0)
{
	return 1;
}
return 0;

It works as said above, when I return in the pixel shader. So the question again,
why is MSDN saying that “discard” can be used?

I think it says that the API will discard. Not that you should write it yourself inside the pixel shader code.
Although the “discard” is a hyperlink to a page explaining discard command, so it could lead to confusion.

Advertisement

The whole quote is
“Note that on most devices, you can specify nullptr for the pixel shader (or skip specifying a pixel shader entirely). But some drivers may throw an exception when you call draw on the Direct3D device with a null pixel shader set. To avoid this exception, you can set a minimal pixel shader for the shadow rendering pass. The output of this shader is thrown away; it can call discard on every pixel.”

So it says I could even specify nullptr for the pixel shader, but shouldn't because of drivers.
So I'm pretty sure MSDN meant that discard could be used in the pixel shader.

I read it again. I think you are interpreting it correctly.

MSDN assumes that the raster itself compares its Z with the depth buffer. Before even calling the PS.

Are you outputting a float4 format in your PS?

If the driver sees a XYZW output from the PS, it can safely assume the third float is Z and safely discard the workload right after the raster. No need to call the PS. Maybe with a single float as output, the driver is not sure if it should optimize so early at the level of the raster.

Yes, I'm outputting float4.
Like this:

float4 ShadowMapPS(PShadowMapInput aInput) : SV_TARGET
{
	//discard;
    return aInput.pos.z / aInput.pos.w;
}

Remove “SV_TARGET” ?
Don't bind render target to it to make it know for sure you are not rendering nothing. Will it compile?
I haven't used graphics for a long time.

Advertisement

No unfortunately it won't compile if I remove it.

https://www.gamedev.net/forums/topic/625377-render-depth-only/4943346/

The link didn't really help as the tutorial in MSDN is exactly that. To render depth only and then render the shadows.

The question is why my rendering doesn't work when discard is used. Because I am only rendering depth, and yet, it's empty if I don't output a pixel.

But thanks anyways, I'll just have to keep debugging till I see it. I bet it's something small I missed.

Zansin said:
I bet it's something small I missed

Sure you'll solve it with a facepalm.

My problems are more serious. Any value i AND with 0xFFFFFFFC is giving me 0xFFFFFFFC again. Inside a compute shader. I am the whole day at it.

This topic is closed to new replies.

Advertisement