[toc]

如何创建

右键 -> Shader -> Standard Surface Shader

# 一个基于 Lambert 的表面着色器

Shader “Custom/SimplestSurfaceShader”
{
Properties
{
_Color (“Color”, Color) = (1,1,1,1)
_MainTex (“Albedo (RGB)”, 2D) = “white” {}
}
SubShader
{
CGPROGRAM
// 定义表面函数名为 surf, 使用 Lambert
#pragma surface surf Lambert

    //Input
    struct Input {
        float2 uv\_MainTex;
    };

    sampler2D \_MainTex;
    fixed4 \_Color;

    void surf(Input IN, inout SurfaceOutput o) {
        fixed4 c = tex2D(\_MainTex, IN.uv\_MainTex) \* \_Color;
        o.Albedo = c.rgb;
    }

    ENDCG
}
FallBack "Diffuse"

}

直接把漫反射光颜色传给 o 即可

# 在表面着色器中使用法线贴图

法线贴图的作用在于为每个顶点处重新赋值一个新的法线方向,以次用最少的消耗来模拟凹凸不平的效果

Shader “Custom/Bump”
{
Properties
{
_Color (“Color”, Color) = (1,1,1,1)
_MainTex (“Albedo (RGB)”, 2D) = “white” {}
_Normal(“Normal Map”,2D) = “bump” {}
_Bumpiness (“Bumpiness”,Range(0,1)) = 0
}
SubShader
{
CGPROGRAM
// 定义表面函数名为 surf, 使用 Lambert
#pragma surface surf Lambert

    //Input
    struct Input {
        float2 uv\_MainTex;
        float2 uv\_Normal;
    };

    sampler2D \_Normal;
    fixed \_Bumpiness;
    sampler2D \_MainTex;
    fixed4 \_Color;

    void surf(Input IN, inout SurfaceOutput o) {
        //采样法线贴图并解包
        fixed3 n = UnpackNormal(tex2D(\_Normal, IN.uv\_Normal));
        n \*= float3(\_Bumpiness, \_Bumpiness, 1);
        fixed4 c = tex2D(\_MainTex, IN.uv\_MainTex) \* \_Color;
        o.Albedo = c.rgb;
        o.Normal = n;
    }

    ENDCG
}
FallBack "Diffuse"

}

第二组纹理只需要 uv_Normal 即可获取到后缀为 Normal 的

由于法线贴图是压缩到 [0,1] 的,而法线范围是 [-1,1], 所以需要使用 UnpackNormal 函数来解压这个贴图重新映射到 [-1,1].

# 效果

# 流水线操作

# 顶点

尽管 Surface Shader 封装了完整的光照计算流程,但是仍然可以使用 vertex:vert 等函数自定义其中的部分流水线

顶点膨胀效果

沿法线方向膨胀, UnityCG.cginc 编写 SurfaceShader 时会自动引用

Shader “Custom/Expand”
{
Properties
{
_Color (“Color”, Color) = (1,1,1,1)
_MainTex (“Albedo (RGB)”, 2D) = “white” {}
_Expansion(“Expansion”,Range(0,0.1)) = 0
}
SubShader
{
CGPROGRAM
// 添加自定义顶点修改函数 vert
#pragma surface surf Lambert vertex:vert

    struct Input {
        float2 uv\_MainTex;
    };
    sampler2D \_MainTex;
    fixed \_Expansion;
    fixed4 \_Color;

    //顶点修改函数,输入/输出appdata\_full结构体
    void vert(inout appdata\_full v) {
        v.vertex.xyz += v.normal \* \_Expansion;
    }

    void surf(Input IN, inout SurfaceOutput o) {
        o.Albedo = tex2D(\_MainTex, IN.uv\_MainTex).rgb \* \_Color;
    }
    ENDCG
}
FallBack "Diffuse"

}