A chunk-based quad tree terrain LOD engine (based off Thatcher Ulrich’s code and my own added stuff/implementations done back then in 2013 for Flash) which i’ve ported over to PlayCanvas. Currently can preview the LOD builds in effect in the PLAY preview. Apparently, my approach to the terrain LOD geometry turns out pretty similar to how Battlefield 2 does it as well:
http://www.dice.se/wp-content/uploads/2014/12/Chapter5-Andersson-Terrain_Rendering_in_Frostbite.pdf#page=15 based off Section 5.4 , which is basically a quad tree of 33x33 vertex chunk leafs and 9 permutation index buffers for stiching neighboring LOD levels between them.
Playcanvas project link
Features already integrated:
- Optimized Front to Back rendering order of quad tree terrain chunk nodes. (so it minimizes overdraw as well)
- Terrain LOD quad tree updates when camera changes position . (with adjustable ‘detail’ level setting)
- Highly performant hierachical Frustum culling for terrain chunks in the quad tree.
- Highly performant 100% accruate straight-line ray-casting within Quad Tree and DDA terrain chunk grid. (with nearest hit early out exit approach) . Suited for extremely long distance rays hit time detections.
(In the demo you can see the white box being traced over the terrain for camera’s center forward ray)
- Some splat mapping/terrain-texturing integrations.
- Highly performant basic ellipsoid character movement collision detection/clipping/movement on Quad Tree and terrain chunk grid using a cross-platform “basic player collision clipping to 3D environment” package. (note: unlike the raycaster, this is mainly optimized for short distanced movement per frame only)
On the roadmap are the following features to integrate properly into PlayCanvas’ 3D environment.
Features to integrate into Playcanvas:
- Highly performant 100% accruate trajectory (quadratic curve ) raycasting within Quad Tree and DDA terrain chunk grid. with nearest hit early out exit approach). Suited for extremely long distance trajectory hit time detections.
I use this to batch pre-calculate stopping locations for a shader (from another engine) that renders hundreds (or even thousands) of bullet-debris bounce-off particles (or archers’ arrows) that shoot them out across the terrain geometry (ie. the particles remain visibly resting on the ground terrain due to shader inputs)
On the roadmap for terrain engine / Playcanvas:
- Grid-based quadtree grid network to allow for infinitely larger environments.
- Streaming/loading/unloading of terrain LOD quadtree assets in quadtree grid network for even larger worlds to go along with LRU pooling approach instead of hard cache. (I already have doubly linked list of chunk states to facilitate this).
Could optimize (Playcanvas specific):
- Memory VRAM optimization…eg. How do i maintain and re-use/share the same index buffer per model chunk being created? Currently, it seems
pc.createMeshalways causes/requires a new index buffer to be created, which is not what i want!! (ie. how do i reuse an existing index buffer i have upon creating a new mesh?)
- Also, come up with support for Materials without requiring Tangents/Normals to be supplied, to save on VRAM vertex buffer usage.
- Also consider VTF instead of buffering/pooling vertex buffer chunks.
Rough Polycount stats:
- Medium sized terrain (512x512 tiles), can go up to around draw chunk calls around the 50-ish range at worse case (out of original 256 calls). (for around
32*32*2*50=102400triangles). Works great on mobile.
- Large sized terrain. (1024x1024 tiles). Also works great in performance draw counts at double only for worse case. Not too sure how it works on mobile because the current unoptimized vertex/index buffers approach to integrate conveniently to Playcanvas crashes browser on mobile atm though (eg. IOS, iphone 5/6, etc.). Anyway, 1024x1024 may be considered too unnecessarily big in some cases as well.
‘Good to have’ Future terrain texturing implementations/utility:
- Paint live-terrain-editing splatting utilities and saving
- Paint live-terrain-editing texture tiling (+ shader) and saving. (my own tile-based texture atlas shader)