three.js使用Instanced Draw+Frustum Cull+LOD來渲染大場景(開源)

大家好,本文使用three.js實現了渲染大場景,在移動端也有較好的性能,並給出了代碼,分析了關鍵點,感謝大家~

關鍵詞:three.js、Instanced Draw、大場景、LOD、Frustum Cull、優化、Web3D、WebGL、開源

代碼:Github

我正在承接Web3D數字孿生項目,具體介紹可看承接各種Web3D業務

加QQ羣交流:106047770

需求描述

數字孿生項目通常需要渲染超大場景,比如智慧城市就需要渲染一片城市區域,甚至整個城市

渲染大場景所需要的技術點包括:

  • Instanced Draw
    一個Draw Call批量渲染物體,物體可以有不同的Transform、Color
  • Frustum Cull
    剔除視椎體外的物體
  • Occlusion Cull
    剔除被遮擋的物體(WebGL1不支持)
  • LOD
    根據物體到相機的距離,顯示不同Level的物體。越遠的越粗糙,越近的越細緻
  • GPU Driven Pipeline
    把前幾個優化都放到GPU中來做,並且物體可以有更多差異(需要WebGPU)
  • Space Partition
    使用Octree、BVH、BSP等加速結構來劃分場景,在Cull、碰撞檢測、Ray Picking等操作時查詢加速結構而不是遍歷所有物體,從而提高性能
  • Multi Thread Render
    開一個渲染線程來渲染
  • AssetBundle、Stream Load
    劃分爲多個場景包,動態、流式加載

本文使用Instanced Draw+Frustum Cull+LOD來渲染大場景,最終實現效果演示:

image

場景總三角面數是千萬級,總物體數量是1萬(PC端)/5000(移動端),動態物體數量是800(PC端)/400(移動端)

其中,樹使用了Instanced Draw+LOD,白色立方體使用了Instanced Draw

可以把相機拉進、拉遠,可看到不同Level的樹

移動相機,可看到紅框內的Triangles在變化(大概在幾十萬到幾百萬),這是Frustum Cull後的三角面數

在5年前的中配手機上,FPS可達15左右

下面開始實現各個關鍵點,給出實現的思路:

Instanced Draw

比如要將克隆的1000個Mesh改爲Instanced的,則保留它們作爲source,並創建一個InstancedMesh,count設爲1000,寫入1000個Mesh的世界矩陣;然後隱藏source,顯示InstancedMesh
之所以保留source,是因爲可以用它們來做碰撞檢測、Ray Picking等單個Mesh的操作

值得注意的是物體可能是多材質的Object3D(如樹),所以要將其中的每個Mesh拆分到一組Instanced Draw中。舉例來說,如果樹有個3個材質(即3個子Mesh),則需要創建3個InstancedMesh,然後將所有樹的第一個材質的Mesh對應到第一個InstancedMesh中,其餘的以此類推

Frustum Cull

image

如上圖所示,實現Instanced Draw+Frustum Cull的原理是將要剔除的物體移到InstancedMesh的instanceMatrix的最後,並將count減1

值得注意的是要將three.js默認的對單個Object3D的frustum cull關閉(即將source的frustumCulled設爲false)

另外,我們直接遍歷所有的待剔除物體來進行Fustum Cull檢測,沒有使用Octree等加速結構
相關的討論請參考:Linear search vs Octree (Frustum cull)

LOD

image

如上圖所示,假設車有3個Level的LOD層級,我們希望離相機越遠,顯示越高的Level(Geometry、Material越簡單)

我們需要創建3個InstanceMesh,分別對應不同的Level,如下圖所示:
image

參考資料

InstancedMesh2 - Easy handling and frustum culling

What is a more straightforward way to do instance culling?

Linear search vs Octree (Frustum cull)

100kTrees

LOD + Instancing

LOD with Instancing and Multi-Material Meshes

Three.js InstancedMesh performance optimizations - DevLog 10

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章