Skip to main content

Model Cache Fixes (February 2026)

Overview

Two critical bugs in the IndexedDB processed model cache were fixed in February 2026. These bugs caused missing objects (altars, trees) and lost textures (white/wrong colors) after browser restarts. The fixes ensure reliable model caching without visual corruption.

Bug #1: Missing Objects

Symptoms

  • Objects disappear after browser restart (altars, trees, buildings)
  • Scene hierarchy incomplete
  • Console errors about missing meshes
  • Inconsistent object counts between sessions

Root Cause

The serializeNode() function used findIndex-by-name to map hierarchy nodes to mesh data:
Problem: Models with duplicate mesh names (common: "", "Cube", "Cube") all resolved to the same index. During deserialization, Three.js add() auto-removes objects from their previous parent, so only the last reference survived. Example Failure:

Fix

Use object-identity map instead of name-based lookup:
Result: All objects preserved correctly, regardless of duplicate names.

Bug #2: Lost Textures

Symptoms

  • White or grey materials after browser restart
  • Textures not loading
  • Correct geometry but wrong colors
  • Trees appear grey instead of green

Root Cause

Textures were serialized as ephemeral blob: URLs but never reloaded during deserialization:
Problem: Blob URLs are ephemeral and only valid during the current page session. After restart, the blob is gone and the texture fails to load.

Fix

Extract raw RGBA pixel data via canvas and restore as THREE.DataTexture:
Result: Textures persist correctly across browser restarts with no async loading race conditions.

Bug #3: Grey Tree Materials (WebGPU)

Symptoms

  • Trees appear grey in WebGPU renderer
  • Dissolve effect not working
  • instanceof MeshStandardMaterial check fails

Root Cause

The createDissolveMaterial() function used instanceof MeshStandardMaterial which fails for MeshStandardNodeMaterial in the WebGPU build:
Problem: ModelCache converts all materials to MeshStandardNodeMaterial for WebGPU compatibility, but they don’t pass instanceof MeshStandardMaterial checks.

Fix

Use duck-type property check instead of instanceof:
Result: Dissolve materials work correctly in both WebGL and WebGPU renderers.

Cache Version Bump

The PROCESSED_CACHE_VERSION was bumped from 2 to 3 to invalidate broken cache entries:
Effect: All users automatically rebuild their cache with the fixed serialization on first load after update.

Debugging Tools

Disable Cache

Bypass the cache entirely for debugging:
Use Cases:
  • Verify cache is causing the issue
  • Test model loading without cache
  • Force fresh model processing

Clear Cache

Delete the entire cache database:

Inspect Cache

View cached models:

Verify Texture Data

Check if textures are properly serialized:

Performance Impact

Cache Size

Before: ~2-5 MB per model (blob URLs + metadata) After: ~5-15 MB per model (raw RGBA pixels + metadata) Trade-off: Larger cache size for reliability and instant texture availability.

Load Time

Before:
  • Cache hit: 50-100ms (blob URL loading + async texture decode)
  • Cache miss: 500-2000ms (GLTF parse + texture load)
After:
  • Cache hit: 20-50ms (synchronous DataTexture creation)
  • Cache miss: 500-2000ms (unchanged)
Improvement: 50-80% faster cache hits, zero async loading race conditions.

Testing

Verify Fix

  1. Load a model with duplicate mesh names (e.g., altar, tree)
  2. Verify all objects are visible
  3. Reload page (cache hit)
  4. Verify all objects still visible
  5. Check textures are correct colors

Regression Test

Expected: All tests pass, no missing objects or white textures.

Rollback

If you encounter issues with the new cache:
Files Modified:
  • packages/shared/src/utils/rendering/ModelCache.ts - Core cache implementation
  • packages/shared/src/systems/shared/world/GPUVegetation.ts - Dissolve material fix
Cache Version History:
  • Version 1: Original implementation (pre-2025)
  • Version 2: Added collision data caching (2025)
  • Version 3: Fixed missing objects and texture persistence (February 2026)