Loading...
墨滴

高照光

2021/10/15  阅读:24  主题:默认主题

ShaderLab开发规范之布局

ShaderLab开发规范之布局

一. ShaderLab 代码整体布局

 Shader "Shader名字"
 {
     //1.属性块
     Properties{}

     //2.代码块
     CGINCLUDE
     ...
     ENDCG
     或者
     HLSLINCLUDE
     ...
     ENDHLSL
     或者
     GLSLINCLUDE
     ...
     ENDGLSL

     //3.子着色器列表块
     SubShader{
         Tags{}
         Pass{...}
         Pass{...}
         ...
     }
     SubShader{...}
     ...

     //4.备用着色器定义块
     FallBack "..."
 }

二. 材质属性定义

  • 关键字:Properties
  • 属性定义格式: 属性名("属性描述",属性类型) = 属性默认值
  • 用处:只要在这里被定义的属性,就在Unity的Editor中,被材质的默认Inspector识别.也就是说可以通过编辑器修改这个属性,设置预设值.
  • 需要注意:
    1. 每个属性的定义,在语句最后一定不能有分号
    2. 这里定义了某个属性,那么使用这个Shader的材质,本属性就是不会被SetGlobalxxx来改变的.
  • 布局示例:
   Properties
   {
       //主颜色,类型:颜色
       _Color ("Main Color", Color) = (1, 1, 1, 1)
       //颜色的调整值, 类型:范围值
       _ColorMultiplier("Color Multipler", Range(0,10)) = 2  
       //主纹理, 类型:纹理
       _MainTex ("Effect Texture", 2D) = "black" {} 
       //环境立方体贴图, 类型: 立方体贴图
       _EnvCube("Env Cube", Cube) = "white" {} 
       //切割区域, 类型:向量
       _ClipRect("ClipRect", Vector) = (-50000,-50000,50000,50000)
       //曝光系数, 类型:浮点值
       _BloomFactor("BloomFactor", Float) = 0
   }

三. 逻辑代码区域

  • 关键字:会根据使用的语言有不同.
    • cg语言:CGINCLUDE ... ENDCG
    • hlsl语言:HLSLINCLUDE ... ENDHLSL
    • glsl语言:GLSLINCLUDE ... ENDGLSL
  • 用处:当前着色器中需要有不同逻辑的子着色器或者pass时,方便代码编写和统一管理.也是为了用于分离业务逻辑定义和渲染标记定义.
  • 需要注意:
    1. 每个着色器的代码文件中尽量只有一个逻辑代码块.
    2. 每个着色器的代码文件中尽量只使用一种高级语言,cg,hlsl,glsl.其中cg和hlsl语法几乎一样,并且推荐使用这两种.
    3. 在定义结构体时,一定不要忘记在定义的结束大括弧后加上分号
    4. 如果这个代码块内容需要被共享给其他着色器代码文件,那么可以把这个代码块提取出来,另外放到一个文件中,然后通过#include的方式引用.(如果是cg代码就放到xxx.cginc文件,如果时hlsl代码就放到xxx.hlsl文件中.)
  • 布局示例
     //1.引用区域
     #include "...";
     ...

     //2.常量或者宏的定义区域
     #define _XXX_XXX_ON 1
     static float xxx = 23;
     const float xxx = 23;
     ...

     //3.结构体的定义区域
     struct xxx {};
     ...

     //4.需要外部赋值的变量定义区域
     uniform float xxx;
     ...

     //5.通用方法定义区域
     inline float getNoise(...)
     {...}
     void resetValue(...)
     {...}

     //6.顶点程序定义区域
     v2f vert(appdata v) 
     {...}

     v2f vertAdd(appdata v) 
     {...}

     v2f vertBlend(appdata v) 
     {...}
     ... 

     //7.片元程序定义区域
     fixed4 frag(v2f i):SV_Target 
     {...}

     fixed4 fragAdd(v2f i):SV_Target 
     {...}

     fixed4 fragBlend(v2f i):SV_Target 
     {...}
     ...

四. 可匹配的着色器列表

  • 关键字: SubShader
  • 用处:这里定义一系列的SubShader,在需要着色时,应用会从上到下的顺序,一个一个筛选可以执行的着色器.
  • 注意:
    1. 可以有多个子着色器.
    2. 每个子着色器内部可以有多个渲染遍Pass.
    3. 排列着色器代码时,一定把你最希望匹配的子着色器放在最前面.
  • 布局:
SubShader
{
    //1.子着色器等级
    LOD 100
    //2.标签
    Tags{...}
    //3.渲染设置列表
    [Render Setup]
    //4.渲染遍列表(走一遍GPU的渲染流程,叫做渲染遍 Pass)
    Pass 
    {
        ...
    }

    Pass 
    {
        ...
    }
    //5.引用其他Shader的渲染遍.
    UsePass "某个Shader的名字/Pass名字"
    ...
}
  • 下面介绍一下子着色器的一些关键元素
    1. 着色标签:

      • 关键字: Tags

      • 格式模板: Tags{"Tag1"="Tag1Value" "Tag2"="Tag2Value"}

      • 用处: 这里的标签是给Unity3D的渲染逻辑使用的,用于判断在Unity渲染处理中是否执行某个逻辑.也可以自定义一些标签,用于自己独有的逻辑.

      • 注意:

        1. Tags标签可以在SubShader的域中定义,也可以在Pass的域中定义.
        2. 标签和值中间的赋值等号之间不可以有空格.
        3. 每个标签之间使用空格分隔.
        4. 标签和值都是用引号包括的字符串内容.
      • 一些常用标签的

        • Queue:这个是用来表示当前着色器在哪个渲染队列中.
        渲染队列 描述 渲染队列值
        Background 这个队列被最先渲染。它被用于skyboxes等。 1000
        Geometry 这是默认的渲染队列。它被用于绝大多数对象。不透明几何体使用该队列。 2000
        AlphaTest 通道检查的几何体使用该队列。它和Geometry队列不同,对于在所有立体物体绘制后渲染的通道检查的对象,它更有效。 2450
        Transparent 该渲染队列在Geometry和AlphaTest队列后被渲染。任何通道混合的(也就是说,那些不写入深度缓存的Shaders)对象使用该队列,例如玻璃和粒子效果。 3000
        Overlay 该渲染队列是为覆盖物效果服务的。任何最后被渲染的对象使用该队列,例如镜头光晕。 4000
        • LightMode:这个是用来表示当前着色器选择哪个光照模式
        光照模式 描述
        Always 适用与任何渲染模式,不使用任何光源
        ForwardBase 用于前向渲染, 只能够使用:环境光,主光源,顶点/球谐光,光照贴图
        ForwardAdd 用于前向渲染, 附加每个像素光源,每个pass对应一个像素光源.
        Deferred 用于延迟渲染, 渲染G-Buffer
        ShadowCaster 用于渲染对象深度到阴影贴图或者深度贴图
        PrepassBase 用于遗留的延迟照明,渲染法线和高光指数
        PrepassFinal 用于遗留的延迟照明,通过结合纹理,照明和发射渲染最终的颜色。
        Vertex 用于遗留的没有光照贴图的顶点光渲染,所有顶点都能被使用.
        VertexLMRGBM 用于遗留的带有光照忒图的顶点光渲染,在PC平台,这里的光照贴图使用RGBM格式来编码.
        VertexLM 用于遗留的带有光照忒图的顶点光渲染;在移动平台,这里的光照贴图使用double-LDR格式来编码
        • RenderType:渲染类型,这个用处挺多,比如:Unity生成的深度图,就是利用这个标签.我们也可以使用这个标签,不过要使用Camera.SetReplacementShader函数.
    2. 渲染设置标记 (Render Setup )

      • 关键字:这个太多了,Blend,ZTest,ZWrite,Cull,Lighting 等等.

      • 用处:这里的标记主要是给GPU用的,通道设定显示硬件的各种状态,例如能打开alpha混合,能使用雾,等等

      • 注意:

        1. 标记定义完成后,不能有分号作为结束.
        2. 标记和值之间都是使用空格作为分割.
        3. 标记与标记之间使用空格或者换行作为分割.
      • 一些常用标记的作用

        标记格式 值列表 描述
        Lighting VALUE On; Off 开启或关闭顶点光照。开启灯光之后,顶点光照才会有作用
        Cull VALUE Back; Front; Off 设置多边形剔除模式
        ZTest VALUE (Less; Greater; LEqual; GEqual; Equal; NotEqual; Always) 设置深度测试模式
        ZWrite VALUE On ; Off 设置深度写模式
        Fog {VALUE} Mode; Color; Density; Range 设置雾参数:模式,颜色,密度,区域
        AlphaTest VALUE1 VALUE2 (Less; Greater; LEqual; GEqual; Equal; NotEqual; Always) CutoffValue 开启alpha测试
        Blend VALUE1 VALUE2[,VALUE3 VALUE4] Zero; One; SrcAlpha; SrcColor; DstAlpha; DstColor; OneMinusXXXX 设置alpha混合模式
        ColorMask VALUE RGB; A; 0; any combination of R, G, B, A 设置颜色写遮罩。设置为0将关闭所有颜色通道的渲染
        Offset VALUE1,VALUE2 float 类型值 设置深度偏移
    3. 着色器等级

      • 关键字: LOD
      • 格式: LOD 整数值
      • 用处: 用于在渲染时筛选子着色器.
      • 注意: 定义Lod数值越大的SubShader,应该放在前面.
    4. 渲染遍Pass

      • 关键字: Pass,UsePass
      • 用处: 每个Pass都表示从头到尾执行一遍GPU渲染流程.这里主要定义渲染设置,编译设置等.(本来这里可以定义业务逻辑,不过我们规范把业务逻辑全部定义到逻辑代码区域中.)
      • 注意:
        1. 在Pass中也可以使用着色标签和渲染设置,如果与SubShader中的有重复,就应用Pass中的.
        2. 每个Pass就是一次渲染提交,尽量减少Pass的数量.
        3. 在Pass中定义Name时,一定要使用全部大写.
        4. 使用UsePass关键字,可以引用其他着色代码文件中的Pass.引用格式为:UsePass "Shader名字/Pass名字"
        5. 这里如果这里没有逻辑的话,每个行后就不要有分号
      • 布局示例:
      Pass{
          //1.定义名字
          Name "全部大写的Pass名字"
          //2.标签
          Tags{...}
          //3.渲染设置列表
          [Render Setup]

          //4.使用cg或者hlsl语言来写的,决定着色器如何编译的一些编译指令.
          //cg语言
          CGPROGRAM
             #pragma target 3.0
             #pragma vertex vert
             #pragma fragment frag
             #pragma multi_compile _XXX_ON _XXX_OFF
             #pragma multi_feature _XXXX_ON _XXXX_OFF
             ....
          ENDCG
          或者
          //hlsl语言
          HLSLPROGRAM
             #pragma target 3.0
             #pragma vertex vert
             #pragma fragment frag
             #pragma multi_compile _XXX_ON _XXX_OFF
             #pragma multi_feature _XXXX_ON _XXXX_OFF
             ....
          ENDHLSL
           或者
          //glsl语言
          GLSLPROGRAM              
             ....
          ENDGLSL
      }

五. 备用着色器

  • 关键字: FallBack
  • 用处:当所有的子着色器都不被匹配时,就执行这里指定的着色器
  • 注意:
    1. 这里指定的是一个着色器的名字,并不是文件路径名.
    2. 如果使用关键字Off,就表示关掉了这个退路.
  • 示例:
Fallback "Gonbest/FallBack/FBWithShadowAlpha"

高照光

2021/10/15  阅读:24  主题:默认主题

作者介绍

高照光