概念页
阴影基础与阴影体
Shadow Basics & Shadow Volumes
阴影帮助玩家判断物体的位置。精确光源只产生硬阴影,面光源产生带本影和半影的软阴影。最简单的情况是投射到平面上的投影阴影;投影纹理可把阴影扩展到曲面;阴影体用模板缓冲计数,能在任意表面得到精确硬阴影,但开销极不稳定,如今很少使用。
术语与感知
- 遮挡体 (occluder) 向接收体 (receiver) 投下阴影;精确光源只产生全阴影区(硬阴影);面光源或体积光源产生软阴影,分为本影(全阴影)和半影(部分阴影)。
- 软阴影一般不能靠低通模糊硬阴影边缘得到:遮挡体离接收体越近,阴影越锐利(例如《The Division》中箱子阴影锐利、人影在接触点锐利向外变软)。软阴影的本影也不等于点光源的硬阴影——光源越大本影越小,甚至消失。
- 软阴影的半影让人确认这是阴影;硬阴影看起来不真实,有时会被误认为几何特征(如表面折痕),但渲染更快。
- 有阴影比没阴影更重要:人眼对阴影形状很宽容,不准确的阴影也比没有好,例如地面上一个模糊黑圆就能把角色"锚"在地上。
平面投影阴影
- 把物体再渲染一次,用矩阵将顶点从光源位置投影到平面 上: 平面为 时有 ,。投影后的物体用深色、无光照渲染。
- 避免阴影三角形画在接收面之下:给投影平面加偏移;更安全的是先画地面,关闭 z-buffer 画投影三角形,再正常画其余物体。地面有边界(矩形)时用模板缓冲限制阴影只画在接收面上。
- 也可把阴影渲染到纹理(一种光照贴图)贴到地面,但纹理可能被放大;光源与投影物体不相对移动时可复用——多数阴影技术都能从逐帧复用中间结果获益。
- 所有投影物体必须在光源和地面之间:光源低于物体最高点会产生反阴影 (antishadow);在接收面之下的物体也不应投影。
平面软阴影
- 在面光源上放多个点光源分别渲染并平均(Heckbert & Herf),任何硬阴影算法都可这样得到半影;但看起来像多个重叠硬阴影, 遍只有 种灰度,代价过高,适合作为检验其他算法的"地面真值"。
- 更高效的是卷积/模糊:模糊一个点光源的硬阴影有时就够(如 Autodesk 查看器的 drop shadow),但在物体接触地面处均匀模糊不可信。Haines 方法在轮廓边上画渐变产生半影(但半影应向轮廓内延伸,本影偏大);Iwanicki 用椭球近似角色。
曲面上的投影阴影
- 从光源视角把遮挡体画成黑色、其余白色,再把这张图像作为投影纹理贴到接收体上。平台跳跃游戏中常给主角正下方一个 drop shadow,即使角色已在阴影中,以帮助判断位置。
- 缺点:应用必须指定谁是遮挡体、谁是接收体;接收体必须比遮挡体离光源更远,否则阴影"反向投射";遮挡体不能自阴影。
- 预制的投影纹理可得到各种光照图案(聚光圆、百叶窗),称为光照衰减遮罩、cookie 或 gobo,可与动态生成的投影纹理相乘。
阴影体
- Heidmann (1991):从点光源穿过三角形顶点延伸到无穷,三角形下方的截断无穷棱锥就是阴影体,其中的物体在阴影中。
- 沿视线计数:穿过阴影体正面 +1,背面 −1,到达表面时计数大于 0 则在阴影中。用模板缓冲实现:清空模板 → 用未受光材质颜色画整个场景(得到深度)→ 关闭深度写和颜色写(保留深度测试),画阴影体正面并递增模板 → 画背面并递减 → 只在模板为 0 处再渲染受光部分。
- 物体穿过相机近平面时计数出错,解决方法是 z-fail:统计可见表面之后被遮挡的穿越次数,此时阴影体必须封口。
- 优点:只需模板缓冲、不基于图像,没有采样问题,处处精确锐利——这有时反而是缺点,例如衣服褶皱的细硬阴影严重混叠。
- 缺点:每个三角形生成三个四边形,过度绘制巨大(1000 个三角形的球生成 3000 个四边形);只沿轮廓边生成可减少到约 50 个,可用几何着色器生成。最严重的是开销极不稳定:相机与光源同位时几乎无开销,绕着走开后阴影体覆盖越来越多屏幕,相机进入阴影时会填满整个屏幕,看向光源时开销可能剧增。因此在需要稳定帧率的应用中基本被放弃,但仍有分层加速等研究。
GEA 的视角:阴影体(卷 II 12.5.6)
- 现实中光源有面积,光线以不同角度擦过物体边缘,所以阴影边缘模糊,形成半影;理想点光源产生锐利阴影(卷 II 12.5.6)。
- 两种最常见的技术是阴影体和阴影贴图。两者都通常把物体分成三类:投射阴影的、接收阴影的、完全不参与阴影的;光源也标记是否产生阴影。这是重要的优化,限制了需要处理的"光源-物体"组合数。
- 阴影体的生成:从产生阴影的光源视角看每个投射者,找出轮廓边,沿光线方向挤出,得到描述被遮挡空间的新几何。
- 模板缓冲做法(GEA 的描述):先正常渲染一张无阴影图像和准确的 z-buffer;模板清零;从相机视角渲染每个阴影体,正面 +1、背面 −1;阴影体正背面都可见的地方计数抵消为 0,背面被真实几何挡住的地方为 1,即在阴影中;第三遍把模板非零的区域变暗。
- 与 RTR4 的差异:
- 合成顺序不同:GEA 是"先画受光图像,再把阴影区变暗";本页 RTR4 是"先画未受光颜色,只在模板为 0 处再渲染受光部分"。
- GEA 只描述了这种 z-pass 计数,没有提到相机进入阴影体时计数出错的问题和 z-fail 方案,也没有讨论开销不稳定的缺点。
GPU Gems 的视角:高效阴影体(GPU Gems 1 第 9 章)
来源:Morgan McGuire《Efficient Shadow Volume Rendering》;摘录 Chapter 9. Efficient Shadow Volume Rendering — Morgan McGuire。Doom 3 系模板阴影体的工程手册:轮廓挤出、模板标记、多灯光叠加。
适合点/聚光/平行光的硬阴影,接收体可以是网格、公告板甚至带深度预渲的场景。能处理「灯在南瓜内、整场景几乎全黑」等反常情况。代价:几何与填充率高,CPU 负担大,本质硬边,对 alpha 测试/位移表面不友好。文中给出方向光/点光、裁剪阴影体、z-fail/z-pass、剪刀与 z-bounds 等几何与填充优化。与 阴影贴图 对照:阴影体贴图像空间可扩展软边与动画网格,阴影体则像素精确但贵。
出处
- realtime_rendering_4ed.pdf 第 7 章 Shadows
- Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 12 章 12.5.6 节
- Chapter 9. Efficient Shadow Volume Rendering — Morgan McGuire
- developer.nvidia.com/gpugems/gpugems/part-ii-lighting-and-shadows/chapter-9-efficient-shadow-volume-rendering
相关页面
图形学阴影贴图Shadow Mapping阴影贴图 (Williams, 1978) 先从光源位置渲染深度,再从相机渲染时把每个点到光源的距离与贴图中存的深度比较:更远就在阴影中。它开销可预测(生成约与图元数成线性、查询为常数时间),非常适合 GPU,是任意表面阴影最常用的算法。主要问题是分辨率、深度精度带来的混叠、阴影痤疮和漏光。图形学软阴影 PCF 与 PCSSSoft Shadows with PCF & PCSS百分比渐近过滤 (PCF) 在阴影贴图上取多个样本,分别与表面深度比较后混合结果,得到伪软阴影,但半影宽度恒定。PCSS 先搜索附近遮挡体的平均深度,再据此决定过滤宽度,从而在接触处硬、远处软(接触硬化)。游戏数学投影矩阵Projection Matrix投影矩阵把视景体变换到规范视体(OpenGL 为 [-1,1]^3,DirectX 的 z 为 [0,1]),在那里裁剪更高效。正交投影保持平行线平行、物体大小与距离无关;透视投影让远处变小,产生的深度与观察深度成反比,近平面位置和"反向 z"决定深度精度。图形学纹理映射管线Texturing Pipeline纹理通过修改着色方程中使用的值(颜色、粗糙度、法线等)来高效表现表面材质的变化。通用纹理管线是:空间位置 → 投影函数得到纹理坐标 → 对应函数变换到纹理空间 → 取值 → 值变换 → 用于着色。本页还整理纹理坐标约定、纹理表示方式、程序纹理、纹理动画、材质贴图、alpha 贴图和纹理光源。图形学轮廓边与几何描边Contour Edges & Geometric Outlining卡通渲染的黑色描边可以按表面着色、过程几何、图像处理、几何边检测或混合方式生成。本页讲边的分类,以及在几何层面生成描边的三类方法:基于着色法线、背面过程几何(偏移、膨胀、外壳)、显式检测轮廓边并做隐藏线消除。图像空间方法见 图像空间边缘检测。游戏开发 · UE5虚拟阴影贴图Virtual Shadow Maps虚拟阴影贴图 (Virtual Shadow Maps, VSM) 是 UE5 默认的阴影方法:概念上就是分辨率极高(虚拟 16k×16k)的阴影贴图,切成 128×128 的页 (Page),只为屏幕上需要着色的像素分配和渲染页,并跨帧缓存;方向光用 clipmap 覆盖大范围,软阴影由阴影贴图光线追踪 (Shadow Map Ray Tracing, SMRT) 生成。它为 Nanite 设计,与 Nanite 一起使用时最高效。图形学合并阶段与帧缓冲Merging & Framebuffer合并阶段把像素着色算出的片元颜色和缓冲区里已有的颜色结合起来,同时负责深度测试、模板测试和混合。它通常不可编程但高度可配置,也叫 ROP(光栅操作或渲染输出单元)。帧缓冲是系统中所有缓冲区的总称。图形学网格整合与顶点法线Mesh Consolidation & Vertex Normals整合 (consolidation) 指把零散多边形合并成共享顶点的网格、让所有面朝向一致、判断是否为实体,并生成平滑的顶点法线与折痕边。这些步骤是背面剔除、折痕检测、阴影体、碰撞检测、3D 打印等的前提。游戏美术阴影的美术功能与假阴影Shadow Visual Functions & Faking现以第 3 版 Ch3「Shadows and Occlusion」为准。 阴影与照明同等重要;occlusion 是可与常规阴影结合的柔和变暗。第 3 版新增 occlusion sandwich 等合成向手法。算法细节链图形学阴影/AO 页,本页偏美术功能与 cheat。游戏美术Doom 3 体积光晕Doom 3 Volumetric GlowGAT 33:Doom 3 灯具周围的「体积」光晕——美术只放简单多边形并挂材质,运行时用(疑似顶点色)网格按视角折叠展开形成光圈;仅在正对光源时绘制并随角度淡出。偏 glare(看不见光源则消失),而非持续 haze。