Shader编写指南(五):ShaderLab 材质属性定义

在 ShaderLab 中,通过 Properties 块 定义的材质属性是连接着色器代码与编辑器交互的核心。这些属性允许美术人员在材质面板中直观调整参数,同时支持通过脚本动态控制。以下是材质属性的定义规则、类型详解及跨管线最佳实践:

一、材质属性的核心作用
  1. 编辑器交互

    • 在材质面板中显示为可编辑字段(如滑块、颜色选择器、纹理预览)。
    • 示例:通过 _MainTex 属性指定模型的基础纹理,通过 _TintColor 控制颜色叠加。
  2. 数据持久化

    • 属性值随材质资产保存,支持跨会话保留修改(如退出 Unity 后重新打开项目,参数值不变)。
  3. 代码控制

    • 通过 C# 脚本调用 Material.SetFloat/Material.GetTexture 等接口动态修改属性值。
    • 示例:实时调整粒子系统的发光强度 material.SetFloat("_GlowIntensity", intensity);
二、属性定义语法与类型

材质属性声明格式为:

hlsl

[属性标签] 属性名 ("面板显示名", 类型) = 默认值  
1. 基础类型与示例
类型声明示例HLSL 对应类型面板显示
Integer_IntProp ("整数", Integer) = 10int整数输入框
Float_FloatProp ("浮点", Float) = 0.5float浮点滑块(默认 0~1)
Range_RangeProp ("范围", Range(0, 5)) = 2.3float限定范围滑块
Color_ColorProp ("颜色", Color) = (1, 0.5, 0.5, 1)float4颜色选择器
Vector_VectorProp ("向量", Vector) = (1, 2, 3, 4)float4四维浮点输入框
2D 纹理_MainTex ("基础纹理", 2D) = "white" {}sampler2D纹理选择器(支持 Alpha)
Cube 纹理_CubeMap ("反射立方图", Cube) = "" {}samplerCUBE立方体贴图选择器
3D 纹理_VolumeTex ("体积纹理", 3D) = "" {}sampler3D三维纹理选择器

  • 默认值规则
    • 纹理类型默认值可指定为 "white"/"black" 等内置纹理,或留空使用灰色纹理。
    • 颜色类型默认值需包含 RGBA 四个分量(如 (R,G,B,A))。
2. 旧版类型(Legacy)
  • Int:基于浮点的伪整数类型(如 _LegacyInt ("旧版整数", Int) = 1),不推荐新代码使用,优先选择 Integer
  • Rect:二维矩形参数(已被 Vector 替代,Vector 的 XY 表示左上角,ZW 表示宽高)。
3. 特殊类型
  • Texture2DArray:二维纹理数组,用于多切片纹理(如地形多层材质)。
  • CubemapArray:立方体贴图数组,支持多视角反射纹理。
三、属性标签(Attributes)

通过标签修饰属性,控制编辑器行为或渲染逻辑:

标签作用示例
[Gamma]声明属性值为 sRGB 颜色空间(如纹理颜色需符合伽马校正)[Gamma]_Color ("伽马颜色", Color) = (1,1,1,1)
[HDR]启用高动态范围(如自发光颜色支持超亮值)[HDR]_Emission ("HDR 发光", Color) = (5,5,5,1)
[Normal]标记为法线贴图(编辑器验证纹理格式并显示警告)[Normal]_NormalMap ("法线", 2D) = "bump" {}
[NoScaleOffset]隐藏纹理平铺 / 偏移字段(适用于不需要 UV 动画的纹理)[NoScaleOffset]_DetailTex ("细节纹理", 2D) = "" {}
[MainTexture]指定主纹理(替代默认 _MainTex 名称,如纹理名为 _TextureMap 时)[MainTexture]_TextureMap ("主纹理", 2D) = "" {}
[HideInInspector]从材质面板隐藏属性(仅通过脚本控制)[HideInInspector]_InternalParam ("内部参数", Float) = 0
  • 最佳实践
    • 法线贴图始终添加 [Normal] 标签,确保编辑器提示正确纹理格式。
    • 移动端避免使用 [HDR] 以减少显存占用,除非必要(如动态光照探针)。
四、跨渲染管线兼容性
  1. SRP Batcher 支持

    • 在 HLSL 中,需将材质属性变量放入同一 CBUFFER 块,确保 SRP Batcher 合并材质实例。

    hlsl

    CBUFFER_START(UnityPerMaterial)  
        float4 _MainTex_ST;  
        fixed4 _TintColor;  
    CBUFFER_END  
    
  2. URP/HDRP 特殊要求

    • URP 中,主纹理需通过 _MainTex 或 [MainTexture] 声明,否则可能无法正确应用光照。
    • HDRP 支持更多高级属性(如体积雾参数),需引用对应 HLSL 库(如 Packages/com.unity.render-pipelines.high-definition/ShaderLibrary/)。
五、属性与代码的交互
1. 在 ShaderLab 指令中使用属性

通过 [属性名] 语法在渲染状态指令中引用属性值:

hlsl

Pass {  
    // 使用 _OffsetScale 属性控制深度偏移  
    Offset 0, [_OffsetScale]  
    CGPROGRAM  
    // ... HLSL 代码 ...  
    ENDCG  
}  
2. 在 HLSL 中引用属性

属性名需与 HLSL 变量名一致,类型匹配:

hlsl

Properties {  
    _MainTex ("Texture", 2D) = "white" {}  
    _TintFactor ("混合因子", Range(0, 1)) = 0.5  
}  
CGPROGRAM  
sampler2D _MainTex;        // 对应 2D 纹理属性  
float _TintFactor;         // 对应 Range/Float 属性  
fixed4 frag(v2f i) : SV_TARGET {  
    fixed4 tex = tex2D(_MainTex, i.uv);  
    return tex * _TintFactor; // 混合因子控制颜色强度  
}  
ENDCG  
3. 通过 C# 脚本控制属性

csharp

public class MaterialController : MonoBehaviour {  
    public Material targetMaterial;  
    void Update() {  
        // 设置浮点属性  
        targetMaterial.SetFloat("_GlowIntensity", Mathf.Sin(Time.time) * 2);  
        // 设置纹理属性  
        targetMaterial.SetTexture("_MainTex", newTexture);  
    }  
}  
六、高级技巧与优化
  1. 属性分组与折叠
    通过注释在 Properties 块中添加空行或 // [Group Name] 注释,实现面板分组:

    hlsl

    Properties {  
        // [基础属性]  
        _MainTex ("基础纹理", 2D) = "" {}  
        _Color ("染色", Color) = (1,1,1,1)  
        // [光照属性]  
        _Metallic ("金属度", Range(0,1)) = 0  
        _Roughness ("粗糙度", Range(0,1)) = 0.5  
    }  
    
  2. 减少材质变体(Shader Variant)

    • 使用 ShaderVariantCollection 管理属性组合,避免为每个参数值生成独立着色器变体。
    • 示例:通过 #pragma multi_compile _ _USE_SPECULAR 动态切换是否启用高光属性。
  3. 移动端优化

    • 避免使用高精度类型(如 double),优先用 fixed(单精度)或 half(半精度)。
    • 合并属性:将颜色与向量属性的 RGBA 分量拆分到同一 float4 变量中,减少寄存器占用。
七、完整示例:带属性的 PBR 材质

hlsl

Shader "URP/PBR_Material" {  
    Properties {  
        [MainTexture]_MainTex ("基础纹理", 2D) = "white" {}  
        [Normal]_NormalMap ("法线贴图", 2D) = "bump" {}  
        _Metallic ("金属度", Range(0,1)) = 0  
        _Roughness ("粗糙度", Range(0,1)) = 0.5  
        [HDR]_EmissionColor ("自发光", Color) = (0,0,0,1)  
    }  
    SubShader {  
        Tags { "RenderType"="Opaque" "LightMode"="UniversalForward" }  
        LOD 300  
        Pass {  
            HLSLPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"  
            CBUFFER_START(UnityPerMaterial)  
                sampler2D _MainTex;  
                float4 _MainTex_ST;  
                sampler2D _NormalMap;  
                float _Metallic;  
                float _Roughness;  
                float4 _EmissionColor;  
            CBUFFER_END  
            // ... 顶点/片元着色器代码(使用上述属性计算 PBR 光照)...  
            ENDHLSL  
        }  
    }  
    Fallback "Universal Render Pipeline/Lit"  
}  

八、注意事项
  1. 命名冲突

    • 避免使用 Unity 保留名(如 _Time_LightColor0),这些名称对应内置变量。
    • 保留名列表:_TransparencyLM(光照贴图透明通道)、_Emission(自发光)等。
  2. 性能影响

    • 每个属性在 GPU 端对应寄存器资源,过多属性可能导致着色器编译时间增加或寄存器溢出。
    • 移动端建议单个材质的属性数量不超过 16 个。
  3. 调试技巧

    • 在材质面板中按住 Ctrl 点击属性名,快速定位 HLSL 代码中的变量声明。
    • 使用 [HideInInspector] 隐藏调试用临时属性,避免污染面板。

总结

材质属性是 ShaderLab 的核心交互机制,通过合理定义属性类型与标签,可在编辑器便利性、代码灵活性和性能之间取得平衡。在实际项目中,需根据渲染管线(内置 / URP/HDRP)和平台特性(PC / 移动端)优化属性结构,同时结合脚本与着色器代码实现动态效果。掌握属性定义规则是进阶着色器开发的基础,尤其在多人协作或美术主导的项目中,清晰的属性设计能显著提升工作效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小李也疯狂

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

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

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

打赏作者

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

抵扣说明:

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

余额充值