I was studying Ryan Bruck's tutorial on volumetric clouds rendering (https://shaderbits.com/blog/creating-volumetric-ray-marcher), and was trying to recreate it in Unity. I managed to do the 3D texture creation and volumetric rendering with raymarching: But as you can see, and as is to be expected, the shadow is cast from the original mesh, and not from the cloud within. I read online that a custom shadow could be created by writing to the depth buffer, but I couldn't find much documentation on how to do that, and I think volumetric clouds would be kind of a special case, since each pixel is checking multiple samples from the volume. My question is, would that be possible? I think I'm missing some kind of basic shader knowledge about depth buffers and shadowmaps, so if anybody could show me a starting point to learn those I'd be very grateful!
All depth buffers, including shadow maps, can only hold a single depth per pixel (ignoring MSAA, which Unity's built in shadow maps don't use). So for a shadow map, you'd just need to make due with a dithered shadow. The way I would probably approach this would be to have either a random value or an index matrix that I get per pixel and use as the cutoff for what density to stop at. Something like a 4x4 index matrix with a 1.0/16.0 to 1.0 range. Then start iterating through the volume. If you reach the requisite density, then write that depth. If you don't reach the requisite density then discard. Note: Unity's Standard shader uses a 4x4 index matrix for its semitransparent shadows already, but the pattern is stored in a form that's not useful for this use case. It's a 3D texture which you input in the appropriate alpha value to the volume texture's Z and it spits out the appropriate B&W pattern. You need the full range of values. You can write out the depth using out float depth : SV_Depth in the frag function definition. That depth needs to be in the appropriate form, which if you can calculate the view space depth can be converted with this function: Code (csharp): float LinearToDepth(float linearDepth) { return (1.0 - _ZBufferParams.w * linearDepth) / (linearDepth * _ZBufferParams.z); } That will produce a shadow dithered both in the depth and the opacity.