Unity Shader中如何学习阴影技术 产生阴影,接受阴影,联级阴影,软阴影

在Unity Shader里学习阴影,关键是理解其核心------Shadow Map(阴影贴图),并掌握一套清晰的学习路径。你可以从了解全局开始,然后逐步深入到各个技术点。

🧭 先构建全局视角:阴影技术概览

在深入代码之前,建议先理清这些基础概念,它们能帮你更好地理解后续的具体实现:

  • Shadow Map 原理:它是现代实时阴影技术的基石。过程分两步:第一步,从光源视角将场景深度渲染到一张贴图里;第二步,在正常渲染时,将当前片段的位置转换到光源空间,比较其深度值与Shadow Map中存储的深度值,以此判断该点是否处于阴影中。

  • 硬阴影 vs. 软阴影 :光线完全被遮挡会产生边缘锐利的硬阴影 ;而现实中光源有体积,会造成半影区,产生边缘过渡柔和的软阴影,真实感更强,但性能开销也更大。

  • 阴影级联 (Shadow Cascades):专为解决方向光(如太阳光)在近处阴影出现的"透视锯齿"问题。它将摄像机的视锥体从近到远划分成多个区域(级联),为近处区域分配更高的阴影贴图分辨率,来保证近处阴影的清晰度。

  • 关键API和宏 :编写Shader时,Unity提供了便捷的宏。例如,SHADOW_COORDS用于定义阴影坐标,TRANSFER_SHADOW用于计算阴影坐标,SHADOW_ATTENUATION用于获取阴影衰减值。

  • 不同渲染管线的差异

    • 内置渲染管线:实现方式较直接,但宏较多,容易让新手混淆。

    • URP:推荐新手从URP开始。它的API和命名更清晰,Shader结构也更现代化,是Unity未来的主流方向。

    • HDRP:主要用于追求顶尖画质的项目,默认阴影效果已经很完善,通常不需要开发者从头编写阴影Shader。


📚 循序渐进:分步学习指南

1. 产生阴影(投射阴影)

这是实现阴影功能的基础,让物体能够在地面或其他物体上留下影子。

  • 核心:ShadowCaster Pass

    一个物体要向场景投射阴影,它的Shader必须包含ShadowCaster这个Pass。Unity在渲染阴影贴图时,就是通过它来获取物体从光源视角看到的"样子"。

  • 快速实现

    • 方法一(推荐新手) :使用 UsePass 命令。它能直接复用Unity内置Shader中的ShadowCasterPass,是生成可投射阴影Shader最简单的方法。

    • 方法二(手动实现) :在Shader中显式定义一个ShadowCaster Pass。这能让你更深入地理解阴影贴图的渲染过程,但代码会复杂一些。

2. 接受阴影

这是让你的Shader能够正确地响应其他物体投射过来的阴影。

  • 核心步骤

    1. 声明阴影坐标 :在顶点着色器的输出结构体(v2f)中,使用SHADOW_COORDS宏来定义一个用于存储阴影贴图采样坐标的成员。

    2. 计算阴影坐标 :在顶点着色器中,使用TRANSFER_SHADOW宏来计算阴影坐标并传递给片元着色器。

    3. 采样并应用阴影 :在片元着色器中,使用SHADOW_ATTENUATION宏来获取当前像素的阴影强度(0为全阴影,1为全光照),然后用这个值乘以光照颜色即可得到阴影效果。

  • 完整的内置管线示例

    下面是一个内置管线中实现了接受阴影的完整Shader示例,结合了漫反射光照:

cs 复制代码
Shader "Lit/Diffuse With Shadows" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader {
        Pass {
            Tags {"LightMode"="ForwardBase"}

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap novertexlight
            #include "AutoLight.cginc"

            struct v2f {
                float2 uv : TEXCOORD0;
                SHADOW_COORDS(1) // 1. 声明阴影坐标
                fixed3 diff : COLOR0;
                fixed3 ambient : COLOR1;
                float4 pos : SV_POSITION;
            };

            v2f vert (appdata_base v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;
                half3 worldNormal = UnityObjectToWorldNormal(v.normal);
                half nl = max(0, dot(worldNormal, _WorldSpaceLightPos0.xyz));
                o.diff = nl * _LightColor0.rgb;
                o.ambient = ShadeSH9(half4(worldNormal,1));
                TRANSFER_SHADOW(o); // 2. 传递阴影坐标
                return o;
            }

            sampler2D _MainTex;
            fixed4 frag (v2f i) : SV_Target {
                fixed4 col = tex2D(_MainTex, i.uv);
                fixed shadow = SHADOW_ATTENUATION(i); // 3. 获取阴影衰减
                fixed3 lighting = i.diff * shadow + i.ambient;
                col.rgb *= lighting;
                return col;
            }
            ENDCG
        }
        UsePass "Legacy Shaders/VertexLit/SHADOWCASTER" // 复用投射阴影的Pass
    }
    FallBack "Diffuse"
}
3. 级联阴影 (Cascaded Shadow Maps)

主要用于解决方向光阴影在近处的"透视锯齿"问题,通过为不同距离的区域分配不同分辨率的阴影贴图,来保证近处阴影清晰。

  • 配置与可视化 :在项目的Quality Settings (内置管线)或URP Asset (URP管线)中设置级联数量(0、2或4)。可以使用Rendering Debugger (Window > Analysis > Rendering Debugger)的Lighting > Shadow Cascades选项来可视化每个级联的覆盖范围,方便调优。

  • Shader支持 :在Shader中,只需要添加对应的预处理宏(如_MAIN_LIGHT_SHADOWS_CASCADE),引擎会自动处理级联的选择和采样。

4. 软阴影 (Soft Shadows)

通过模拟半影区域让阴影边缘看起来更柔和,增强真实感。

  • 如何在项目中开启 :在光源的Inspector面板中,将Shadow Type 设置为Soft Shadows 。在URP Asset中,确保Soft Shadows选项已勾选。

  • 性能与技巧:软阴影开销更大,因为它需要对阴影贴图进行多重采样滤波。一个优化技巧是,使用较低的阴影分辨率(如1024)并开启软阴影,反而能获得视觉上更柔和的阴影效果。

  • 进阶:PCSS (Percentage-Closer Soft Shadows):这是一种更高级的软阴影技术,能根据遮挡物距离光源的远近,动态改变阴影的软硬程度。PCSS的性能开销很高,需要你编写复杂的自定义Shader或在Asset Store中寻找解决方案。


⚡ 高级技巧与优化

  • 材质与物体设置:在编辑器中,物体的Mesh Renderer组件可单独控制是否"Cast Shadows"(投射阴影)和"Receive Shadows"(接受阴影)。

  • 处理透明材质 :Alpha Test(镂空)材质需要在ShadowCaster Pass中进行裁剪,以投射出符合形状的阴影。

  • 阴影顽疾 (Shadow Artifacts) 的解决 :常见问题包括阴影痤疮 (表面出现条纹状伪影)和Peter Panning (阴影与物体分离),可以通过调整光源设置里的Bias参数来修复。

  • Bias 的深刻影响Bias分为Depth Bias(深度偏移)和Normal Bias(法线偏移)。Depth Bias主要解决阴影痤疮,而Normal Bias主要解决Peter Panning。调整这两个值是阴影调试中最关键的一步,需要根据你的场景反复试验。

  • 性能调优

    • 级联阴影性能 :级联数量增加会成倍增加渲染开销,建议在Quality Settings中严格限制阴影的Shadow Distance(阴影距离)。

    • 移动平台优化:在移动设备上,尽量使用硬阴影并限制阴影距离。如果必须使用软阴影,务必做好性能分析(Profiling)。

    • 复杂几何体阴影:对于高模或远处的物体,可以考虑使用低模(LOD)来投射阴影,以降低GPU负担。

🚀 总结与学习路径建议

  1. 从URP开始:建立新项目,选择URP模板。

  2. 理解原理:学习Shadow Map的基本原理,通过光源Shadow Type的不同设置,直观对比硬阴影与软阴影、有无级联的视觉效果。

  3. 编写Shader:使用Shader Graph或手写HLSL Shader,从最基本的"接受阴影"功能开始,确保物体能正确响应光照和阴影。

  4. 进阶实现 :手动添加ShadowCaster Pass,实现完整的阴影投射与接收。

  5. 优化与调试:学习调整光源的Bias、Shadow Distance等参数,并使用Frame Debugger和Rendering Debugger来分析和优化阴影性能。

相关推荐
♡すぎ♡2 小时前
ShaderLab:线条几何体旋转
unity·计算机图形学·着色器·shaderlab
鱼很腾apoc2 小时前
【学习篇】第17期 C++入门必看——类和对象全站最详篇
c语言·开发语言·学习·算法·青少年编程
小贺儿开发2 小时前
【MediaPipe】Unity3D 指间游鱼互动演示
游戏·unity·人机交互·摄像头·手势识别·互动·康复训练
土豆~3 小时前
Claude Code源码学习—— Agent Prompt 设计
学习·prompt·claude code
星幻元宇VR3 小时前
VR流动行走平台|让虚拟体验真正“走起来”
科技·学习·安全·vr·虚拟现实
赵侃侃爱分享3 小时前
学习网络安全后首先应该做这些工作
学习·安全·web安全
像一只黄油飞3 小时前
第二章-02-注释
笔记·python·学习·零基础
xiebingsuccess3 小时前
ThingsPanel IoT Platform 学习笔记
笔记·学习
网创联盟,知识导航3 小时前
沐雨云香港直连500M大带宽云主机深度测评
经验分享·学习·测试工具