5.Shader的子着色器基本构成

5.ShaderLab-ShaderLab语法规则-Shader的子着色器-基本构成


5.1 知识点

知识回顾

ShaderLab主要由4个部分组成:

  1. Shader的名字
  2. Shader的属性
  3. 1~n个子着色器
  4. 备用的Shader

第一部分:

Shader "着色器名字" 
{ 
    // 第二部分
    Properties
    {
        // 材质面板上可以看到的属性
    }

    // 第三部分
    SubShader
    {
        // 顶点-片段着色器 或 表面着色器 或 固定函数着色器
    }
    SubShader
    {
        // 更加精简的版本
        // 目的是适配旧设备
    }
    // 可以有n个SubShader代码块

    // 第四部分
    Fallback "备用的Shader"
}

SubShader语句块的作用

  • 每一个Shader中都会包含至少一个SubShader。
  • 当Unity想要显示一个物体的时候,就会在Shader文件中去检测这些SubShader语句块,然后选择第一个能够在当前显卡运行的SubShader进行执行。
  • 因此在一个Shader当中实现一些高级效果时,为了避免在某些设备上无法执行,可能会存在多个SubShader语句块,用于适配这些低端设备。
  • SubShader当中包含最终的渲染相关代码,决定了最终的渲染效果。

SubShader的基本构成

SubShader语句块中主要由3部分构成:

  1. 渲染标签:通过标签来确定什么时候以及如何对物体进行渲染
  2. 渲染状态:通过状态来确定渲染时的剔除方式、深度测试方式、混合方式等等内容
  3. 渲染通道:具体实现着色器代码的地方(每个SubShader语句块中至少有一个渲染通道,可以有多个)

第三部分:

SubShader
{
    // 渲染标签
    Tags { "标签名1" = "标签值1" "标签名2" = "标签值2" .....}

    // 渲染状态
    .....

    // 渲染通道
    Pass
    {
        // 第一个渲染通道
    }
    Pass
    {
        // 第二个渲染通道
    }
    // .............
}

在SubShader中每定义一个渲染通道Pass,就会让物体执行一次渲染。n个Pass,就会有n次渲染,在实现一些复杂渲染效果时需要使用多个Pass进行组合实现。但是我们要尽量减少它的数量,更多的Pass会增加性能消耗。

观察普通顶点着色器的结构

SubShader
{
    // 1. 渲染标签
    Tags { "RenderType"="Opaque" }

    // 2. 渲染状态
    LOD 100

    // 3. 渲染通道
    Pass
    {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        // make fog work
        #pragma multi_compile_fog

        #include "UnityCG.cginc"

        struct appdata
        {
            float4 vertex : POSITION;
            float2 uv : TEXCOORD0;
        };

        struct v2f
        {
            float2 uv : TEXCOORD0;
            UNITY_FOG_COORDS(1)
            float4 vertex : SV_POSITION;
        };

        sampler2D _MainTex;
        float4 _MainTex_ST;

        v2f vert (appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = TRANSFORM_TEX(v.uv, _MainTex);
            UNITY_TRANSFER_FOG(o,o.vertex);
            return o;
        }

        fixed4 frag (v2f i) : SV_Target
        {
            // sample the texture
            fixed4 col = tex2D(_MainTex, i.uv);
            // apply fog
            UNITY_APPLY_FOG(i.fogCoord, col);
            return col;
        }
        ENDCG
    }
}

总结

SubShader子着色器基本构成为:

  • Tags(渲染标签)
  • States(渲染状态)
  • Pass(渲染通道1)
  • Pass(渲染通道2)
  • ….(渲染通道n)

在Shader文件中可以存在多个SubShader语句块。当Unity想要显示一个物体的时候,会在Shader文件中去检测这些SubShader语句块,然后选择第一个能够在当前显卡运行的SubShader进行执行。因此在一个Shader当中实现一些高级效果时,为了避免在某些设备上无法执行,可能会存在多个SubShader语句块,用于适配这些低端设备。


5.2 知识点代码

Lesson05_ShaderLab_ShaderLab语法规则_Shader的子着色器_SubShader基本构成

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson05_ShaderLab_ShaderLab语法规则_Shader的子着色器_SubShader基本构成 : MonoBehaviour
{
    void Start()
    {
        #region 知识回顾

        //ShaderLab主要由4个部分组成
        //1.Shader的名字
        //2.Shader的属性
        //3.1~n个子着色器
        //4.备用的Shader

        //第一部分
        //Shader "着色器名字" 
        //{ 
        //      //第二部分
        //      Properties
        //      {
        //          //材质面板上可以看到的属性
        //      }

        //      //第三部分
        //      SubShader
        //      {
        //          //顶点-片段着色器 或 表面着色器 或 固定函数着色器
        //      }
        //      SubShader
        //      {
        //          //更加精简的版本
        //          //目的是适配旧设备
        //      }
        //      .....可以有n个SubShader代码块

        //      //第四部分
        //      Fallback "备用的Shader"
        //}

        #endregion

        #region 知识点一 SubShader语句块的作用

        //每一个Shader中都会包含至少一个SubShader
        //当Unity想要显示一个物体的时候
        //就会在Shader文件中去检测这些SubShader语句块
        //然后选择第一个能够在当前显卡运行的SubShader进行执行
        //因此在一个Shader当中实现一些高级效果时
        //为了避免在在某些设备上无法执行
        //可能会存在多个SubShader语句块,用于适配这些低端设备

        //SubShader当中包含最终的渲染相关代码,决定了最终的渲染效果

        #endregion

        #region 知识点二 SubShader的基本构成

        //SubShader语句块中主要由3部分构成
        //1.渲染标签:通过标签来确定什么时候以及如何对物体进行渲染
        //2.渲染状态:通过状态来确定渲染时的剔除方式、深度测试方式、混合方式等等内容
        //3.渲染通道:具体实现着色器代码的地方(每个SubShader语句块中至少有一个渲染通道,可以有多个)

        //第三部分
        //SubShader
        //{
        //  1.渲染标签
        //  Tags{ "标签名1" = "标签值1" "标签名2" = "标签值2" .....}
        //
        //  2.渲染状态
        //  .....
        //
        //  3.渲染通道
        //  Pass
        //  {
        //      第一个渲染通道
        //  }
        //  Pass
        //  {
        //      第二个渲染通道
        //  }
        //  .............
        //}

        //注意:
        //在SubShader中每定义一个渲染通道Pass,就会让物体执行一次渲染
        //n个Pass,就会有n次渲染,在实现一些复杂渲染效果时需要使用多个Pass进行组合实现
        //但是我们要尽量减少它的数量,更多的Pass会增加性能消耗

        #endregion

        #region 总结

        //SubShader子着色器基本构成为:
        //             --------Tags(渲染标签)
        //            |--------States(渲染状态)
        //SubShader---|--------Pass(渲染通道1)
        //            |--------Pass(渲染通道2)
        //            |--------....(渲染通道n)

        //在Shader文件中可以存在多个SubShader语句块
        //当Unity想要显示一个物体的时候
        //会在Shader文件中去检测这些SubShader语句块
        //然后选择第一个能够在当前显卡运行的SubShader进行执行
        //因此在一个Shader当中实现一些高级效果时
        //为了避免在在某些设备上无法执行
        //可能会存在多个SubShader语句块,用于适配这些低端设备

        #endregion
    }
}

Lesson05_NewUnlitShader.shader

Shader "ShaderTeach/Lesson05_NewUnlitShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
            //  1.渲染标签
        Tags { "RenderType"="Opaque" }
        
        //  2.渲染状态
        LOD 100

        //  3.渲染通道
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏