Search Unity

Limit Amount of Light Applied to Sprite

Discussion in '2D' started by Fariel, Sep 20, 2016.

  1. Fariel

    Fariel

    Joined:
    Feb 9, 2013
    Posts:
    29
    This is a cross-post between Answers and Forums to try to get a solution, because I'm impatient.

    Original, currently unanswered Answers post.

    Hi all! I've been bashing my head at this for a few days while trying to learn shader sorcery and I'm still not grasping what I need.

    My end goal here is to make a replacement to the "Sprites Diffuse" shader that has a cap to the amount of light it can receive. Basically, unlit, the sprite should appear black. However, when lit, the sprite should gradually become brighter until it gets to its normal image.

    Currently, this is not the behaviour exhibited by Unity. When you apply to much light to a sprite, it "whites out." The sprite information is lost as the pixels turn white.

    I notice that the "Sprites Diffuse" shader uses a surface shader to add the lighting. Or, at least, I think that's what I'm getting out of it. I'd rather do this in the fragment or vertex portions, to give smoother lighting. I managed to get lighting working, as in I could get the vertices "lit" or "unlit" but I couldn't figure out how to apply light strength or distance.

    Could anyone nudge me in the right direction?



    The only other thing I wanted this shader to do was to not account for the Z depth of the light versus the sprite so that lights don't have to be moved manually to effect sprites. This is kind of a "stretch goal" for the shader, though, as I have a feeling the answer to this will be kind of obvious once I know how to apply the lighting properly.
     
  2. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    I think it boils down to a multiply shader? i.e. lighting * sprite? because at the moment lighting appears to be 'lightening' the sprite even more, like it's adding the light to the sprite color. You want to multiply it by the light - and maybe you can scale the light amount too, or just say if red > 0.3 then red=0.3 or whatever.
     
  3. Fariel

    Fariel

    Joined:
    Feb 9, 2013
    Posts:
    29
    That's what I'm thinking, too, but I don't know how to get the light data in the shader code.

    In hindsight, it might have been better to post this in the shaders forum.

    At any rate, here's the shader pseudocode that I'm looking at:

    Code (csharp):
    1. Get pixel from texture (SAMPLE)
    2.  
    3. Set BLACK color (COLOR)
    4.  
    5. For each light:
    6.     Get light value from color/range/intensity (how do we do this? This is the sorcery.)
    7.     Add light value to COLOR
    8.  
    9. If COLOR is brighter than BLACK (aka there is light data that was added to black)
    10.     multiply SAMPLE by COLOR (tint the color of the pixel, but not change the brightness. Right?)
    11.     return result
    12. else
    13.     return COLOR (this should be black, right?)
    14.  
     
  4. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Hey there. I am by no means an expert, and hardly even an intermediate shader programmer. But in the docs you can see which built-in shader variables are accessible for lighting:

    https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html

    You may also be able to achieve the effect you're looking for with normal/specular maps, using the Standard shader set to Cutout.
     
    Last edited: Sep 21, 2016