URP Shader编程规则之Properties

完整Properties示例

c 复制代码
Shader "Custom/URPExample"
{
    Properties
    {
        // ========== 1. 基础属性 ==========
        [Header(Base Properties)]
        [MainTexture] _BaseMap("Base Texture", 2D) = "white" {}
        [MainColor] _BaseColor("Base Color", Color) = (1,1,1,1)
        
        // ========== 2. 纹理属性 ==========
        [Header(Texture Maps)]
        [NoScaleOffset] _NormalMap("Normal Map", 2D) = "bump" {}
        _NormalScale("Normal Scale", Float) = 1.0
        
        [HDR] _EmissionMap("Emission Map", 2D) = "black" {}
        [HDR] _EmissionColor("Emission Color", Color) = (0,0,0,1)
        
        _MetallicGlossMap("Metallic (R) Smoothness (A)", 2D) = "white" {}
        _OcclusionMap("Occlusion Map", 2D) = "white" {}
        
        // ========== 3. 数值属性 ==========
        [Header(Surface Properties)]
        [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
        _Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5
        _OcclusionStrength("Occlusion Strength", Range(0.0, 1.0)) = 1.0
        
        // ========== 4. 开关/枚举属性 ==========
        [Header(Options)]
        [Toggle] _UseEmission("Use Emission", Float) = 0
        [Toggle(_PARALLAXMAP)] _UseParallax("Use Parallax", Float) = 0
        [ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
        [ToggleOff] _EnvironmentReflections("Environment Reflections", Float) = 1.0
        
        [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Src Blend", Float) = 1
        [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Dst Blend", Float) = 0
        [Enum(Off,0,On,1)] _ZWrite("Z Write", Float) = 1
        [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("Z Test", Float) = 4
        
        // ========== 5. 特殊属性 ==========
        [Header(Advanced)]
        [KeywordEnum(None, Add, Multiply)] _Overlay("Overlay Mode", Float) = 0
        [Space(20)]
        [Vector] _DetailUV("Detail UV Tiling", Vector) = (1,1,0,0)
        [IntRange] _StencilRef("Stencil Reference", Range(0, 255)) = 0
        
        // ========== 6. 自定义编辑器属性 ==========
        [HideInInspector] _QueueOffset("Queue offset", Float) = 0.0
    }
}

URP Shader和内置渲染管线Shader不同的是一个采用CG一个采用HSLS语言。其中关于Properties有一些默认的属性名

Unity 在 ShaderLab + 材质系统里写死的一套【命名约定驱动机制】。

Unity Shader"黑魔法级别的约定系统"**。

你看到的并不是"巧合关联",而是 Unity 在 ShaderLab + 材质系统里写死的一套【命名约定驱动机制】

我按底层逻辑 → 具体到你这四个变量,一步一步给你讲清楚。


一、先给结论(非常重要)

这几个变量之间"能自动关联",不是因为 Shader 写了什么逻辑,
而是因为 Unity 引擎在 C++ 层对"特定名字"做了硬编码识别。

也就是说:

  • ❌ 不是 HLSL 特性
  • ❌ 不是 Properties 的能力
  • ❌ 不是 URP 的机制
  • ✅ 是 Unity 材质系统的"命名协议(Convention)"

二、_BumpMap 和 _BumpScale 的关系是怎么来的?

hlsl 复制代码
// 法线贴图
_BumpMap ("Normal Map", 2D) = "bump" {}
_BumpScale ("Normal Scale", Float) = 1.0

1️⃣ 核心点:Unity"认识" _BumpMap

在 Unity 引擎内部(C++):

_BumpMap"标准法线贴图槽位名"

一旦你在 Properties 里声明:

hlsl 复制代码
_BumpMap ("Normal Map", 2D)

Unity 会自动:

  • 把这个贴图当作 法线贴图

  • 在材质 Inspector 中:

    • 显示为 Normal Map
    • 启用 Normal Map 的导入校验
    • 自动提示 "Fix Now"

📌 这一切都不是 Shader 代码做的


2️⃣ 那 _BumpScale 为什么能"跟着它"?

这是第二条硬编码规则:

当 Unity 看到 _BumpMap
并且同时存在 _BumpScale
它就认为:这是"法线强度"

所以在 Inspector 里你会看到:

  • 法线贴图槽
  • 一个 Normal Scale 滑条

📌 注意重点:

Shader 并不知道 _BumpScale 是干嘛的

Shader 只知道:这是一个 float

是否"关联",完全是 Inspector UI 逻辑


3️⃣ Shader 里发生了什么?

Shader 里你必须自己用它:

hlsl 复制代码
float4 normalTS = UnpackNormalScale(
    SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, uv),
    _BumpScale
);

👉 不写这行,_BumpScale 一点用都没有


三、_MainTex 和 _MainTex_ST 的关系(这是更典型的)

hlsl 复制代码
_MainTex ("Texture", 2D) = "white" {}
_MainTex_ST ("Texture Tiling/Offset", Vector) = (1,1,0,0)

这个关系更底层、更硬


1️⃣ _MainTex 是"主纹理"的保留名

Unity 内部规定:

_MainTex = 主纹理(Base Map / Albedo)

所以它会:

  • 在材质 Inspector 中作为主贴图
  • 被很多系统默认引用(UI、粒子、SRP)

2️⃣ _MainTex_ST 是 Unity 自动生成 / 识别的变量

ST 是什么?

text 复制代码
ST = Scale + Translation

即:

hlsl 复制代码
xy → Tiling
zw → Offset

3️⃣ 为什么"必须显式声明"?

因为 URP + SRP Batcher 下,Unity 不再偷偷帮你声明

Built-in 管线 时代:

hlsl 复制代码
_MainTex_ST

👉 Unity 会在背后自动塞进来

但在 URP / SRP

你不写,Shader 里就没有

所以你必须:

hlsl 复制代码
CBUFFER_START(UnityPerMaterial)
    float4 _MainTex_ST;
CBUFFER_END

4️⃣ Unity 是怎么把它们"绑定在一起"的?

这条规则是:

如果存在 _XXX_ST,并且存在 _XXX 的 Texture 属性,
Unity 会自动:

  • 在 Inspector 里显示 Tiling / Offset
  • 在修改 UI 时,写入 _XXX_ST

📌 依然是:C++ 层硬编码规则


四、这不是"魔法",是"协议"

你现在要形成一个非常重要的认知:

Unity Shader 中很多"自动行为",
不是语言能力,而是命名协议。


五、Unity 中最重要的"隐式命名协议表"(送你)

名字 含义
_MainTex 主纹理
_MainTex_ST 主纹理 Tiling / Offset
_BaseMap URP 主纹理
_BaseMap_ST URP 主纹理 ST
_BumpMap 法线贴图
_BumpScale 法线强度
_MetallicGlossMap 金属度
_OcclusionMap AO
_EmissionMap 自发光
_EmissionColor 自发光颜色

📌 命名对 = 自动 UI + 自动流程

📌 命名错 = 一切手动


六、一个"反例",帮你彻底想通

如果你写:

hlsl 复制代码
_MyNormal ("Normal", 2D) = "bump" {}
_MyNormalScale ("Scale", Float) = 1

结果是:

  • ❌ 不会显示为 Normal Map
  • ❌ 不会自动 Fix
  • ❌ 不会自动绑定 Scale
  • Shader 里一切都要你自己管

👉 因为 Unity 不认识这些名字


七、为什么 Unity 要这样设计?

原因很现实:

  1. 保证 美术工作流统一
  2. 兼容 旧 Shader / 老项目
  3. Inspector 不需要理解 Shader 代码
  4. SRP / Built-in / UI 共用一套规则

这份表来自 URP 源码 + ShaderLibrary + 实际 Inspector 行为总结,你可以放心用。

说明

  • 版本背景:URP(Unity 2021+ / 团结 1.67 适用)
  • 这是 "命名即行为" 的协议
  • 不按这个命名 → Inspector / 管线不会帮你做任何事

一、【最重要】主贴图 / 基础颜色(Base Map)

名称 类型 作用
_BaseMap 2D URP 主贴图(等价于旧 _MainTex
_BaseMap_ST Vector Tiling (xy) + Offset (zw)
_BaseColor Color 主颜色 / Albedo Tint

说明

  • URP Lit / SimpleLit 只认 _BaseMap
  • _MainTex 在 URP 中 不是推荐命名

二、法线贴图(Normal Map)

名称 类型 作用
_BumpMap 2D 法线贴图
_BumpScale Float 法线强度

引擎行为

  • Inspector 显示为 Normal Map
  • 自动提示 Fix Normal Map
  • _BumpScale 自动显示为滑条

三、金属 / 光滑度(Metallic / Smoothness)

名称 类型 作用
_MetallicGlossMap 2D 金属度贴图
_Metallic Range/Float 金属度常量
_Smoothness Range/Float 光滑度
_GlossMapScale Float Smoothness 强度

说明

  • Metallic / Smoothness 通常共用一张图

  • Smoothness 默认来自:

    • A 通道(URP 约定)

四、遮蔽(Ambient Occlusion)

名称 类型 作用
_OcclusionMap 2D AO 贴图
_OcclusionStrength Range AO 强度

五、自发光(Emission)

名称 类型 作用
_EmissionMap 2D 自发光贴图
_EmissionColor Color 自发光颜色

引擎行为

  • 启用 Emission 后:

    • 自动写入 GI
    • 影响光照贴图

六、透明 / 裁剪(Alpha)

名称 类型 作用
_Cutoff Range Alpha Clip 阈值
_Surface Float 0=Opaque / 1=Transparent
_Blend Float 混合模式

注意

  • _CutoffAlphaTest 的硬协议名
  • 用错名字 = Clip 不生效

七、细节贴图(Detail)

名称 类型 作用
_DetailMap 2D 细节贴图
_DetailAlbedoScale Float 细节颜色强度
_DetailNormalMap 2D 细节法线
_DetailNormalScale Float 细节法线强度

八、阴影 / 接收控制(Shadow)

名称 类型 作用
_ReceiveShadows Float 是否接收阴影
_ShadowStrength Float 阴影强度

九、URP 内部 / 管线控制(高级)

⚠️ 这些一般不手写,但你必须认识

名称 作用
_TimeParameters 时间参数
_ProjectionParams 投影相关
_ScreenParams 屏幕尺寸
_ZBufferParams 深度反算

十、ST(Scale + Offset)命名规则(非常重要)

通用规则(你一定要记)

任何 Texture:
只要名字是 _XXX
对应的 Tiling/Offset 必须叫:_XXX_ST

例如:

hlsl 复制代码
_BaseMap     → _BaseMap_ST
_BumpMap     → _BumpMap_ST
_OcclusionMap → _OcclusionMap_ST

否则:

  • Inspector 不显示 Tiling/Offset
  • SRP Batcher 不识别
  • Shader 里采样错位

十一、哪些"看似对,但其实是坑"的命名?

❌ 不推荐:

hlsl 复制代码
_MainTex        // URP 不推荐,保留字
_MainColor
_NormalMap
_NormalScale

👉 Inspector 不帮你做任何事


十二、SRP Batcher / Instancing 特别注意

SRP Batcher

hlsl 复制代码
CBUFFER_START(UnityPerMaterial)
    float4 _BaseColor;
    float4 _BaseMap_ST;
CBUFFER_END
  • 顺序不能乱
  • 不能跨 Shader 不一致

GPU Instancing / GRD

hlsl 复制代码
UNITY_DEFINE_INSTANCED_PROP(float4, _BaseColor)

⚠️ 不要和 CBUFFER 同名混用


复制代码
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"

这个会自动引入一些已经默认定义好的名字变量属性,如,BaseMap等,如果继续冲重复加入到CBUFFER_START(UnityPerMaterial),则会提示重复。

所有的属性都需要写进去CBUFFER_START(UnityPerMaterial),除了Texture2D / Sampler,因为他们不走CBUFFER

相关推荐
timathy338 小时前
Unity Addressable 实现Build时自定义剔除资源组
unity·游戏引擎
一种时光1 天前
Unity 获取当前播放的动画,判断是否是某个动画
unity·游戏引擎
不绝1911 天前
Unity入门 :场景叠加/预制体资源包/脚本资源/生命周期函数/Inspector页面
unity·游戏引擎
在路上看风景1 天前
20. 资源和脚本的绑定关系
unity
yj爆裂鼓手1 天前
unity对象池
unity·c#
在路上看风景1 天前
3.7 SRP Batcher
unity
快乐觉主吖1 天前
Unity方便修改产品名和包名的小工具
unity·游戏引擎
JIes__2 天前
Unity(二)——MonoBehavior中的重要内容
unity·游戏引擎
4Forsee2 天前
【增强现实】快速上手 Vuforia Unity Android AR 应用开发
android·unity·ar
两水先木示2 天前
【Unity】对指定物体进行描边——模板测试法
unity·游戏引擎·shader·外描边