一、ShaderLab 整体框架
hlsl
Shader "Shader路径/Shader名称"
{
// 1. 属性定义块(可选)
Properties { ... }
// 2. 自定义编辑器指令(可选)
CustomEditor "编辑器类名"
// 3. Fallback 回退(可选)
Fallback "回退Shader"
// 或 Fallback Off
// 4. 子着色器(必需,至少一个)
SubShader
{
// 可以有多个SubShader
}
// 可以有多个SubShader用于不同平台
SubShader
{
// 针对低端设备的简化版本
}
}
二、Properties 属性块详解
2.1 属性基本语法
hlsl
Properties
{
// 格式:属性名 ("显示名称", 类型) = 默认值
// 数值类型
_IntValue ("整型", Int) = 1
_FloatValue ("浮点数", Float) = 1.5
_RangeValue ("范围值", Range(0.0, 1.0)) = 0.5
// 颜色和向量
_Color ("颜色", Color) = (1, 1, 1, 1)
_Vector ("四维向量", Vector) = (0, 0, 0, 0)
// 纹理
_MainTex ("主纹理", 2D) = "white" {}
_NormalMap ("法线贴图", 2D) = "bump" {} // bump是特殊默认值
_CubeMap ("立方体贴图", Cube) = "" {}
_3DTex ("3D纹理", 3D) = "black" {}
// 特殊属性
[Toggle] _UseEffect ("启用特效", Float) = 0
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("混合源", Float) = 1
[Header(分组标题)]
[Space(20)] // 间距
}
2.2 默认纹理值
hlsl
_MainTex ("Texture", 2D) = "white" {} // 白色
_CubeTex ("Cubemap", Cube) = "" {} // 空
_Normal ("Normal", 2D) = "bump" {} // 法线凹凸
_3DTex ("3D Texture", 3D) = "black" {} // 黑色
_DecalTex ("Decal", 2D) = "red" {} // 红色
_DetailTex ("Detail", 2D) = "gray" {} // 灰色
2.3 属性修饰器
hlsl
Properties
{
// HDR颜色
[HDR] _HDRColor ("HDR颜色", Color) = (1,1,1,1)
// 在Gamma和Linear空间之间切换
[Gamma] _GammaValue ("Gamma值", Float) = 1.0
// 无符号整型
[IntRange] _IntRange ("整型范围", Range(0, 255)) = 128
// 向量分量
[Vector2] _Vec2 ("二维向量", Vector) = (0,0,0,0)
[Vector3] _Vec3 ("三维向量", Vector) = (0,0,0,0)
// 关键字切换
[KeywordEnum(Off, On, Blur)] _EffectMode ("特效模式", Float) = 0
// 功率值
[PowerSlider(3.0)] _PowerValue ("功率值", Range(0.01, 1)) = 0.5
// 分组
[Header(光照设置)]
[Space(10)]
_Glossiness ("光泽度", Range(0,1)) = 0.5
_Metallic ("金属度", Range(0,1)) = 0.0
}
三、SubShader 子着色器详解
3.1 SubShader 基本结构
hlsl
SubShader
{
// 1. 标签(控制渲染队列、类型等)
Tags
{
"Queue" = "Geometry"
"RenderType" = "Opaque"
"DisableBatching" = "True"
}
// 2. 渲染状态(全局)
Cull Back
ZWrite On
ZTest LEqual
Blend SrcAlpha OneMinusSrcAlpha
// 3. LOD值
LOD 200
// 4. 可共享的代码块(可选)
CGINCLUDE
// 被所有Pass共享的代码
#include "UnityCG.cginc"
ENDCG
// 5. Pass块(必需,至少一个)
Pass { ... }
// 可以有多个Pass
Pass { ... }
}
3.2 SubShader 标签详解
hlsl
Tags
{
// 渲染队列(重要!控制渲染顺序)
// 常用值(数字越小越先渲染):
// "Background" = 1000 // 背景
// "Geometry" = 2000 // 不透明物体(默认)
// "AlphaTest" = 2450 // Alpha测试
// "Transparent" = 3000 // 半透明
// "Overlay" = 4000 // 覆盖层
"Queue" = "Transparent"
// 渲染类型(用于着色器替换和相机深度纹理)
// 常用值:
// "Opaque" // 不透明
// "Transparent" // 半透明
// "TransparentCutout" // 透明裁剪
// "Background" // 天空盒
// "Overlay" // UI、镜头光晕
"RenderType" = "Transparent"
// 禁用动态批处理
"DisableBatching" = "True" // "True"/"False"/"LODFading"
// 是否投射阴影
"ForceNoShadowCasting" = "True"
// 忽略投影器
"IgnoreProjector" = "True"
// 是否为预览着色器
"PreviewType" = "Plane" // "Plane"/"Sphere"/"Cube"/"Skybox"
// 是否可以被拾取
"CanUseSpriteAtlas" = "True"
// 性能相关
"PerformanceChecks" = "False"
}
3.3 渲染状态(Render States)
hlsl
// 剔除模式
Cull Back // 剔除背面(默认)
Cull Front // 剔除正面
Cull Off // 双面渲染
// 深度测试
ZTest Less // 深度小于当前值通过
ZTest Greater // 深度大于当前值通过
ZTest LEqual // 深度小于等于当前值通过(默认)
ZTest GEqual // 深度大于等于当前值通过
ZTest Equal // 深度等于当前值通过
ZTest NotEqual // 深度不等于当前值通过
ZTest Always // 总是通过
// 深度写入
ZWrite On // 写入深度缓冲(默认)
ZWrite Off // 不写入深度缓冲
// 混合模式
Blend SrcAlpha OneMinusSrcAlpha // 传统透明混合
Blend One One // 加法混合
Blend DstColor Zero // 乘法混合
Blend OneMinusDstColor One // 软加法
Blend SrcAlpha One // 预乘Alpha混合
// Alpha混合
AlphaToMask On // 开启Alpha-to-Coverage
// 模板测试
Stencil
{
Ref 1
Comp Always
Pass Replace
Fail Keep
ZFail Keep
}
// 颜色通道掩码
ColorMask RGB // 写入RGB通道
ColorMask R // 只写入红色通道
ColorMask 0 // 不写入任何颜色(深度和模板仍可写入)
// 裁剪(硬裁剪)
Clip
{
// 动态裁剪
Factor 0.5
Units 0
}
// 偏移(解决z-fighting)
Offset 0, -1
四、Pass 通道详解
4.1 Pass 基本结构
hlsl
Pass
{
// 1. Pass名称(可选,用于其他Pass引用)
Name "FORWARD"
// 2. Pass标签
Tags
{
"LightMode" = "ForwardBase"
"PassFlags" = "OnlyDirectional"
}
// 3. Pass特定的渲染状态
Blend One One
ZWrite Off
// 4. 着色器代码
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
// 包含文件
#include "UnityCG.cginc"
#include "AutoLight.cginc"
#include "UnityPBSLighting.cginc"
// 结构体定义
struct appdata { ... };
struct v2f { ... };
// 变量声明
sampler2D _MainTex;
// 顶点着色器
v2f vert(appdata v) { ... }
// 片元着色器
fixed4 frag(v2f i) : SV_Target { ... }
ENDCG
}
4.2 Pass 标签详解
hlsl
Tags
{
// 光照模式(重要!)
"LightMode" = "ForwardBase" // 前向渲染基础pass
"LightMode" = "ForwardAdd" // 前向渲染附加光源pass
"LightMode" = "Deferred" // 延迟渲染
"LightMode" = "ShadowCaster" // 阴影投射
"LightMode" = "MotionVectors" // 运动向量
"LightMode" = "PrepassBase" // 遗留延迟渲染
"LightMode" = "Always" // 总是渲染
// 渲染路径要求
"RequireOptions" = "SoftVegetation" // 需要软植被
// 其他Pass引用
"Name" = "MainPass" // Pass名称
}
4.3 常用Pass类型
hlsl
// 1. 基础Pass
Pass
{
Tags { "LightMode" = "ForwardBase" }
// 处理环境光和主方向光
}
// 2. 附加光源Pass
Pass
{
Tags { "LightMode" = "ForwardAdd" }
Blend One One // 加法混合
ZWrite Off // 不写入深度
}
// 3. 阴影投射Pass
Pass
{
Tags { "LightMode" = "ShadowCaster" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
float4 vert(appdata_base v) : SV_POSITION
{
return UnityObjectToClipPos(v.vertex);
}
fixed4 frag() : SV_Target
{
return 0;
}
ENDCG
}
// 4. 深度纹理Pass(用于屏幕空间效果)
Pass
{
Tags { "LightMode" = "DepthOnly" }
ColorMask 0 // 不写入颜色
ZWrite On // 只写入深度
}
五、CGPROGRAM 代码块详解
5.1 编译指令
hlsl
CGPROGRAM
// 编译目标
#pragma target 3.0 // Shader Model 3.0
#pragma target 4.0 // Shader Model 4.0
#pragma target 5.0 // Shader Model 5.0
// 顶点和片元着色器入口
#pragma vertex vert
#pragma fragment frag
// 表面着色器指令
#pragma surface surf Lambert
#pragma surface surf Standard fullforwardshadows
// 几何着色器(需要SM 4.0+)
#pragma geometry geom
// 细分着色器(需要SM 4.6+)
#pragma hull hull_program
#pragma domain domain_program
// 多编译变体
#pragma multi_compile_fwdbase
#pragma multi_compile_fwdadd
#pragma multi_compile_fog
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma shader_feature _NORMALMAP
#pragma skip_variants POINT_COOKIE DIRECTIONAL_COOKIE
// 禁用警告
#pragma disable warning 3205 // 禁用特定警告
// 优化指令
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
5.2 结构体定义
hlsl
// 输入结构体
struct appdata_base
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct appdata_tan // 带切线的输入
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 texcoord : TEXCOORD0;
};
// 输出结构体
struct v2f_base
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
};
// 复杂输出(支持多光源)
struct v2f_forward_base
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
float3 worldTangent : TEXCOORD3;
float3 worldBitangent : TEXCOORD4;
SHADOW_COORDS(5) // 阴影坐标,占用TEXCOORD5
UNITY_FOG_COORDS(6) // 雾坐标,占用TEXCOORD6
#if defined(LIGHTMAP_ON)
float2 lightmapUV : TEXCOORD7;
#endif
};
六、Fallback 和 CustomEditor
6.1 Fallback 回退机制
hlsl
// 1. 回退到内置Shader
Fallback "VertexLit"
Fallback "Diffuse"
Fallback "Specular"
Fallback "Standard" // Unity标准Shader
// 2. 禁用回退
Fallback Off
// 3. 自定义回退
Fallback "Custom/MyFallbackShader"
6.2 CustomEditor 自定义编辑器
hlsl
// 关联自定义编辑器脚本
CustomEditor "MyShaderEditor"
// 内置编辑器
CustomEditor "StandardShaderGUI" // 标准Shader编辑器
CustomEditor "SimpleShaderGUI" // 简单Shader编辑器
七、完整示例
hlsl
Shader "Custom/AdvancedShaderExample"
{
Properties
{
[Header(Main Settings)]
[MainColor] _BaseColor ("颜色", Color) = (1,1,1,1)
[MainTexture] _MainTex ("纹理", 2D) = "white" {}
[Header(Normal Map)]
[Normal] _BumpMap ("法线贴图", 2D) = "bump" {}
_BumpScale ("法线强度", Range(0, 2)) = 1
[Header(Specular)]
_SpecColor ("高光颜色", Color) = (0.5,0.5,0.5,1)
_Glossiness ("光泽度", Range(0,1)) = 0.5
[Header(Emission)]
[HDR] _EmissionColor ("自发光颜色", Color) = (0,0,0,1)
_EmissionMap ("自发光贴图", 2D) = "white" {}
[Header(Advanced)]
[Toggle(_ALPHATEST_ON)] _AlphaTest ("启用Alpha测试", Float) = 0
_Cutoff ("Alpha阈值", Range(0,1)) = 0.5
[Enum(UnityEngine.Rendering.CullMode)] _Cull ("剔除模式", Float) = 2
}
SubShader
{
Tags
{
"RenderType" = "Opaque"
"Queue" = "Geometry"
"RenderPipeline" = "UniversalPipeline"
}
LOD 300
// 共享代码
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
ENDHLSL
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
Cull [_Cull]
ZWrite On
ZTest LEqual
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _ADDITIONAL_LIGHTS
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 texcoord : TEXCOORD0;
};
struct Varyings
{
float4 positionHCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normalWS : TEXCOORD1;
};
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
Varyings vert(Attributes input)
{
Varyings output;
VertexPositionInputs positionInputs = GetVertexPositionInputs(input.positionOS.xyz);
output.positionHCS = positionInputs.positionCS;
output.uv = input.texcoord;
output.normalWS = TransformObjectToWorldNormal(input.normalOS);
return output;
}
half4 frag(Varyings input) : SV_Target
{
half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
return color;
}
ENDHLSL
}
// 阴影Pass
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On
ZTest LEqual
HLSLPROGRAM
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
ENDHLSL
}
}
Fallback "Universal Render Pipeline/Lit"
CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.LitShader"
}
八、总结
关键点:
-
Properties:定义材质面板的可调参数
-
SubShader:针对不同硬件/平台的着色器变体
-
Tags:控制渲染顺序、类型等元数据
-
Pass:具体的渲染通道,每个Pass执行一次渲染
-
Render States:控制GPU渲染状态(混合、深度、剔除等)
-
Shader Code:HLSL/Cg代码,实际的着色器逻辑
最佳实践:
-
使用合适的Queue标签确保正确的渲染顺序
-
为半透明物体设置Transparent渲染类型
-
为阴影接收物体添加ShadowCaster Pass
-
使用Fallback提供兼容性
-
合理使用LOD值控制不同硬件的表现
掌握ShaderLab结构是编写高质量Unity Shader的基础,理解每个部分的作用和相互关系至关重要。