【游戏开发】Cluster Light Culling是什么?
关于RenderPath
主流目前有Forward ,Deferred
而对于多光源,传统的Forward管线采用,一盏灯光灯光多渲染一遍物体的方法来绘制多光源,也就是Forward Add的方式,这种方式随着灯光的数量上涨,即会造成O(n*m)的复杂度。
而Deferred对于多光源,则是以先渲染图形信息GBuffer,然后延后处理灯光,O(n m)的复杂度。
为什么会突然好奇~~?
因为Cluster出现频率高。。还实现过总有一点蛋疼的感觉。。。当看到URP也有LightCulling时(不知道里面的实现有没有Tile)~就去了解一下...
Cluster Base Light Culling
无论是Deferred还是Forward,在灯光数量大的时候其实性能消耗还是很严重的,Deferred虽然解决了Forward Add在多光源下OverDraw和DC严重的问题。但也无法处理灯光数量巨大时(灯光范围影响小)。
普遍来说,如果不做Cluster,灯光机型剔除,基本的做法是用摄像机视椎体与点光(球体),与SpotLight(椎体)来进行碰撞检测做剔除。但是对于 Small light range,上千栈灯光,就很有必要做Tile / Cluster来剔除灯光。。
简单的原理理解:
1.划分Tile
给屏幕分Tile,如16x16为一个Tile,每个Tile都是一个视椎体,然后从ClipSpace转到View Space中计算,计算视椎体与每个灯光(点光球体/椎体)的相交来判定灯光是否剔除。
2.数据结构方面
1.Global Light List
2.Global Light Index List
3.Light Grid {Light Count,Light Start Offset}
按照理解,Light LIst,和Light Index List,就像VertexBuffer,和IndexBuffer,所以,最后计算完后,每个shader计算着色,也是通过 ClipPos->ScreenPos ->计算出TileIndex,得到LightGrid -> 再索引到 -> 对应的灯光信息。
3.Light Culling
1.如3dgep的教程,没有按照Depth来再分Slice 视椎体,是通过直接读取深度图,判定每个ThreadGroup (Tile)的min max Depth来决定视椎体裁剪灯光的。
2.Opaque和Transparent的裁剪因为mix max depth的原因, 有所不同,因为透明物体一般不会写入深度图,所以min depth必须=near plane,我们只能裁剪Opaque后面的灯光。
3.因为灯光是根据cluster来裁剪的,一个group Thread 包含TileSizexTileSize的线程数,每个线程都可以负责256次方的灯光,即线程1处理灯光{1,256,512...},线程2处理{2,257,513},因为是整个Tile,所以遍历灯光当然分开到每个线程啦。
4.Final shade
1.灯光剔除完成后,我们就知道了 每个Tile接受的LightList
2.通过ClipPos - > ScreenPos - >拿到对应的Tile->索引到灯光
3.遍历灯光计算灯光信息
总结:
Cluster的基本思路就是 分块,3dgep,只在2D上分了Tile,而在Emil Persson的pdf里面,则对比了几种cluster and depth的策略。
Cluster Light Culling,可以 用于Deferred (Tile base deferred),也可以用于Forward(forward plus),主要是用于用于减少灯光的复杂度。
转载声明:本文来源于网络,不作任何商业用途。
全部评论
暂无留言,赶紧抢占沙发