The fragment of ShadowCaster in URP

Hi,
I’m learning URP code for Shadow, but have some doubts. We cast shadow use shader pass “LightMode” = “ShadowCaster” in file Lit.shader, It use ShadowPassVertex for vertex and ShadowPassFragment for fragment, which are defined in ShadowCasterPass.hlsl
I can understand the function ShadowPassVertex. But I am confused about ShadowPassFragment, it nearly does nothing. But I can find correct shadowmap texture in FrameDebugger. In my opinion, to get shadowmap, I should write depth in light space for shading point. But this ShadowPassFragment in URP write nothing, why? which is the real fragment?

You don’t need write depth value in fragment shader manually.

If you don’t use semantic like SV_Depth in fragment shader to write depth ,
it will use clip space position(SV_POSITION) to calculate depth value when rasterization stage.

You can check this page for some information. (See chapter Vertex shader outputs and fragment shader inputs)

Depth buffer was a thing from before programmable shaders when GPUs just drew stuff on the screen instead of mined bitcoin and only had a few fixed functions. Back then, you had no shaders at all, you just gave a few fixed commands and the GPU had to figure out how to draw it. Think 1990s arcade games, PlayStation1, or N64. So you just had one bit to switch - ZWrite On or ZWrite Off. That stayed true after shaders were added since it’s a useful optimization.

As @lilacsky824 says, you can control it with SV_Depth, but that turns off early Z and is much slower. Avoid using SV_Depth unless you really, really have to. Just output the vertex position from vertex shader using SV_Position and the GPU will do its magic.

By the way if you don’t want to write out depth, set ZWrite Off. Do this for transparent geometry. But obviously not useful in shadows (except in HDRP 'cause they’re not using depth-based shadow maps).

Thanks, I have read the doc.
‘A vertex shader needs to output the final clip space position of a vertex, so that the GPU knows where on the screen to rasterize it, and at what depth.’
So , after vertex, GPU will get the depth info, so I don’t need to write it by myself. It seems that, In FrameDebugger, it use the depth info in the shadow map, as my follow screenshot8466299--1124576--URP_Shadow.png
It shows that to render the left shadowmap texture, it use Pass ShadowCaster. I mean, in the code of the this Pass, I can’t find any code related to depth. We get the depth after ShadowPassVertex, but did’nt use it in ShadowPassFragment. So how does the left shadowmap texture come out? Is there any default rules?

When you or URP setup to draw to the screen, textures must be bound for writing. In URP’s case, it will bind a depth and a color texture. Your fragment shader will write the returned value to the color texture. But the vertex shader, by default, will end up writing the depth value to the depth texture. You can override this behavior, but you do not need to usually, as you could just modify your vertex shader to change the depth value.

Thanks you.
So, the left pic in my screenshot, the shadowmap doesn’t show the color texture, it really show the depth texture, it has nothing relation with ShadowPassFragment(this is for color output). In other case of FrameDebugger Pass, left picture shows color texture in most case. Is that so?

Almost. It’s not entirely accurate to say that the fragment shader has nothing to do with the depth buffer, even by default. If you follow URP’s ShadowCaster pass’s macro layer junk, you will eventually find something like “if alpha < 0.5, clip()” - for cutout shaders, so they don’t write to the depth buffer either. If the fragment is not clipped, depth will be written (derived from the vertex pass, as others have stated before).

Thank you very much, I want to know more info, in URP code, MainLightShadowCasterPass.cs, in function Configure, we call GetTemporary to get the shadowmap texture in GPU, so this texture id , include both color buffer and depth buffer, in MainLightShadowCasterPass, we get this shadow texture, has both color and depth info for later use, is that so?