完整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 要这样设计?
原因很现实:
- 保证 美术工作流统一
- 兼容 旧 Shader / 老项目
- Inspector 不需要理解 Shader 代码
- 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 | 混合模式 |
注意
_Cutoff是 AlphaTest 的硬协议名- 用错名字 = 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