US5L9——表面着色器

表面着色器

表面着色器(Surface Shader)是 Unity 自己创造的一种着色器代码类型,
它的本质是对顶点 / 片元着色器的一层封装,它需要的代码量很少,很多工作都帮助我们去完成了

它的优点在于,它帮助我们处理了很多光照细节,我们可以直接使用而无需自己计算实现光照细节,
它的缺点是渲染的消耗较大,可控性较低。

我们可以在创建 Shader 时,选择创建 Standard Surface Shader

image

通过观察该 Shader 文件的内部结构,会发现着色器相关代码被放在 SubShader​ 语句块中(并非 Pass​ )的 CGPROGRAM​ 和 ENDCG​ 之间

image

表面着色器的特点就是:

  1. 直接在 SubShader​ 语句块中书写着色器逻辑
  2. 我们不需要关心也不需要使用多个 Pass​,每个 Pass​ 如何渲染,Unity会在内部帮助我们去处理
  3. 可以使用 CG 或 HLSL 两种 Shader 语言去编写 Shader 逻辑
  4. 代码量较少,可控性较低,性能消耗较高
  5. 适用于处理需要和各种光源打交道的着色器(主机、PC 平台时更适用,移动平台需要考虑性能消耗)

表面着色器的结构

我们通过实例对比 表面着色器 和 顶点/片元着色器 的区别,最大区别就是,表面着色器中没有显示的 Pass​ 了
而其中最为关键的几个部分为:

  1. 编译指令

    1
    2
    3
    4
    5
    // Physically based Standard lighting model, and enable shadows on all light types
    #pragma surface surf Standard fullforwardshadows

    // Use shader model 3.0 target, to get nicer looking lighting
    #pragma target 3.0
  2. 结构体

    1
    2
    3
    4
    struct Input
    {
    float2 uv_MainTex;
    };
  3. 自定义函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void surf (Input IN, inout SurfaceOutputStandard o)
    {
    // Albedo comes from a texture tinted by color
    fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    o.Albedo = c.rgb;
    // Metallic and smoothness come from slider variables
    o.Metallic = _Metallic;
    o.Smoothness = _Glossiness;
    o.Alpha = c.a;
    }

虽然这个默认创建出来表面着色器内没有任何光照计算内容,但是这个表面着色器依然有光照和阴影效果:

image

因为当我们编写完表面着色器后,Unity 会自动将其编译为顶点 / 片元着色器,Unity 会将光照处理、反射、折射、阴影、雾效等等相关计算代码自动加入
点击表面着色器,我们在 Inspector 窗口内可以点击 Show generated code​ 即可查看生成出来的 Shader 代码

image

为什么不一开始学习表面着色器

表面着色器 是 顶点/片元着色器 的封装,要了解了 顶点/片元着色器,才能了解表面着色器的本质原理
学会了更“底层”的 顶点/片元着色器 编写,以后学习其它的 Shader 语言,才会更加得心应手!