Skip to content

feat: GPU instancing helper in @webgamekit/threejs #120

Description

@cnotv

Parent epic

#19

Problem

Scenes with many identical meshes (trees, rocks, particles, game tiles) currently create individual THREE.Mesh objects, resulting in one draw call per object. For 1 000+ objects this tanks performance. THREE.InstancedMesh can collapse them to a single draw call but its matrix API is verbose and error-prone.

Goal

A composable helper in packages/threejs/src/ that wraps InstancedMesh with a clean, functional API matching the project's existing patterns.

Plan

1. packages/threejs/src/instancing.ts

/**
 * Creates a managed InstancedMesh with helpers to set/update instance transforms.
 * @param geometry - shared BufferGeometry
 * @param material - shared Material
 * @param transforms - initial array of { position, rotation, scale } objects
 * @returns { mesh, updateInstance, resetInstances }
 */
export const createInstancedMesh = (
  geometry: THREE.BufferGeometry,
  material: THREE.Material,
  transforms: InstanceTransform[]
): InstancedMeshHandle => {  }
  • Internally uses a pre-allocated Matrix4 and Euler/Quaternion — no new in update path
  • updateInstance(index, transform) mutates the matrix at index and sets instanceMatrix.needsUpdate = true
  • resetInstances(transforms) bulk-updates all matrices

2. Export from packages/threejs/src/index.ts

3. Apply in at least one existing scene

  • Identify a view that renders many identical objects (e.g. ContinuousWorld tree population in area-population.ts)
  • Migrate from individual meshes to createInstancedMesh
  • Measure draw call reduction (before/after comment in PR)

4. Tests (packages/threejs/src/instancing.test.ts)

  • createInstancedMesh returns a mesh with correct count
  • updateInstance sets the matrix correctly at a given index
  • Pre-allocated scratch objects are not re-created across calls

Acceptance criteria

  • createInstancedMesh exported from @webgamekit/threejs
  • No new THREE.* in the update path
  • At least one scene migrated; draw calls visibly reduced in stats panel
  • Unit tests pass

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions