Shader编写指南(十七):ShaderLab命令

在 ShaderLab 中,命令(Commands)用于控制 GPU 渲染状态、定义特殊用途的 Pass 或实现传统固定功能着色器逻辑。这些命令是构建着色器渲染流程的核心,可分为渲染状态设置Pass 定义传统固定功能三类。以下是核心命令的详解及实践示例:

一、渲染状态设置命令

此类命令用于配置 GPU 的渲染状态(如混合模式、深度测试、模板缓冲等),可作用于单个 Pass 或整个 SubShader。

1. 混合(Blend)
  • 作用:启用 alpha 混合,控制源颜色与目标颜色的混合方式。
  • 语法

    hlsl

    Blend [源混合因子] [目标混合因子]  
    BlendOp [混合操作]  // 可选,设置混合后的颜色操作(如Add、Subtract)  
    
  • 示例

    hlsl

    Blend SrcAlpha OneMinusSrcAlpha  // 标准透明混合(如玻璃、UI)  
    Blend One One                   // 相加混合(如粒子发光)  
    BlendOp Min                     // 取最小值混合  
    
2. 深度测试与写入(ZTest / ZWrite)
  • ZTest:设置深度测试条件(如当前片元深度是否通过测试)。

    hlsl

    ZTest LessEqual  // 仅当片元深度≤缓冲区深度时通过(默认值)  
    ZTest Always     // 始终通过(用于UI覆盖)  
    
  • ZWrite:控制是否写入深度缓冲。

    hlsl

    ZWrite On  // 启用深度写入(不透明物体默认)  
    ZWrite Off // 禁用深度写入(透明物体常用)  
    
3. 模板测试(Stencil)
  • 作用:通过模板缓冲实现复杂遮挡或特效(如贴花、轮廓渲染)。
  • 语法

    hlsl

    Stencil {  
        Ref [参考值]       // 用于比较的参考值  
        Comp [比较函数]    // 如Equal、NotEqual  
        Pass [通过时操作]  // 如Replace、Keep  
        Fail [失败时操作]  
    }  
    
  • 示例:仅渲染模板值为 1 的区域:

    hlsl

    Stencil {  
        Ref 1  
        Comp Equal  
        Pass Keep  
    }  
    
4. 剔除模式(Cull)
  • 作用:控制渲染正面 / 背面三角形,优化性能。
  • 取值

    hlsl

    Cull Back    // 剔除背面(默认,适用于闭合网格)  
    Cull Front   // 剔除正面  
    Cull Off     // 渲染双面(如薄片物体、透明布料)  
    
5. 深度偏移(Offset)
  • 作用:解决深度缓冲冲突(Z-Fighting),通过偏移值调整片元深度。
  • 语法

    hlsl

    Offset [深度系数] [深度 bias]  
    
  • 示例

    hlsl

    Offset 1, 1  // 增加深度值,确保物体在其他物体前方渲染  
    
二、Pass 定义命令

用于创建特殊用途的 Pass,简化常见渲染流程。

1. UsePass:引用其他着色器的 Pass
  • 作用:复用其他着色器中的 Pass 代码,避免重复编写(如阴影投射 Pass)。
  • 语法

    hlsl

    UsePass "ShaderName/PassName"  
    
  • 注意
    • 名称需为全大写(如原 Pass 名为 "ShadowCaster",引用时写作 "SHADOWCASTER")。
    • 示例:引用内置着色器的阴影投射 Pass:

      hlsl

      UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"  
      
2. GrabPass:抓取屏幕内容
  • 作用:将当前屏幕图像抓取到纹理中,用于反射、折射等效果(内置管线常用)。
  • 语法

    hlsl

    GrabPass [纹理名称]  // 可选,指定纹理名称,默认名为"_GrabTexture"  
    
  • 示例

    hlsl

    GrabPass "CustomGrabTex"  
    // 在片元着色器中使用该纹理:  
    float4 frag(v2f i) : SV_TARGET {  
        float4 screen = tex2Dlod(_CustomGrabTex, float4(i.uv, 0, 0));  
        return screen * _TintColor;  
    }  
    
三、传统固定功能命令(Legacy)

适用于无需编写 HLSL 的简单着色器,仅支持内置管线,不推荐用于现代项目。

1. 颜色与纹理设置
  • Color:设置固定颜色。

    hlsl

    Color (1, 0.5, 0, 1)  // 橙色  
    
  • SetTexture:设置纹理采样状态。

    hlsl

    SetTexture [_MainTex] {  
        Combine texture * primary  // 纹理与固定颜色相乘  
    }  
    
2. 光照模型
  • Lighting:启用 / 禁用光照。

    hlsl

    Lighting On  // 启用光照(默认)  
    Lighting Off // 禁用光照(如自发光材质)  
    
  • Material:定义材质属性(漫反射、高光等)。

    hlsl

    Material {  
        Diffuse (1, 1, 1, 1)  // 漫反射颜色  
        Shininess 0.5        // 光泽度  
        Specular (1, 1, 1, 1) // 高光颜色  
    }  
    
四、命令作用域与优先级
  1. SubShader 级 vs Pass 级

    • SubShader 级命令:作用于该 SubShader 的所有 Pass(如Cull Back)。
    • Pass 级命令:仅作用于当前 Pass,覆盖 SubShader 级设置(如 Pass 中Cull Off会覆盖 SubShader 的Cull Back)。
  2. 执行顺序

    • 渲染状态命令需在 HLSL 代码块前声明(如Blend需在CGPROGRAM之前)。

    hlsl

    Pass {  
        Blend SrcAlpha OneMinusSrcAlpha  
        CGPROGRAM  
        // 着色器代码  
        ENDCG  
    }  
    
五、跨渲染管线注意事项
  1. URP/HDRP 限制

    • 传统固定功能命令(如ColorSetTexture)在 URP/HDRP 中无效,需使用 HLSL 实现。
    • GrabPass在 URP/HDRP 中性能较低,建议使用ScriptableRenderContext或 RenderTexture 替代。
  2. SRP 兼容性

    • 自定义 SRP 中,部分命令(如ZTest)需配合管线的渲染设置使用,可能需通过代码动态配置。
六、完整示例:透明物体渲染

hlsl

Shader "Example/TransparentShader" {  
    Properties {  
        _MainTex ("基础纹理", 2D) = "white" {}  
        _TintColor ("颜色", Color) = (1, 1, 1, 1)  
    }  
    SubShader {  
        Tags { "RenderType"="Transparent" "Queue"="Transparent" }  
        // SubShader级设置:关闭深度写入  
        ZWrite Off  
        Pass {  
            Tags { "LightMode"="UniversalForward" } // URP正向渲染  
            // Pass级设置:启用混合  
            Blend SrcAlpha OneMinusSrcAlpha  
            HLSLPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"  
            sampler2D _MainTex;  
            float4 _MainTex_ST;  
            float4 _TintColor;  
            struct appdata {  
                float4 vertex : POSITION;  
                float2 uv : TEXCOORD0;  
            };  
            struct v2f {  
                float2 uv : TEXCOORD0;  
                float4 pos : SV_POSITION;  
            };  
            v2f vert (appdata v) {  
                v2f o;  
                o.pos = TransformObjectToHClip(v.vertex);  
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);  
                return o;  
            }  
            float4 frag (v2f i) : SV_TARGET {  
                float4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);  
                return tex * _TintColor;  
            }  
            ENDHLSL  
        }  
    }  
}  
七、性能优化建议
  1. 减少状态切换

    • 相邻 Pass 尽量复用相同的渲染状态(如相同的BlendZTest),减少 GPU 状态切换开销。
  2. 避免滥用 GrabPass

    • 屏幕抓取操作性能较高,URP/HDRP 中优先使用渲染纹理或管线内置功能(如 URP 的屏幕空间反射)。
  3. 现代管线优先使用 HLSL

    • 对复杂效果(如自定义光照模型),使用 HLSL 编程而非传统固定功能命令,以获得更好的性能和灵活性。

总结

ShaderLab 命令是控制渲染流程的底层工具,通过合理组合渲染状态命令和 Pass 定义命令,可实现从简单透明效果到复杂阴影系统的各种渲染逻辑。在实践中,需根据目标渲染管线选择合适的命令集,优先使用 HLSL 实现现代效果,并利用状态复用和管线特性优化性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李也疯狂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值