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

【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)

相关推荐
yiyeguzhou10010 小时前
论文解读:CortenMM- Efficient Memory Management with Strong Correctness Guarantees
性能优化·云计算
闲人编程10 小时前
Django中间件开发:从请求到响应的完整处理链
python·中间件·性能优化·django·配置·codecapsule
❆VE❆10 小时前
【技术分享】前端跨窗口/标签页面通信:掌握以下几种方法,提升用户体验(附带常用场景以及典例)
前端·javascript·性能优化·vue·跨标签通信
年小个大17 小时前
优化App启动时间?startup-coroutine是什么?
性能优化·架构·kotlin
ZouZou老师19 小时前
FFmpeg性能优化经典案例
性能优化·ffmpeg
七夜zippoe20 小时前
使用Ollama在消费级硬件上运行大模型:从环境配置到企业级实战
性能优化·大模型·模型量化·ollama
SmalBox20 小时前
【URP】Unity[内置Shader]非光照Unlit
unity3d·游戏开发·图形学
2401_861277551 天前
Web应用程序、服务器、数据库性能测试工具Jemeter使用方法与举例说明
性能优化·压力测试
6***S2221 天前
SQL Server Management Studio的使用
数据库·oracle·性能优化
谢尔登1 天前
原来Webpack在大厂中这样进行性能优化!
前端·webpack·性能优化