Search Unity

Casting shadows from your custom lights shader

Discussion in 'Shaders' started by Tudor, Sep 11, 2015.

  1. Tudor

    Tudor

    Joined:
    Sep 27, 2012
    Posts:
    150
    I've implemented my own deferred point-light volume shader for special effects reasons. The volume is a sphere mesh and it lights whatever geometry it intersects.
    I more or less got it to behave like unity's own point light, except obviously it's not casting shadows.

    My question is what are my options (and what is the easiest approach) to have my custom light also cast (hard) shadows? I'm guessing you can't just pass a point and a radius to some sort of unity magic shadow maker and it writes to the shadow map for you...

    I only have some theoretical idea about how unity calculates shadows, and I don't know where that happens (it doesn't seem to be in the "built-in standard shader" archive).
     
  2. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    It is possible, but I am gathering that you're going to need to implement your own shadow mapping for said light. Unless, of course, someone knows how to tap the 5.x cubemap shadows in unity. (@Aras, we need you! :D)

    And you're not going to find the shadow mapping helpers in the built-in standard shader, they're actually in their own CG includes. :)

    Would love to see your custom light BTW. :)
     
    Zuntatos likes this.
  3. Zuntatos

    Zuntatos

    Joined:
    Nov 18, 2012
    Posts:
    612
    My own custom light solution

    They 'standard' way is basically this:

    Draw a depth cubemap with Camera.RenderToCube with a depth shader
    In the light shader, reconstruct the depth of the light (depth buffer -> world pos -> distance etc)
    Compare that depth to the one found in the cubemap
    If it's bigger, it's shadow. (plus some shadow bias etc)

    P.S: Practically all the math required is hidden in the builtin cginc's, like UnityDeferredLibrary.cginc and UnityShadowLibrary.cginc, but besides that you'd need to set up the camera/culling/LoD & all the shader variables / keywords
     
  4. Tudor

    Tudor

    Joined:
    Sep 27, 2012
    Posts:
    150
    Okay so it's builtin and you have to make your own shadows.

    So I'm on the fragment of my light volume (sphere), I have the pixel I'm rendering and the light position, depth etc, and the cubemap taken from the light's position.
    Methinks that I need a ray from my light's position (I guess world space), that goes through the current fragment's position and also through the cubemap. Then when I render the fragment, I sample the cubemap with that ray going through my fragment, and see if the cubemap's pixel's depth is in front or behind my current fragment. Is that right? Is the "depth cubemap" the "shadow map"?

    Great work with your own custom lights btw! I hadn't seen your post. You make a very good point on static lights (not re-rendering the depth cubemap each frame).


    FuzzyQuills, my light is not very exciting at the moment (the unity Custom Area Lights project using command buffers is more interesting and educational), but I'll post something when I have something fancy.
     
    Zuntatos likes this.
  5. Zuntatos

    Zuntatos

    Joined:
    Nov 18, 2012
    Posts:
    612
    In the cubemap I wrote a depth value from 0...1 where 1 is max range of the point light
    Then in the light volume it's basically
    Code (CSharp):
    1. float3 ldir = wpos - lpos;
    2. float ldepth = length(ldir) * (1 / lrange) * bias;
    3. float shadow = texCUBE(_DepthCube,  ldir)  < ldepth ? 0.0 : 1.0;
    where you then multiply shadow with the lighting, or discard or w/e you want to do (0.0 as in, no lighting)

    Thanks. It seemed like the only solution for my game, as it's fully procedural and editable.
    Baking lighting isn't viable as it would produce very blurry shadows and it would be hard to set up if you'd want to use some kind of dynamic system to support normal mapping / specular highlights. But it would have great framerate.
    Dynamic shadows isn't viable as it has terrible framerate, but does produce sharp shadows.

    Updating only lights near an edit gets most of the benefits of both sides without most of their drawbacks.
     
    Tudor likes this.