本篇接續Tiled shading的內容。
上回的light culling實作因為偷懶而只考慮物體比光源還要遠的情況,因為近處的光源照不到遠方的物體,可以將該光源剔除掉。但換個角度來看,遠處的光源即使照不到近處的物體,卻會被加入各個tile的光源列表中。而這些多餘的光源會嚴重拖累著色的計算,浪費顯卡的計算能力。如下圖:
▲水平視角,場景中擺了99個光源
▲紅色區域累積了一堆遠處的光源,但其實許多都照不到近處的物體,FPS只有21左右
這回實作的Clustered shading將Z方向切割為16塊,每一塊都有一個獨立的光源列表。Z方向切割的方式參考了惡靈古堡7,越遠處切越細。不過我稍微將比重拉回來一點,讓近處的空間不會大得太誇張。修改後的距離生成演算法如下:
log10(pow(sliceIndex / 16.0, 1.5) * 9.0 + 1.0)sliceIndex = [1, 16]
計算光源佔據了Z方向哪些區塊則參考了Nvidia的方案,計算從攝影機沿著Tile四個角落出去的四條射線與光源的碰撞座標,取得min Z與max Z後就能推得光源佔據了Z方向哪幾個區塊。再加上2.5D Culling的技巧,只對實際有物體存在的區塊寫入光源列表。結果如下圖:
▲過濾掉太遠的光源後,FPS上升到40
▲測試另一個角度
▲修改前,FPS為48
▲修改後,FPS上升到62
接下來進入大雜燴部分??偹阍黾恿斯趋绖赢嫻δ?,實作上真是個大工程。每個vertex最多被4個bone節點影響。聽說就算能處理更多節點,效果也不會變更好。因為採取混合的shading策略每個物體要被繪出兩次,所以被骨骼影響後的Mesh也在GPU中生成了兩次。
另外暗角、相片顆粒和Color grading等實作比較簡單的效果也加回來了。
▲f/8 ISO125 快門時間1/125 s
▲增加25%飽和度,Color grading模擬正片
▲模擬黑白底片
▲負片正沖