【Cesium 歷史博客】多視錐體優化:使用對數深度緩存


導語

Cesium 的渲染引擎是基於高精度渲染設計的。不過,就算是以米作為單位的常規游戲引擎,也會遇到精度問題,例如 z值沖突 和 抖動。

z值沖突是指兩個三角形接近時,有重疊的像素,但是深度緩存的精度不足以確定哪一個三角形更接近相機,當視圖發生變化時,這些重疊像素會閃爍。

之所以會發生 z值沖突,是因為深度緩存的精度 與 深度的倒數成正比,意味着越靠近截平面的三角形繪制精度越高,越遠則越低。

這里有一個動圖,顯示了相機在 WGS84 橢球上方約 8000 米觀察的地形發生的 z值沖突:

z值沖突的兩種解決方法:使用多視錐體、使用對數深度緩存。

在 Cesium 1.45 版本中,Cesium 混合了這兩種技術以替代原來單一的多視錐體技術。

這么做的好處顯而易見:

  • 更好的性能:減少了 drawcall
  • 更好的視覺效果:可以在不影響性能的情況下將近平面盡可能移動得近一些

1. 多視錐渲染技術

Cesium 原來的多視錐體實現是使用 3 個視錐體,其分割距離分別是 [1, 1000],[1000, 100w], [100w, 10e] 米。

這些視錐體從后到前(相對於相機)的順序進行渲染,並且在每個視錐體中深度緩存被清除。

渲染開始時,根據繪制命令(DrawCommands)的包裹范圍(boundingVolume),將繪制命令放置在一個或多個圓錐體中。

在兩個視錐邊界的繪制命令則兩邊都會繪制一次,為了優化這個重復繪制,Cesium 從視點觸發,根據最近和最遠的包裹范圍計算合適的近平面和遠平面距離,以最大程度減少視錐。(這句話翻譯得不太好,專業名稱比較多)。

下圖是珠穆朗瑪峰的近地視圖:

將每個視錐分別着色后的樣子(第一個視錐是紅色,第二個視錐是綠色,黃色介於第一個和第二個視錐中,這里看不到第三個視錐):

下圖是一樣的地形場景,只不過把視錐體顯示了出來,第一個視錐(1~1000米)太小了這里看不到。

在這個場景下,有 137 個 drawcall,第一個視錐有 28 個,第二個視錐有 102 個,第三個視錐有 7 個。重復調用數有 26 個,第一個和第二個視錐之間的重復調用占 12 個;在所有視錐體中都重復的調用有 7 個。

2. 對數深度緩存

z值沖突的另一種解決方法是使用對數深度緩存技術。

將對數值輸出到深度緩存,可以很好分配這些數值。Cesium 更新了頂點和片元着色器以支持對數深度緩存。

關於對數緩存技術,可以參考三篇博客(在國外國內訪問不了)

對上述的場景使用對數深度緩存,近平面為 0.1,遠平面為 1e8,只需一個視錐體,一共 111 個 drawcall。

這么做不僅可以減少 drawcall,而且默認情況下,近平面更接近相機,從而可以近距離查看。

對於多個視錐體,這並非不可實現,但是可能會有性能問題。只用一個視錐體,使用對數深度緩存,可以減少將繪制命令分配給每個視錐體的 CPU 計算量。

視錐上清除命令和全屏掃描命令可能比較少。對數深度緩存消除了視錐邊界處的奇怪問題,對后續開發的新功能(后處理、貼地線)會有幫助。

這是一張拖拉機的輪子,近平面為 1 米。

當近平面距離為 0.1 米時,輪胎看起來就比較完整了。

簡而言之,對於只有地形瓦片的視圖,刪除重復的 drawcall 為 10~30個。對於 3dTiles 或 BIM 模型來說,能減少 20~40 個 drawcall。

在片元着色器中,覆蓋平面很大一部分的三角形的深度信息將被寫入深度緩存,在頂點着色器中計算、插值得來的對數數值可能並不是對的。對數深度緩存的典型優化方法是僅修改頂點着色器、僅修改接近相機的三角形的片元着色器兩種。

在片元着色器中寫入片元深度值會導致 GPU 的深度檢測被禁用。而在 Cesium 中是不可能的,因為存在一種情況:可能存在覆蓋屏幕但是不靠近相機的三角形,例如覆蓋整個陸地的超大多邊形。所以,瀏覽器得支持 EXT_frag_depth 這個 WebGL 擴展,才能在片元着色器中寫入片元深度,才能利用這個功能,否則 Cesium 仍會使用舊的多視錐體技術。

雖然 Cesium 中的大多數視圖僅需要一個單個對數深度的視錐,但是也有例外。一個極端的例子是,在非常遙遠的距離觀察一個很大的三角面。

下例是一個極端情況,即這里有兩個超級大平面,和地球切面差不多,它們尺寸是一樣的,但是空間距離上只差 300 米,但是相機到觀察目標的距離有 6400w 米。

對於上面的視圖,可以預見,幾何圖形在三角面距離比較遠時仍然可見(例如行星)。三角面比較靠近的,則看不到,例如衛星。為了解決這個問題,Cesium使用了一種混合技術,在多個視錐體中,每個視錐都使用對數深度緩存。減小 Scene.logarithmicDepthFarToNearRatio 的值,就會增加視錐體的個數,然后減少z值沖突。

*譯者注

簡而言之,配合對數深度緩存技術和原來的多視錐體技術的靈活搭配使用,減少 drawcall,提升性能,提升顯示效果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM