Search Unity

Frontface and Backface equal lighting

Discussion in 'Shaders' started by GixG17, Oct 17, 2015.

  1. GixG17

    GixG17

    Joined:
    Aug 18, 2013
    Posts:
    105
    I'm new at writing shader code but so far I've been doing pretty good as there's enough documentation on the internet for me to get by. There's one thing I just can't seem to find information on, though.

    I'm trying to write a shader that'll work for non-billboard grass. If I just use a standard shader with a cutoff, one side is lit properly but the other side of the grass blades don't get any light. That's to be expected and that works pretty well for most things except for grass or anything that should have some sort of translucency.

    So the problem isn't about rendering the backface, it's about computing both sides as if it were one. If light hits the backface, the frontface should get the same info and vice versa. If two different lights hit both sides, maybe it could even it out or just compute the strongest light or something. I'm not looking for anything accurate.

    The only documentation that I can find is about backface culling but I already know how to render the backface. I can't just use a unlit shader as I don't want my grass to glow in shaded areas.

    Can anyone help or steer me in the right direction? Thanks!
     
  2. Hjeldnes

    Hjeldnes

    Joined:
    Jul 22, 2012
    Posts:
    116
    Well, make grass blades that are one sided, only one visible side, like the default plane. Then it will be lit the same on both sides.
    Turn off culling, use a dotproduct between the normal and the light. if it returns positive, then that pixel is lit, and negative, then its in shadow and you can do tinting etc....
     
    GixG17 likes this.
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    While the above is an answer to the question you asked of "how to get lighting in both sides to be the same" it doesn't solve the issue you're experiencing. What you actually want to do for something like grass is a little different.

    A couple of options people use:
    * Ignore the surface normal and use "up" in world space as your normal. This has the benefit of working for most situations where you have grass as most lighting is going to be above the ground. Kind of fakes light passing through the grass when lights are on the other side. Works best with half lambert style shading (light dot normal * 0.5 + 0.5).
    * Calculate lighting twice, once with dot normal and once with dot -normal, and add the results together. You can darken light from the back side by testing the normal against the view direction, or I think there's a kind of hidden variable to know if the face is a backside or not in the pixel shader.
    * Look up translucent approximation. Similar to above in terms of doing lighting "twice".

    Edit: look up VFACE or FACE usage for Unity shaders for knowing if you're looking at the front or back of a face in the pixel shader. You could also test the normal against the camera vector in the vertex shader and test it there, but it might cause some oddities on some smooth geometry.
     
    Last edited: Oct 18, 2015
  4. GixG17

    GixG17

    Joined:
    Aug 18, 2013
    Posts:
    105
    I knew using the "up" in world space wouldn't be appropriate for my project but I'm thankful nonetheless that it was brought up.

    Hjeldnes' solution is basically what I was looking for and it works pretty much as I imagined it. I, then, added a dot with reversed normal as bgolus suggested and it works great.

    Doing a quick search on VFACE or FACE and I couldn't find much info on it (at least nothing that I could understand / reverse engineer) but I'll sure get back to it the day I'll be re-evaluating my shaders.

    So thank you both! This is exactly the kind of response I was looking for!