Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  2. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

Is it possible for a volumetric cloud using raymarch to cast shadows?

Discussion in 'Shaders' started by magehuntz, Jul 15, 2019.

  1. magehuntz

    magehuntz

    Joined:
    Mar 24, 2017
    Posts:
    4
    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!
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    8,694
    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):
    1. float LinearToDepth(float linearDepth)
    2. {
    3.     return (1.0 - _ZBufferParams.w * linearDepth) / (linearDepth * _ZBufferParams.z);
    4. }
    That will produce a shadow dithered both in the depth and the opacity.
     
  3. magehuntz

    magehuntz

    Joined:
    Mar 24, 2017
    Posts:
    4
    Thanks, I'm gonna try that!
     
unityunity