Shader编写指南(四):Shader对象定义

在 ShaderLab 中,** 着色器对象(Shader Object)** 通过 Shader 块声明,用于组织着色器程序、材质属性和渲染逻辑。以下是其核心结构、语法规则及跨渲染管线的应用说明:

一、着色器对象的嵌套结构

着色器对象采用层级化结构,包含以下核心组件:

hlsl

Shader "着色器路径/名称" {  
    // 1. 材质属性(可选)  
    Properties { ... }  
    
    // 2. 子着色器(至少一个)  
    SubShader { ... }  
    
    // 3. 自定义编辑器(可选)  
    CustomEditor "自定义编辑器类名"  
    
    // 4. 回退着色器(可选)  
    Fallback "回退着色器路径"  
}  

  • 层级关系
    Shader → SubShader → Pass(每个 SubShader 包含一个或多个 Pass)。
  • 渲染流程
    Unity 按顺序尝试每个 SubShader,直到找到硬件支持的版本,每个 SubShader 内的 Pass 依次执行渲染。
二、关键组件解析
1. 着色器名称与路径(Shader Name)
  • 格式Shader "路径/名称"(如 Shader "URP/MyLitShader")。
  • 作用
    • 决定材质在 Unity 编辑器中的分类路径(如 "Custom/Effects" 会显示在材质创建菜单的对应目录下)。
    • 旧版着色器(Legacy Shaders)的功能由名称路径决定(如 "Transparent/Cutout" 启用 Alpha 裁剪)。
2. 属性块(Properties Block)

定义可在材质面板编辑的参数,语法为 属性名 ("显示名称", 类型) = 默认值

hlsl

Properties {  
    _MainTex ("基础纹理", 2D) = "white" {}       // 二维纹理  
    _TintColor ("染色", Color) = (1,1,1,1)        // 颜色  
    _Glossiness ("光泽度", Range(0,1)) = 0.5      // 浮点范围  
    _EmissionTex ("自发光纹理", 2D) = "black" {}  // 带 Alpha 的纹理  
}  
  • 参数类型:支持 Color2DRangeVector 等,参数值通过同名变量传递给 HLSL 代码。
3. 子着色器块(SubShader Block)

每个 SubShader 定义一组渲染指令,Unity 会根据硬件能力选择第一个支持的 SubShader。

hlsl

SubShader {  
    Tags { "RenderType"="Opaque" "Queue"="Geometry" }  // 渲染标签  
    LOD 200                                             // 细节层级  
    Pass { ... }                                        // 至少一个 Pass  
    // 可选:多个 Pass 或 UsePass 引用其他着色器的 Pass  
}  

  • 核心标签(Tags)
    • RenderType:定义渲染类型(如 "Opaque"、"Transparent"),影响渲染队列和后期处理。
    • LightMode:指定光照模式(如 "ForwardBase" 用于正向渲染主光源)。
  • LOD(Level of Detail):当材质 LOD 等级低于当前值时,跳过该 SubShader(如 LOD 200 表示支持法线贴图)。
4. 通道块(Pass Block)

每个 Pass 代表一次完整的渲染流程,包含渲染状态设置和 HLSL 代码。

hlsl

Pass {  
    // 渲染状态指令  
    Blend SrcAlpha OneMinusSrcAlpha   // 透明混合  
    ZTest LEqual                     // 深度测试  
    Cull Off                         // 关闭背面剔除(显示双面)  
    // 嵌入 HLSL 代码  
    CGPROGRAM  
    #pragma vertex vert  
    #pragma fragment frag  
    #include "UnityCG.cginc"  
    // 顶点和片元着色器函数  
    ENDCG  
}  

  • 渲染状态:控制混合模式、深度缓冲、剔除等 GPU 状态,影响最终渲染效果。
  • HLSL 代码:通过 CGPROGRAM 块嵌入,实现顶点变换、像素着色等核心逻辑。
5. 回退着色器(Fallback)

当所有 SubShader 均不被支持时,使用指定的回退着色器。

hlsl

Fallback "Legacy Shaders/VertexLit"  // 回退到内置顶点光照着色器  

  • 最佳实践:回退至简单着色器(如 Diffuse 或 VertexLit),确保低端设备兼容。
6. 自定义编辑器(CustomEditor)

指定用于材质面板的自定义编辑器脚本,格式为 CustomEditor "脚本类名"

hlsl

CustomEditor "MyShaderEditor"  // 引用 Assets 目录下的 MyShaderEditor.cs  

  • 用途:自定义材质参数的显示方式(如添加按钮、滑动条或条件显示参数)。
三、跨渲染管线的兼容性

ShaderLab 的 Shader 块兼容所有渲染管线,但需注意以下差异:

功能内置管线URPHDRP
材质属性
SubShader 标签传统标签(如 "LightMode")URP 专用标签(如 "LightMode"="UniversalForward")HDRP 专用标签(如 "LightMode"="HDRenderPipeline")
HLSL 头文件引用UnityCG.cgincPackages/.../Core.hlslPackages/.../ShaderLibrary/
自定义渲染流程直接编写 Pass使用 URP 专用函数使用 HDRP 专用函数

示例:URP 着色器的 SubShader 标签

hlsl

SubShader {  
    Tags {  
        "RenderType"="Opaque"  
        "LightMode"="UniversalForward"  // URP 正向渲染标签  
        "UniversalPipeline"="UniversalPipeline"  
    }  
    // ...  
}  
四、旧版着色器名称规则(Legacy Shader Names)

在 Unity 5.0 前,部分着色器的功能由名称路径决定,修改名称可能导致功能异常:

  • 示例
    • 名称包含 "Transparent/Cutout" 的着色器自动启用 Alpha 裁剪。
    • 名称包含 "Reflective" 的着色器支持立方体贴图反射。
  • 注意事项
    • 旧项目中的 legacy 着色器需保持名称不变。
    • 新项目应避免依赖此机制,改用现代渲染管线的标签和代码逻辑。
五、完整示例:基础漫反射着色器

hlsl

Shader "Custom/BasicDiffuse" {  
    // 1. 属性定义  
    Properties {  
        _MainTex ("Base Texture", 2D) = "white" {}  
        _Color ("Tint Color", Color) = (1,1,1,1)  
    }  
    // 2. 子着色器定义  
    SubShader {  
        Tags { "RenderType"="Opaque" "Queue"="Geometry" }  
        LOD 100  // 最低细节层级(仅漫反射)  
        Pass {  
            Tags { "LightMode"="ForwardBase" }  // 内置管线正向渲染主光源  
            // 渲染状态:开启深度测试  
            ZTest LEqual  
            // HLSL 代码块  
            CGPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
            #include "UnityCG.cginc"  
            // 引用属性变量  
            sampler2D _MainTex;  
            float4 _MainTex_ST;  
            fixed4 _Color;  
            // 顶点输入结构  
            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 = UnityObjectToClipPos(v.vertex);  
                o.uv = TRANSFORM_TEX(v.uv, _MainTex); // 应用 UV 缩放/偏移  
                return o;  
            }  
            // 片元着色器:纹理采样与颜色混合  
            fixed4 frag (v2f i) : SV_TARGET {  
                fixed4 tex = tex2D(_MainTex, i.uv);  
                return tex * _Color;  
            }  
            ENDCG  
        }  
    }  
    // 3. 回退至内置漫反射着色器  
    Fallback "Diffuse"  
}  
六、最佳实践建议
  1. 渲染管线适配
    • 新项目优先为 URP/HDRP 编写着色器,使用对应的标签和 HLSL 库。
    • 通过 #if UNITY_URP 等条件编译区分不同管线的代码。
  2. 性能优化
    • 减少 SubShader 数量,通过 LOD 分级而非重复编写 SubShader。
    • 合并 Pass,使用 MultiCompile 生成变体而非多个独立 Pass。
  3. 可维护性
    • 为属性和变量添加注释,说明其功能(如 // 控制皮肤光泽度)。
    • 将通用函数封装到 .cginc 头文件中,避免重复代码。

总结

ShaderLab 的 Shader 块是定义 Unity 着色器的基础,通过合理组织属性、SubShader 和 Pass,可实现从简单漫反射到复杂 PBR 材质的各种效果。理解其嵌套结构与渲染管线兼容性,能帮助开发者高效编写跨平台、高性能的着色器,同时为后续使用 Shader Graph 或自定义渲染管线奠定基础。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小李也疯狂

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

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

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

打赏作者

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

抵扣说明:

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

余额充值