ShaderLab 基本结构详解

一、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"
}

八、总结

关键点:

  1. Properties:定义材质面板的可调参数

  2. SubShader:针对不同硬件/平台的着色器变体

  3. Tags:控制渲染顺序、类型等元数据

  4. Pass:具体的渲染通道,每个Pass执行一次渲染

  5. Render States:控制GPU渲染状态(混合、深度、剔除等)

  6. Shader Code:HLSL/Cg代码,实际的着色器逻辑

最佳实践:

  1. 使用合适的Queue标签确保正确的渲染顺序

  2. 为半透明物体设置Transparent渲染类型

  3. 为阴影接收物体添加ShadowCaster Pass

  4. 使用Fallback提供兼容性

  5. 合理使用LOD值控制不同硬件的表现

掌握ShaderLab结构是编写高质量Unity Shader的基础,理解每个部分的作用和相互关系至关重要。

相关推荐
mxwin1 天前
Unity Shader 极坐标特效 从数学原理到实战案例
unity·游戏引擎·shader·uv
mxwin2 天前
Unity Shader UI 流光效果完全推导指南
ui·unity·游戏引擎·shader·uv
mxwin3 天前
Unity Shader FLOWMAP岩浆流动制作案例
unity·游戏引擎·shader·uv
mxwin3 天前
Unity Shader 用 Ramp 贴图实现薄膜干涉效果
unity·游戏引擎·贴图·shader·uv
mxwin4 天前
Unity Shader · UV 技术 用 UV 坐标打造水波涟漪效果
unity·游戏引擎·shader·uv
千里马-horse1 个月前
Building a Simple Engine -- Mobile Development -- Conclusion
pipeline·shader·rendering·vulkan
千里马-horse1 个月前
Building a Simple Engine -- Mobile Development -- Performance optimizations
shader·内存优化·rendering·纹理优化·vulkan·压缩格式
weixin_409383121 个月前
cocosshader像素风沙消散
shader·cocos
千里马-horse1 个月前
Building a Simple Engine -- Tooling -- Introduction
pipeline·shader·rendering·vulkan
千里马-horse2 个月前
Multithreading with Vulkan
shader·rendering·vulkan·vertex·multithreaded