Custom ShadowCaster pass: How to disable shadow casting, but still write to depth texture?

I’d like to control shadow casting of a submesh with some value on a vertex color or a UV channel.

So, I wrote my own shadowcaster pass that discards a pixel when a corresponding flag in a vertex color is set to off.

But the trouble is that if I discard a shadowcaster pass, then shader doesn’t write to the depth texture either. And some of my FX go wrong (like a depth fog).

So, I need a parameter-controlled shader that can:

  1. Drop shadows, write to the depth texture
  2. Don’t drop shadows, still write to the depth texture

PS: I can achieve #2 behavior by adding a "ForceNoShadowCasting" = "True" tag, but I want to control it via shader code.

I’m not sure, but seems that SHADOWS_DEPTH does the trick.

Here’s a bit of code in my shadow caster pass:

#ifndef SHADOWS_DEPTH
clip(dropShadow - 0.5);
#endif

WARNING! This is wrong, see bgolus’s reply below with a working piece of code.

The camera depth texture also uses SHADOWS_DEPTH, so that will also cause it to be clipped there too, unless your dropShadow variable is dependant on something that’s different between a shadow map and camera depth texture.

I use this code:

#ifdef SHADOWS_DEPTH
if (any(unity_LightShadowBias)) {
  // not the camera depth texture
  clip(-1); // replace with whatever
}
#endif

The unity_LightShadowBias holds the shadow caster bias settings you set per light. For the camera depth texture this should be all zeros, and shouldn’t be all zeros for shadow maps (as long as you don’t have a light with a bias and normal bias of 0.0).

1 Like

I was so confused seeing that even with both defined(UNITY_PASS_SHADOWCASTER) && defined(SHADOWS_DEPTH) I couldn’t get Unity to distinguish between using the shadowcaster pass for actually casting shadows from this… whatever this is (after fiddling so long with shaders I feel like I still have no idea how this thing works). Thanks for the solution! This is infinitely better than what I was using before, dot(ObjectViewDirNorm(), ObjectCameraDirNorm()) > 0.999.

I am very disappointed this is not documented properly anywhere, and it only has a runtime solution as opposed to a shader variant keyword or something.

PS: Seems that in ** @bgolus **'s code there should be

#ifndef SHADOWS_DEPTH