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的基础,理解每个部分的作用和相互关系至关重要。

相关推荐
CreasyChan1 天前
Unity Shader 入门指南
unity·c#·游戏引擎·shader
dzj20217 天前
Unity的旁门左道用法(科学计算):用shader调用GPU做k线MA5的计算——DuckDB + Compute Shader
unity·金融·gpu·shader·量化·compute shader
HONT16 天前
Unity Crest Ocean System源码阅读
shader
Jessica巨人17 天前
Shader显示为黑色
unity·shader
米芝鱼20 天前
UnityURP3D管线自定义功能shader
游戏·unity·shader·urp·着色器
雪下的新火23 天前
ASE07-魔法药剂炼制效果
经验分享·unity·shader·ase·游戏效果
在路上看风景1 个月前
1.7 C#传递参数给Shader
shader
17岁的勇气2 个月前
Unity Shader unity文档学习笔记(二十二):雪地几种实现方式(1. 2D贴花式 2.3D曲面细分并且实现顶点偏移)
笔记·学习·unity·shader
淡海水3 个月前
【URP】Unity[内置Shader]光照着色器Lit
unity·游戏引擎·shader·urp·着色器·lit