再聊阴影裁剪与高性能视锥剔除

【USparkle专栏】如果你深怀绝技,爱"搞点研究",乐于分享也博采众长,我们期待你的加入,让智慧的火花碰撞交织,让知识的传递生生不息!


一、实际需求

因为项目的树与草都采用Compute Shader剔除的GPU Instance绘制,所以需要自己实现阴影投递物的裁剪方法。也就是每一帧具体让哪些物体绘制ShadowMap。该计算的精确性会很影响树(有大量顶点又需要用AlphaTest镂空)的渲染性能。之前实现了一版《阴影视锥裁剪实现》,是在世界空间暴力计算,不算直观,也不精巧。最近有一种非常不错又好理解的新思路,所以再分析一次。

二、主要思路

  • 把物体的AABB的8个顶点转到灯光空间,重新计算出AABB(与灯光空间xyz轴平行)。
  • 把视锥的6个平面与AABB也转到灯光空间。
  • 如果物体AABB的max.z < 视锥AABB的max.z,则把物体AABB的max.z设置为视锥AABB的max.z(这里是比较巧妙一步,解决了本身在视锥外但投影在视锥内的物体)。

满足以上三步后,只要做普通视锥与AABB裁剪就行了,效果演示如下:

期间也尝试过一种裁剪计算量更小但精确度稍差一点的思路,就是在灯光空间下取消z判断,当作2D几何,求交。那么计算量会小很多。主体思想和这套相同,可根据实际项目来判断要省裁剪性能还是提示裁剪精度。演示如下:

三、代码解释

为了方便自己与其他人验证算法,一般用C#实现,等落地时再转Compute Shader。为了代码清晰,一些不复杂的计算直接用Unity的API。做Compute Shader时需要实现这些基础函数,都能找到这种标准件代码。

1. 视锥转换

把视锥体转到灯光空间,并绘制出5个视锥平面的法线(仅调试平面法线方向用),一般为了通用性视锥按6个平面处理,实际绝大部分项目,NearClip都靠近0,当作一个锥体处理。转换的方式比较简单每个点通过灯光矩阵转完 重新计算AABB即可。

灯光空间下 视锥体AABB

2. 对象转换

把投影对象AABB也转到灯光空间,转换方法和视锥那个一样,不过要转8个顶点,并做z轴方向延长。延长后的体积,就是整个阴影有效范围。这里可以做一个小优化,如果最小的z比相机最大的z还大就不用计算了,说明在相机外侧且远离灯光的方向,不可能投影入可见区域。

四、再谈视锥裁剪

这样在转换后做正常视锥裁剪就行,而这部分技术就非常普遍成熟。但写这篇主要是为了分享一种非常规裁剪,用于对树这种少裁剪一棵就影响帧数的项目,会比普通裁剪精确很多。

先看两种裁剪对比效果:

普通视锥裁剪

本方案裁剪

普通裁剪是比较保守但偏向正确和低复杂度的模式,就是要存在至少一个视锥平面,让这AABB的8个点同时在这个平面的外部。所以整体在视锥外部,但不同顶点在不同平面外部的情况就剔除不了。比如下图,没有任何一个平面可以让所有点都满足在它的外侧。

普通裁剪逻辑代码

不满足裁剪条件但应用剔除的情况

这是因为这种方式区分不了上图与下图2种不同情况,为了画面不出错只能选择保守处理:

不满足裁剪条件但不应用剔除的情况

五、精确裁剪推导

这部分逻辑属于功能扩展,如果不是有优化渲染性能要求,不需要了解这部分,直接用常规裁剪就好了。

首先做视锥AABB与物体AABB重叠检测,这不满足,肯定剔除(偏保守,但能加速淘汰)。

我们把物体AABB,与视锥重叠的方式分为2类:

  1. 物体AABB与视锥4个侧面三角形发生碰撞的重叠类型。
  2. 物体AABB不与视锥4个侧面三角形发生碰撞的重叠类型。

物体AABB与视锥4个侧面三角形发生碰撞的重叠类型

物体AABB不与视锥4个侧面三角形发生碰撞的重叠类型

可以这样归纳两类,如果重叠,那么不是物体AABB与视锥4个三角形碰撞,就是物体AABB有个角点在视锥内。

因为不存在只与远平面碰撞而同时又没有顶点在视锥体内的情况。因为这时候AABB会穿透视锥体,而视锥体是封闭多面体,这种时候一定会再与四个侧面发生碰撞,所以可归到第一类里。

对应的代码如下。其中三角形与AABB碰撞函数,是用GitHub上cginc文件改的,后面落地Compute Shader还能直接用它。
github.com/bonzajplc/A...

解决普通视锥裁剪的问题


这是侑虎科技第1541篇文章,感谢作者jackie 偶尔不帅供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:465082844)

作者主页:www.zhihu.com/people/jack...

再次感谢jackie 偶尔不帅的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:465082844)

相关推荐
CCblandy10 小时前
Agent 工具调用怎么编排?本机实测:并行只到 2.63 倍,慢的先发省 30ms,CPU 活加 worker 无效
人工智能·后端·python·性能优化
用AI来创业吧15 小时前
网站建设公司哪家好:报价差 3 倍,差在哪四项成本上(选型笔记)
笔记·性能优化·软件工程·安全威胁分析
yunwei3717 小时前
eBPF 入门实践教程:BPF Token,安全的委托式权限与程序加载
linux·后端·性能优化
SmalBox18 小时前
04-05-源码-清单生成与构建报告
unity3d·游戏开发
CSharp精选营21 小时前
SaveChanges 一万行?换批量操作快 10 倍
性能优化·efcore·批量操作·csharp·executeupdate
爱喝水的鱼丶1 天前
SAP-ABAP:S/4 HANA ABAP 新特性入门:与 ECC ABAP 的核心差异、架构优势与学习路径规划
运维·数据库·性能优化·sap·abap·hana·开发交流
余槐i1 天前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
余槐i1 天前
Skills 增至 30 个,Claude Code 反而变慢:token 与加载实测
性能优化·开发工具·ai agent·claude code·agent skills
xiaoqiMikko1 天前
fastjson 1.2.84 的补丁关掉了一个缓存:addAccept 包前缀白名单下,反序列化慢了 13~28 倍
java·后端·性能优化
万联WANFLOW1 天前
LLM 调用很快,AI Agent 为什么还是慢?关键路径分析与优化方法
性能优化·llm·aigc