Several questions regarding the custom lightning function

Hi,

Here are the questions that I haven’t figured yet, in a custom Lightning function:

  • How can I know if the current light is a directional light, a point light or a spotlight?

  • How can I modify the effect of the ambient color?

My current function is :

half4 LightingTest(SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
{
    half4 c;
    c.rgb = s.Albedo * _LightColor0.rgb * atten;
    c.a = s.Alpha;
    return c;
}

Thanks in advance,

For the ambient I’m thinking to add the tag noambient in the #pragma and doing it on my own in the surface function.

I’m not sure that it’s the best solution though.

For exemple: if I apply an ambient effect in the surface function, this effect doesn’t do anything if there is no light…

The short answer to all of your questions is “the same way you would do it with a vertex / fragment shader”. That’s not super helpful, obviously, but know when you’re going down this route gets much more complicated and surface shaders don’t have built in helpers for this as much.

There are a number of defines that exist to call out the type of light in use.

DIRECTIONAL
DIRECTIONAL_COOKIE
POINT
POINT_COOKIE
SPOT

There isn’t a SPOT_COOKIE as it’s assumed all spot lights use a cookie. Additionally Surface Shaders define a UNITY_PASS_FORWARDBASE and UNITY_PASS_FORWARDADD, and forward base will always be directional (or directional cookie), but forward add can be anything.

You would use these like this:

#if defined(DIRECTIONAL) || defined(DIRECTIONAL_COOKIE)
// do directional light specific stuff
#elif defined(POINT) || defined(POINT_COOKIE)
// do point light specific stuff
#elif defined(SPOT)
// do spot light specific stuff
#endif

There’s also the _WorldSpaceLightPos0 variable, which you can test if .w is 0 or 1, 0 == directional, 1 == point or spot, or the USING_DIRECTIONAL_LIGHT define, which also differentiates between directional and point or spot. When it comes to surface shaders, the “atten” value generally handles everything relevant to differentiate between point or spot, or any cookies, so unless you want something more specific from spotlights you can get away with just:

#ifdef USING_DIRECTIONAL_LIGHT
// directional stuff
#else
// point and spot stuff
#endif

This is actually a more complex question in some ways. Surface Shaders have a custom GI function which passes in data that may have come from light maps or light probes for you to do with as you want.

https://docs.unity3d.com/Manual/SL-SurfaceShaderLighting.html
half4 Lighting<Name>_GI (SurfaceOutput s, UnityGIInput data, inout UnityGI gi);

There’s very little documentation for this function, so you’ll really have to dig into the existing code to figure out what to do with it. If you’re not concerned with lightmaps you could conceivably sample either the ambient colors or the light probe SH directly in the Surf function, just make sure you only do it when UNITY_PASS_FORWARDBASE is defined as you don’t want to do ambient lighting on every light, only the first.

See this page for a simple example of sampling a light probe:

o.diff.rgb += ShadeSH9(half4(worldNormal,1));

Thanks a lot for your answer, Il will take the time to look at it thoroughly.