Custom Lighting models in Surface Shaders

When writing Surface Shaders, you're describing properties of a surface (albedo color, normal, ...) and the lighting interaction is computed by a Lighting Model. Built-in lighting models are Lambert (diffuse lighting) and BlinnPhong (specular lighting).

Sometimes you might want to use a custom lighting model, and it is possible to do that in Surface Shaders. Lighting model is nothing more than a couple of Cg/HLSL functions that match some conventions. The built-in Lambert and BlinnPhong models are defined in Lighting.cginc file inside Unity ({unity install path}/Data/CGIncludes/Lighting.cginc on Windows, /Applications/Unity/Unity.app/Contents/CGIncludes/Lighting.cginc on Mac).

Lighting Model declaration

Lighting model is a couple of regular functions with names starting with Lighting. They can be declared anywhere in your shader file or one of included files. The functions are:

  1. half4 LightingName (SurfaceOutput s, half3 lightDir, half atten); This is used in forward rendering path for light models that are not view direction dependent (e.g. diffuse).
  2. half4 LightingName (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten); This is used in forward rendering path for light models that are view direction dependent.
  3. half4 LightingName_PrePass (SurfaceOutput s, half4 light); This is used in deferred lighting path.

Note that you don't need to declare all functions. A lighting model either uses view direction or it does not. Similarly, if the lighting model will not work in deferred lighting, you just do not declare _PrePass function, and all shaders that use it will compile to forward rendering only.

Decoding Lightmaps

Decoding lightmap data can be customized in a similar fashion as the lighting function for forward and deferred lighting. Use one of the functions below depending on whether your light model is view direction dependent or not. To decode standard Unity lightmap texture data (passed in color, totalColor, indirectOnlyColor and scale arguments) use built-in DecodeLightmap function.

Custom lightmap decoding functions handle forward and deferred lighting rendering paths automatically. However you must be aware that in deferred case LightingName_PrePass function will be called after lightmap decoding and light argument will contain sum of realtime lighting and lightmaps. If necessary you can distinguish forward and deferred paths by using built-in UNITY_PASS_PREPASSFINAL macro.

Functions to customize decoding of Single lightmaps are:

  1. half4 LightingName_SingleLightmap (SurfaceOutput s, fixed4 color); This is used for light models that are not view direction dependent (e.g. diffuse).
  2. half4 LightingName_SingleLightmap (SurfaceOutput s, fixed4 color, half3 viewDir); This is used for light models that are view direction dependent.

Functions to customize decoding of Dual lightmaps are:

  1. half4 LightingName_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade); This is used for light models that are not view direction dependent (e.g. diffuse).
  2. half4 LightingName_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade, half3 viewDir); This is used for light models that are view direction dependent.

Functions to customize decoding of Directional lightmaps are:

  1. half4 LightingName_DirLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal); This is used for light models that are not view direction dependent (e.g. diffuse).
  2. half4 LightingName_DirLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, half3 viewDir, bool surfFuncWritesNormal, out half3 specColor); This is used for light models that are view direction dependent.

Examples

Surface Shader Lighting Examples

Page last updated: 2013-06-28