Overview
TheGLBTreeBatchedInstancer module provides BatchedMesh-based rendering for multi-variant trees with minimal draw calls.
Source:
packages/shared/src/systems/shared/world/GLBTreeBatchedInstancer.tsAdded in commits 82a5365 and 6c14c8e (March 12, 2026).Initialization
initGLBTreeBatchedInstancer
scene- Three.js scene for adding BatchedMesh instancesworld- World instance for material setup
destroyGLBTreeBatchedInstancer
Instance Management
addInstance
treeType- Tree type identifier (e.g., “oak”, “birch”)variantPaths- Array of model paths for variants (e.g., [“oak_1.glb”, “oak_2.glb”])variantIndex- Index of variant to use (0-based)entityId- Unique entity IDposition- World position (THREE.Vector3)rotation- Y-axis rotation in radiansscale- Uniform scale multiplierdepletedModelPath- Optional path to depleted model (stump)depletedScale- Optional scale for depleted model
Promise<boolean> - true if successful, false if failed
Example:
removeInstance
entityId- Entity ID of tree to remove
State Management
setDepleted
entityId- Entity ID of treedepleted-trueto show stump,falseto show normal tree
- Removes instance from current LOD pool
- Adds instance to depleted pool (or normal pool)
- Uses
depletedScalefor stump size - Preserves position and rotation
setHighlight
entityId- Entity ID of treeon-trueto highlight,falseto remove highlight
- Only one tree can be highlighted at a time
- Automatically removes previous highlight when highlighting new tree
- Highlight persists across LOD transitions
clearHighlight
Utility Functions
hasInstance
entityId- Entity ID to check
true if instance exists, false otherwise
Example:
hasDepleted
entityId- Entity ID to check
true if depleted model available, false otherwise
Example:
getModelDimensions
entityId- Entity ID to query
height and radius in meters, or null if not found
Example:
Update Loop
updateGLBTreeBatchedInstancer
- Switches LOD levels based on camera distance
- Updates dissolve uniforms (camera pos, player pos, sun direction, wind)
- Preserves highlight state across LOD transitions
- Uses hysteresis (0.81x) to prevent flickering
Constants
MAX_INSTANCES
- Limit instance count per tree type to 512
- Split into multiple tree types if needed
- Prevents BatchedMesh overflow
Type Definitions
TreeSlot
BatchedLODPool
TreeTypePool
Error Handling
Model Load Failures
- Model file not found
- Invalid model format
- Texture loading failure
- Out of memory
Variant Matching Failures
- Variants have different numbers of meshes
- Material slot order differs between variants
- Texture dimensions don’t match
Best Practices
Use consistent material slots
Use consistent material slots
Ensure all variants have materials in the same order (bark first, leaves second). This allows texture fingerprinting to work correctly.
Provide depleted models
Provide depleted models
Always provide a depleted model (stump) for harvestable trees. This improves visual feedback when trees are chopped.
Use LOD models
Use LOD models
Provide LOD1 and LOD2 models for better performance at distance. Use
inferLOD1Path() and inferLOD2Path() naming convention.Limit instance count
Limit instance count
Keep instance count below
MAX_INSTANCES (512) per tree type. Split into multiple tree types if needed.Call update every frame
Call update every frame
Call
updateGLBTreeBatchedInstancer() once per frame to update LOD levels and material uniforms.Related APIs
Terrain LOD API
TerrainQuadTree and TerrainQuadNode API
Biome API
BiomeType enum and tree configuration
Resource System
Resource spawning and gathering
GPU Materials
TSL-based materials with dissolve effects