Sign up for free to use this document yourself.
  • Hierarchical LOD, Batching, and Culling

  • Hierarchical LOD notes on implementation:

    • Bounding volume hierarchy (BVH) for frustum culling and LOD among homogenous 3D objects’ AABBs. (conservative largest possible AABB across all LODs)
    • 3D Objects contain their own object LOD levels (ie. different mesh variation model file for each LOD) including billboard images to use for y(vertical-axis)-locked sprites.
    • Set min bounding size for BVH AABB’s for checking and processing LODs at respective hierarchical LOD levels. This setting used for frustum culling might differ from the one in LOD processing. This ensures frustum culling/LOD processing need not drill down to individual 3D objects, but bunches of them given a min-bounding size threshold. For frustum culling, this would obviously affect number of draw calls, since not all trees need to be culled individually.
    • LOD selection is determined via a simple distance threshold checks to AABBs of respective object hierarchical LOD groups. When camera is outside of the hierarchical group’s AABB, instead of Euclidean distance towards AABB, a naive Max(dispX,dispY,dispZ) towards AABB distance check is used instead, where the distances are simply measured on each dimension alone (towards the closer x/y/z plane bound of the AABB) and the highest distance difference value is picked among them. If max picked distance passes the threshold, the next hierarchical LOD level is considered.
    • For any lowest LOD that displays billboard image, distance check avoids measuring distance along vertical (eg. y) axis distance since billboards always face towards the (eg, x/z) axes of the world and thus only those distances are relevant. This prevents “low altitude” objects “far below” (ie. lie close to 90 degrees vertically below the camera) from rendering as billboards that will be thinly visible in such cases.
    • All frustum culling is built to handle culling hierarchically via plane masking technique (integer bitwise operators are typically used for this to track which frustum planes still need/no longer need testing). https://cesium.com/blog/2015/08/04/fast-hierarchical-culling/
    • All 3D objects at each LOD (being homogenous model at each LOD) are handled via a “dynamic batching repeater” each containing a single linear geometry typed array buffer (of float value object transforms). When it comes to visibility frustum culling and swapping objects in/out of given LOD buffers, numbers are simply moved in/out of the array (at “last index” and/or “target array” index) while adjusting an internal len length variable value of each buffer to limit the number of triangles to draw along the linear buffer depending on how many objects are visible at a given LOD , thus the array buffer size is kept constant and only expanded if needed be. (eg. https://superfunc.github.io/posts/lua-performance-musings-1/ but without Step 1b to keep actual memory array size the same)
    • Frame coherent dirty checking (with timestamp counter variable) between previous/current frames to only determine exact specific LOD hierarchical groups of objects that would need adjustments in visibilities / LOD swapping among the buffers between previous to current frame.
  • https://www.youtube.com/watch?v=JNzKHp3fPh4

    Detailed Tech feature notes on implementation:

    • Bounding volume hierarchy (BVH) for frustum culling and LOD among homogenous 3D objects’ AABBs
    • 3D Objects contain their own object LOD levels (ie. different mesh variation model file for each LOD) including billboard images to use for y(vertical-axis)-locked sprites.
    • Set min bounding size for BVH AABB’s for checking and processing LODs at respective hierarchical LOD levels. This setting used for frustum culling might differ from the one in LOD processing. This ensures frustum culling/LOD processing need not drill down to individual 3D objects, but bunches of them given a min-bounding size threshold. For frustum culling, this would obviously affect number of draw calls, since not all trees need to be culled individually.
    • LOD selection is determined via a simple distance threshold checks to AABBs of respective object hierarchical LOD groups. When camera is outside of the hierarchical group’s AABB, instead of Euclidean distance towards AABB, a naive Max(dispX,dispY,dispZ) towards AABB distance check is used instead, where the distances are simply measured on each dimension alone (towards the closer x/y/z plane bound of the AABB) and the highest distance difference value is picked among them. If max picked distance passes the threshold, the next hierarchical LOD level is considered.
    • For any lowest LOD that displays billboard image, distance check avoids measuring distance along vertical (eg. y) axis distance since billboards always face towards the (eg, x/z) axes of the world and thus only those distances are relevant. This prevents “low altitude” objects “far below” (ie. lie close to 90 degrees vertically below the camera) from rendering as billboards that will be thinly visible in such cases.
    • All frustum culling is built to handle culling hierarchically via plane masking technique (integer bitwise operators are typically used for this to track which frustum planes still need/no longer need testing). https://cesium.com/blog/2015/08/04/fast-hierarchical-culling/
    • All 3D objects at each LOD (being homogenous model at each LOD) are handled via a “dynamic batching repeater” each containing a single linear geometry typed array buffer (of float value object transforms). When it comes to visibility frustum culling and swapping objects in/out of given LOD buffers, numbers are simply moved in/out of the array (at “last index” and/or “target array” index) while adjusting an internal len length variable value of each buffer to limit the number of triangles to draw along the linear buffer depending on how many objects are visible at a given LOD , thus the array buffer size is kept constant and only expanded if needed be. (eg. https://superfunc.github.io/posts/lua-performance-musings-1/ but without Step 1b to keep actual memory array size the same)
    • Frame coherent dirty checking (with timestamp counter variable) between previous/current frames to only determine exact specific LOD hierarchical groups of objects that would need adjustments in visibilities / LOD swapping among the buffers between previous to current frame.
{"cards":[{"_id":"3f49ba1d9687ee7906000069","treeId":"3f49ba309687ee7906000067","seq":22125724,"position":1,"parentId":null,"content":"## Hierarchical LOD, Batching, and Culling"},{"_id":"3f49b99d9687ee790600006a","treeId":"3f49ba309687ee7906000067","seq":22126734,"position":1,"parentId":"3f49ba1d9687ee7906000069","content":"https://www.youtube.com/watch?v=JNzKHp3fPh4\n\n### Detailed Tech feature notes on implementation:\n\n- Bounding volume hierarchy (BVH) for frustum culling and LOD among homogenous 3D objects' AABBs \n- 3D Objects contain their own object LOD levels (ie. different mesh variation model file for each LOD) including billboard images to use for y(vertical-axis)-locked sprites.\n- Set min bounding size for BVH AABB's for checking and processing LODs at respective hierarchical LOD levels. This setting used for frustum culling might differ from the one in LOD processing. This ensures frustum culling/LOD processing need not drill down to individual 3D objects, but bunches of them given a min-bounding size threshold. For frustum culling, this would obviously affect number of draw calls, since not all trees need to be culled individually.\n- LOD selection is determined via a simple distance threshold checks to AABBs of respective object hierarchical LOD groups. When camera is outside of the hierarchical group's AABB, instead of Euclidean distance towards AABB, a naive Max(dispX,dispY,dispZ) towards AABB distance check is used instead, where the distances are simply measured on each dimension alone (towards the closer x/y/z plane bound of the AABB) and the highest distance difference value is picked among them. If max picked distance passes the threshold, the next hierarchical LOD level is considered.\n- For any lowest LOD that displays billboard image, distance check avoids measuring distance along vertical (eg. y) axis distance since billboards always face towards the (eg, x/z) axes of the world and thus only those distances are relevant. This prevents \"low altitude\" objects \"far below\" (ie. lie close to 90 degrees vertically below the camera) from rendering as billboards that will be thinly visible in such cases.\n- All frustum culling is built to handle culling hierarchically via plane masking technique (integer bitwise operators are typically used for this to track which frustum planes still need/no longer need testing). https://cesium.com/blog/2015/08/04/fast-hierarchical-culling/\n- All 3D objects at each LOD (being homogenous model at each LOD) are handled via a \"dynamic batching repeater\" each containing a single linear geometry typed array buffer (of float value object transforms). When it comes to visibility frustum culling and swapping objects in/out of given LOD buffers, numbers are simply moved in/out of the array (at \"last index\" and/or \"target array\" index) while adjusting an internal `len` length variable value of each buffer to limit the number of triangles to draw along the linear buffer depending on how many objects are visible at a given LOD , thus the array buffer size is kept constant and only expanded if needed be. (eg. https://superfunc.github.io/posts/lua-performance-musings-1/ but without Step 1b to keep actual memory array size the same)\n- Frame coherent dirty checking (with timestamp counter variable) between previous/current frames to only determine exact specific LOD hierarchical groups of objects that would need adjustments in visibilities / LOD swapping among the buffers between previous to current frame."},{"_id":"3f1c2b49f32537636a00007b","treeId":"3f49ba309687ee7906000067","seq":22142666,"position":2,"parentId":null,"content":"## Hierarchical LOD notes on implementation:\n\n- Bounding volume hierarchy (BVH) for frustum culling and LOD among homogenous 3D objects' AABBs. (conservative largest possible AABB across all LODs)\n- 3D Objects contain their own object LOD levels (ie. different mesh variation model file for each LOD) including billboard images to use for y(vertical-axis)-locked sprites.\n- Set min bounding size for BVH AABB's for checking and processing LODs at respective hierarchical LOD levels. This setting used for frustum culling might differ from the one in LOD processing. This ensures frustum culling/LOD processing need not drill down to individual 3D objects, but bunches of them given a min-bounding size threshold. For frustum culling, this would obviously affect number of draw calls, since not all trees need to be culled individually.\n- LOD selection is determined via a simple distance threshold checks to AABBs of respective object hierarchical LOD groups. When camera is outside of the hierarchical group's AABB, instead of Euclidean distance towards AABB, a naive Max(dispX,dispY,dispZ) towards AABB distance check is used instead, where the distances are simply measured on each dimension alone (towards the closer x/y/z plane bound of the AABB) and the highest distance difference value is picked among them. If max picked distance passes the threshold, the next hierarchical LOD level is considered.\n- For any lowest LOD that displays billboard image, distance check avoids measuring distance along vertical (eg. y) axis distance since billboards always face towards the (eg, x/z) axes of the world and thus only those distances are relevant. This prevents \"low altitude\" objects \"far below\" (ie. lie close to 90 degrees vertically below the camera) from rendering as billboards that will be thinly visible in such cases.\n- All frustum culling is built to handle culling hierarchically via plane masking technique (integer bitwise operators are typically used for this to track which frustum planes still need/no longer need testing). https://cesium.com/blog/2015/08/04/fast-hierarchical-culling/\n- All 3D objects at each LOD (being homogenous model at each LOD) are handled via a \"dynamic batching repeater\" each containing a single linear geometry typed array buffer (of float value object transforms). When it comes to visibility frustum culling and swapping objects in/out of given LOD buffers, numbers are simply moved in/out of the array (at \"last index\" and/or \"target array\" index) while adjusting an internal `len` length variable value of each buffer to limit the number of triangles to draw along the linear buffer depending on how many objects are visible at a given LOD , thus the array buffer size is kept constant and only expanded if needed be. (eg. https://superfunc.github.io/posts/lua-performance-musings-1/ but without Step 1b to keep actual memory array size the same)\n- Frame coherent dirty checking (with timestamp counter variable) between previous/current frames to only determine exact specific LOD hierarchical groups of objects that would need adjustments in visibilities / LOD swapping among the buffers between previous to current frame."}],"tree":{"_id":"3f49ba309687ee7906000067","name":"Hierarchical LOD, Batching, and Culling","publicUrl":"hierarchical-lod-batching-and-culling"}}