• Shader 中 SubShader Tags Pass的理解


    Shader 中 SubShader Tags Pass的理解

    SubShader
        {
            Tags
            {"RenderType" = "Opaque"}
            Pass
            {
                Tags
                {"LightMode" = "UniversalForward"}
                HLSLPROGRAM
                .......
                ENDHLSL
            }
            Pass
            {
                Tags
                { "LightMode" = "SRPDefaultUnlit"}
                HLSLPROGRAM
                .......
                ENDHLSL
             }
         }
    FallBack "other"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    SubShader

    这里解释一下 SubShader Tags Pass的意思
    一个Shader中可以有多个SubShader,但只执行第一个可执行的SubShader。

    当你编写的shader需要在多种GPU下运行时,比如一个游戏同时在手机和电脑端运行,并且使用同一个shader,由于硬件本身的原因,第一个SubShader可能无法运行,可编写多个SubShader,让游戏去使用第二个或者第三个SubShader。

    在所有SubShader的后面可定义 Fallback。基本上就是说,“如果没有任何子着色器能够在此硬件上运行,则尝试使用另一个着色器中的子着色器”。Fallback是最后一道防线,如果以上SubShader都不能用就只能用最低级的。不写就是不管了,会出现不可预测的渲染错误。

    SubShader的状态设置

    ShaderLab提供了一系列渲染状态的设定,这些指令可以设置显卡的各种状态,例如是否开启混合/深度测试等。

    Cull     Cull Back|Front|Off
    设置剔除模式,剔除背面|正面|关闭剔除,默认CullBack

    ZTest    ZTest Less Greater|LEqual|GEqual|Equal|NotEqual|Always
    设置深度时使用的函数, 默认ZTest LEqual 小于或等于目标深度才能被渲染

    ZWrite    ZWrite On|Off
    开启和关闭深度写入, 默认ZWrite On

    Blend    Blend SrcFactor DstFactor
    开启并设置混合模式

    SubShader的Tags

    进入SubShader,第一个遇到的便是Tags,这个Tags定义了该subshader的渲染类型和队列位置。
    “RenderType” = “Opaque”
    “Queue”=“Geometry”

    RenderType和Queue是SubShader最重要的两个tags,下面介绍一下。
    此外还有标签
    DisableBatching(顶点动画需要关闭和批,True/False)
    ForceNoShadowCasting(强制不投射阴影,True/False)
    IgnorceProjector(不受projector影响,True/False)
    CanUseSpriteAtlas(用于精灵,True/False)
    PreviewType(Unity中的预览类型,Plane/SkyBox)

    RenderType

    RenderType标签将着色器分类为若干预定义组,例如是一个不透明的着色器,或alpha测试的着色器等。被用于着色器替换,或者在某些情况下用于生成相机的深度纹理。

    所有Unity 内置的着色器,都设置了一个RenderType类型,便于渲染时的着色器替换。

    内置的RenderType类型有:

    Opaque: 用于大多数着色器(法线着色器、自发光着色器、反射着色器以及地形的着色器)。
    Transparent:用于半透明着色器(透明着色器、粒子着色器、字体着色器、地形额外通道的着色器)。
    TransparentCutout: 蒙皮透明着色器(Transparent Cutout,两个通道的植被着色器)。
    Background: Skybox shaders. 天空盒着色器。
    Overlay: GUITexture, Halo, Flare shaders. 光晕着色器、闪光着色器。
    TreeOpaque: terrain engine tree bark. 地形引擎中的树皮。
    TreeTransparentCutout: terrain engine tree leaves. 地形引擎中的树叶。
    TreeBillboard: terrain engine billboarded trees. 地形引擎中的广告牌树。
    Grass: terrain engine grass. 地形引擎中的草。
    GrassBillboard: terrain engine billboarded grass. 地形引擎何中的广告牌草。

    这些RenderType的类型名称实际上是一种约定,用来区别这个Shader要渲染的对象,当然你也可以改成自定义的名称,RenderType类型名称使用自定义的名称并不会对该Shader的使用和着色效果产生影响,甚至"RenderType"这个名称也可以修改。

    指定RenderType的名称,主要是为了配合使用替代渲染的方法。
    Unity可以运行时替换符合特定RenderType的Shader。主要通过Camera.RenderWithShader或者Camera.SetReplacementShader这两个接口来实现。

    官方对于替代渲染的解释
    https://docs.unity3d.com/Manual/SL-ShaderReplacement.html

    两个接口的区别
    RenderWithShader与SetReplacementShader的区别是RenderWithShader是 当前帧 用指定的Shader渲染,SetReplacementShader是替换后的 每一帧 用指定的Shader渲染。

    当把代码SetReplacementShader换成RenderWithShader发现没什么效果,主要是因为RenderWithShader是当前帧用指定的Shader渲染,要与SetReplacementShader同样的效果,必须每帧都调用RenderWithShader。注意必须在OnGUI函数里调用。

    Queue

    Queue渲染队列,用来指定当前shader作用的对象的渲染顺序:
    Unity中的几种内置的渲染队列,按照渲染顺序,从先到后进行排序,队列数越小的,越先渲染,队列数越大的,越后渲染。

    • Background(1000) 最早被渲染的物体的队列。
    • Geometry (2000) 不透明物体的渲染队列。大多数物体都应该使用该队列进行渲染,也是UnityShader中默认的渲染队列
    • AlphaTest (2450) 有透明通道,需要进行Alpha Test的物体的队列,比在Geomerty中更有效。
    • Transparent(3000) 半透物体的渲染队列。一般是不写深度的物体,Alpha Blend等的在该队列渲染。
    • Overlay (4000) 最后被渲染的物体的队列,一般是覆盖效果,比如镜头光晕,屏幕贴片之类的

    Queue也可以参与运算得出一些特殊的位置:
    “Queue”=“Transparent - 50”
    Transparent对应的是3000,-50,渲染的位置就在2950。这种情况下,渲染的顺序在Transparent之后,而在Overlay之前

    Pass

    在一个SubShader可以有一个和多个pass,这多个pass会按照顺序逐个进行渲染。称为多pass。

    比如:在处理光照和阴影时,灯光编写一个Pass,阴影编写一个Pass。

    当GPU执行时,先计算灯光Pass输出颜色,然后再计算阴影Pass再输出颜色。

    Pass的Tags

    Pass的tags有LightMode和RequireOptions

  • 相关阅读:
    通过matlab对比遗传算法优化前后染色体的变化情况
    Python统计学01——数据可视化
    高速电路设计笔记----第一章
    Leetcode 238. 除自身以外数组的乘积
    flink使用kryo支持自定义的序列化器
    【康耐视国产案例】AI视觉相机创新 加速商超物流数智化转型
    【多AZ】浅述云计算多az
    测试面试题集锦(四)| Linux 与 Python 编程篇(附答案)
    记录:Unity脚本的编写5.0
    快速了解Docker
  • 原文地址:https://blog.csdn.net/GameObject14715/article/details/125376947