当前位置: 首页 > news >正文

【C++游戏引擎开发】第24篇:级联阴影映射(CSM,Cascaded Shadow Maps)

一、阴影映射技术基础

1.1 阴影映射的核心原理

1.1.1 深度测试与阴影生成

阴影映射(Shadow Mapping)是一种基于深度比较的阴影渲染技术,其核心思想分为两步:

  1. 从光源视角渲染深度贴图:将场景渲染到光源的深度缓冲区,生成阴影贴图(Shadow Map)​
  2. 从摄像机视角进行深度比较:在正常渲染时,将像素点转换到光源空间,比较其深度值与阴影贴图记录的深度值,决定是否处于阴影中。

数学上,阴影可见性计算可表示为:
V ( p ) = { 0 若  d fragment > d shadow map 1 否则 V(p) = \begin{cases} 0 & \text{若 } d_{\text{fragment}} > d_{\text{shadow map}} \\ 1 & \text{否则} \end{cases} V(p)={01 dfragment>dshadow map否则
其中 d fragment d_{\text{fragment}} dfragment 是当前片元到光源的深度, d shadow map d_{\text{shadow map}} dshadow map 是阴影贴图中存储的最近深度。

1.1.2 关键问题:透视走样(Perspective Aliasing)

传统阴影映射在以下场景中表现不佳:

  • 近处物体:阴影贴图分辨率不足导致锯齿(锯齿状阴影边缘)
  • 远处物体:相同纹理像素覆盖过大区域,导致模糊(过度稀疏采样)

根本原因在于透视投影下深度分布的非线性,使得固定分辨率的阴影贴图无法均匀分配精度。

1.2 阴影映射的数学基础

1.2.1 光源空间变换
  1. 模型-光源视图矩阵(Light View Matrix)​:将物体从世界坐标系变换到光源视角的视图空间。
  2. 光源投影矩阵(Light Projection Matrix)​:通常使用正交投影(方向光)或透视投影(点光源)。

组合后的变换矩阵为:
M light = M projection × M view M_{\text{light}} = M_{\text{projection}} \times M_{\text{view}} Mlight=Mprojection×Mview

1.2.2 深度值非线性分布

在透视投影中,深度值 z z z 的归一化计算公式为:
z ndc = f + n f − n + 2 f n f − n ⋅ 1 z z_{\text{ndc}} = \frac{f+n}{f-n} + \frac{2fn}{f-n} \cdot \frac{1}{z} zndc=fnf+n+fn2fnz1
其中 n n n f f f 为近、远平面,导致深度缓冲区中近处精度高、远处精度低。

1.3 阴影映射的局限性

1.3.1 自阴影问题(Shadow Acne)

由于深度贴图分辨率和浮点精度限制,表面可能错误地判定自身处于阴影中。常用解决方案:

  • 深度偏移(Depth Bias)​:添加固定或斜率缩放偏移量:
    d adjusted = d fragment + bias d_{\text{adjusted}} = d_{\text{fragment}} + \text{bias} dadjusted=dfragment+bias
1.3.2 Peter-Panning 现象

过度使用深度偏移会导致物体与阴影分离(“漂浮”效果)。需在视觉质量与偏移量之间权衡。


二、级联阴影映射(CSM)理论

2.1 CSM 的设计动机

2.1.1 动态分辨率分配

将摄像机视锥体(View Frustum)按深度分割为多个子区域(级联),每个级联独立生成阴影贴图:

  • 近层级:高分辨率贴图,捕捉细节
  • 远层级:低分辨率贴图,节省资源
2.1.2 视锥体分割策略

常用的分割方式包括:

  1. 均匀分割(Uniform Split)​:线性划分深度范围
    z i = n + i k ( f − n ) z_i = n + \frac{i}{k}(f-n) zi=n+ki(fn)
  2. 对数分割(Logarithmic Split)​:适应透视分布
    z i = n ( f n ) i / k z_i = n \left( \frac{f}{n} \right)^{i/k} zi=n(nf)i/k
  3. 实用分割(Practical Split)​:混合线性与对数分割

2.2 CSM 的算法流程

2.2.1 视锥体分割与层级计算
  1. 将摄像机视锥体分割为 k k k 个层级(通常 k = 4 k=4 k=4
  2. 对每个层级计算其包围盒(AABB)
2.2.2 光源投影矩阵优化

为每个层级生成紧贴包围盒的正交投影矩阵,最大化利用阴影贴图像素:

  1. 将层级包围盒变换到光源空间
  2. 计算包围盒在光源空间的最小/最大坐标
  3. 构建正交投影矩阵:
    M ortho = [ 2 r − l 0 0 − r + l r − l 0 2 t − b 0 − t + b t − b 0 0 2 f − n − f + n f − n 0 0 0 1 ] M_{\text{ortho}} = \begin{bmatrix} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l} \\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{t-b} \\ 0 & 0 & \frac{2}{f-n} & -\frac{f+n}{f-n} \\ 0 & 0 & 0 & 1 \end{bmatrix} Mortho= rl20000tb

相关文章:

  • springboot3 声明式 HTTP 接口
  • HTML 地理定位(Geolocation)教程
  • hadoop-3.3.5.tar.gz 镜像
  • OpenHarmony之电源模式定制开发指导
  • 策略模式(Strategy Pattern)详解
  • 2、Ubuntu 环境下安装RabbitMQ
  • 【高频考点精讲】前端构建工具对比:Webpack、Vite、Rollup和Parcel
  • 内联函数(c++)
  • 【FastJSON】的parse与parseObject
  • Oracle for Linux安装和配置(11)——Oracle安装和配置
  • 基于STM32、HAL库的MAX31865模数转换器ADC驱动程序设计
  • 嵌入式 C 语言面试核心知识点全面解析:基础语法、运算符与实战技巧
  • c++之网络编程
  • 立创商城、云汉芯城、亿配芯城均启用DeepSeek AI 大模型赋能电子元器件采购平台
  • 第十四届蓝桥杯刷题——day20
  • [官方IP] AXI Memory Init IP
  • 【音视频】AVIO输入模式
  • UnityEditor - 调用编辑器菜单功能
  • 汽车零配件供应商如何通过EDI与主机厂生产采购流程结合
  • Spark读取Apollo配置
  • 时代邻里:拟收购成都合达联行科技剩余20%股权
  • 国家数据发展研究院在京正式揭牌
  • 成都一季度GDP为5930.3亿元,同比增长6%
  • 世卫发布预防少女怀孕新指南,呼吁终止童婚、延长女孩受教育时间
  • 停止水资源共享、驱逐武官,印度对巴基斯坦宣布多项反制措施
  • 中国建设银行原党委委员、副行长章更生严重违纪违法被开除党籍