Unity's Rendering Pipeline
Reference Manual > ShaderLab Reference > Advanced ShaderLab topics > Unity's Rendering PipelineShaders define both how an object looks by itself (its material properties) and how it reacts to the light. Because lighting calculations must be built into the shader, and there are many possible light types, writing quality shaders that "just work" is an involved task. This document describes the pecularities of Unity's lighting&rendering pipeline and how the shaders need to be written to support all the different lights.
Light types and modes
In Unity, a Light can be Directional, Point or Spot light. Additionally, Ambient light level can be specified in Render Settings.
When any object is rendered, the lights that illuminate it are determined; and each light is chosen to render in Vertex or Pixel lighting mode. Per-pixel lighting usually looks a lot better, but is more expensive to render as well. So for each object, only some amount (specified in Quality Settings) of brightest lights are rendered in Pixel mode, while the remaining are rendered using Vertex lighting. When no lights are shining on an object, it is rendered in None mode.
Each object is then rendered in the following way:
- If there are any Vertex lights shining on it, they are all rendered at once. This renders all "vertex" passes in the shader, and the shader is expected to take both vertex lighting and ambient light into account here.
- If there are no Vertex lights shining on it, a shader is executed once, to take ambient light into account. This renders all "none" passes in the shader.
- After that, the pixel lighting is added on top. All "pixel" passes in the shader are rendered for each pixel light. This is the main reason why pixel lights are more expensive - because they have to render object for each light separately, instead of for all lights at once.
Each pass in a shader communicates its lighting type (pixel, vertex etc.) via Pass Tags.
Vertex Lights
Vertex lights are rendered using "vertex" passes (see pass tags). All lights are rendered at once, using a fixed function OpenGL/Direct3D lighting model (Blinn-Phong). It is not possible to use vertex programs with vertex lights because vertex programs and fixed function lighting can be used at the same time. Note that it is still possible to use fragment programs, reading the interpolated diffuse and specular lighting colors.
In summary, vertex lighting is calculated automatically. All you do in a shader is use the calculated diffuse/specular colors, either in a fragment program or in the texture combiner setup. Vertex lights do not support light cookies.
Pixel Lights
Implementing a pixel lighting shader part is much more involved, mostly because there are different light types (directional, point, spot) and a shader must be able to process all of them. For pixel lights you also want to write a custom vertex program (using fixed function lighting does not make sense - you could just use vertex lights and get much better performance) where you must calculate the lighting yourself.
If you implement pixel lighting passes in the shader, most often you want to implement passes for the case when no lights are shining (ambient pass) as well. See Pass Tags for details.
The details of implementing light types in custom shaders are described in Attenuation and Cookies for Pixel Lights.