GameTech/URP 渲染实战

案例 17.2阴影 Pass 同步顶点偏移入门

目标:直观看到“只在颜色 Pass 里做顶点动画”的后果,理解为什么必须在 ShadowCaster、DepthOnly 中做同样的变形。

原理:主光阴影贴图是在相机渲染之前,由 ShadowCaster Pass 从光源视角单独渲染的。如果 ShadowCaster 不做变形,阴影贴图里记录的就是原始的平面旗子:地面上的影子是一个规规矩矩的矩形,而且旗子自己接收的自阴影也是“平面旗子”投下的,与它实际的起伏完全无关。

Flag Shader 为演示这个错误,给阴影 Pass 准备了一个带开关的变形函数,通过 VA_DEFORM_SHADOW 宏替换公共文件里阴影 Pass 调用的函数(见上一节 deform 片段末尾)。实际项目里不需要这个开关,公共文件默认就让阴影 Pass 调用同一个 Deform。

图 17-4俯视旗帜与地面上的投影。左:阴影 Pass 不变形,影子是一个平整的矩形,与飘动的旗面毫无关系;右:阴影 Pass 与颜色 Pass 使用同一个 Deform,影子随旗面起伏

阴影 Pass 里的变形还有一个容易忽略的细节:ApplyShadowBias 的法线偏移(Normal Bias)使用的是变形后的法线。如果 Deform 只改位置不改法线,在起伏剧烈的地方法线偏移的方向是错的,可能产生阴影痤疮或漏光。本章的框架里 Deform 同时更新 normalOS,阴影 Pass 自然拿到正确的法线。

深入:其他需要同步的地方① DepthOnly / DepthNormals:开启了 Depth Texture、SSAO 或 Depth Priming 时它们会被执行;不同步会导致 SSAO 的暗角留在原位置、软粒子在错误的地方变淡。② MotionVectors:URP 14 有对象运动矢量 Pass(MotionVectorRenderPass 绘制 LightMode 为 MotionVectors 的 Pass,Shader 没有这个 Pass 时使用内置的回退材质)。回退材质不知道你的顶点动画,所以依赖运动矢量的效果(例如 TAA、运动模糊的对象模式)看到的是静止的物体。需要的话可以仿照 URP 的 ObjectMotionVectors.shader 自己写一个 MotionVectors Pass,在里面用当前帧和上一帧的时间各算一次 Deform。③ Meta Pass:烘焙光照贴图时用,顶点动画物体一般不参与烘焙,可以忽略。