Surface Shaders

Surface shaders use a material system to make it easy to write complex lit surfaces without the technical complexity of writing a lighting model.

Where a typical legacy shader defines a 'fragment program' that returns color values for each point, such as:

float4 fragment() : COLOR0
{
    return float4(1, 0, 0, 1);
}

This returns a basic flat shaded output, regardless of lighting and other effects.

A surface shader, by contrast, uses the Unity specific SurfaceOutput structure, which then has a predefined lighting model applied to it:

struct SurfaceOutputStandard
{
    fixed3 Albedo;      // base (diffuse or specular) color
    fixed3 Normal;      // tangent space normal, if written
    half3 Emission;
    half Metallic;      // 0=non-metal, 1=metal
    half Smoothness;    // 0=rough, 1=smooth
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // alpha for transparencies
};

struct SurfaceOutputStandardSpecular
{
    fixed3 Albedo;      // diffuse color
    fixed3 Specular;    // specular color
    fixed3 Normal;      // tangent space normal, if written
    half3 Emission;
    half Smoothness;    // 0=rough, 1=smooth
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // alpha for transparencies
};

This allows relatively simple surface shaders to be created, while retaining the full complexity of a high quality lighting model.