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

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

相关推荐
Edingbrugh.南空1 小时前
操作系统级TCP性能优化:高并发场景下的内核参数调优实践
网络协议·tcp/ip·性能优化
Edingbrugh.南空2 小时前
ClickHouse 全生命周期性能优化
clickhouse·性能优化
运维小贺5 小时前
各服务器厂商调整BIOS睿频教程
linux·运维·服务器·性能优化
Thomas_YXQ6 小时前
Unity3D游戏内存优化指南
游戏·unity·职场和发展·性能优化·蓝桥杯·游戏引擎·unity3d
合作小小程序员小小店9 小时前
web网页开发,在线%ctf管理%系统,基于html,css,webform,asp.net mvc, sqlserver, mysql
mysql·sqlserver·性能优化·asp.net·mvc
Thomas_YXQ1 天前
Unity URP法线贴图实现教程
开发语言·unity·性能优化·游戏引擎·unity3d·贴图·单一职责原则
一名用户1 天前
unity实现梦日记式传送组件
后端·c#·unity3d
熊猫钓鱼>_>2 天前
Django全栈开发:架构解析与性能优化实战
性能优化·架构·django
天若有情6732 天前
03_性能优化:让软件呼吸更顺畅
计算机·性能优化·软件·发展
双力臂4042 天前
MyBatis动态SQL进阶:复杂查询与性能优化实战
java·sql·性能优化·mybatis