Capítulo 820 de 859

Chapter 820: How to Update Things (Manual)

Core Idea

Rules for updating three.js objects after their first render: matrices update automatically by default, BufferGeometry buffers can't be resized (only pre-allocated and partially drawn), and different material/texture/camera changes have different runtime costs.

Key Concepts

  • Automatic matrix updates: objects added to the scene recompute their transform matrix automatically; static objects can opt out and update manually for a small performance win.
  • Buffers can't be resized: a BufferGeometry attribute's underlying typed array is fixed size once created — growing it requires allocating a new, larger buffer (as costly as a new geometry).
  • BufferGeometry.setDrawRange(): lets you pre-allocate a large buffer (e.g. for 500 vertices) but draw only a subset, so the visible vertex count can grow without resizing anything.
  • attribute.needsUpdate = true: required after changing buffer contents (position, color, etc.) so three.js re-uploads the data; may also require recomputing bounding volumes.
  • Uniforms and GL state are free to change: colors, textures, opacity, depthTest, blending, etc. can change every frame at no special cost.
  • Some material properties require a new shader: changing things like flatShading or adding/removing per-pixel features forces a shader recompile the first time they're used after the change, which can cause a frame hitch.
  • texture.needsUpdate = true: required for image/canvas/video/data textures whose source content changed; render targets update automatically.
  • Camera changes: position/target update automatically, but changing fov, aspect, near, or far requires calling camera.updateProjectionMatrix().
  • InstancedMesh / SkinnedMesh bounding volumes: these classes keep their own boundingBox/boundingSphere (superseding the geometry-level ones) and must be recomputed whenever instance transforms or bone poses change.

Code Examples

const MAX_POINTS = 500;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(MAX_POINTS * 3);
geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
geometry.setDrawRange(0, 2); // draw only the first 2 points initially

const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
const line = new THREE.Line(geometry, material);
scene.add(line);
  • What it demonstrates: pre-allocating buffer space for a line that grows at render time by increasing the draw range instead of resizing the buffer.

Key Takeaways

  1. BufferGeometry attribute buffers have a fixed size; pre-allocate for the maximum you'll need and use setDrawRange() to control how much is actually drawn.
  2. After changing buffer contents, set attribute.needsUpdate = true and, if positions changed, consider recomputing bounding volumes.
  3. Uniforms and GL state changes are cheap every frame; changes that force a shader recompile are not and can cause jerkiness.
  4. Camera fov/aspect/near/far changes require an explicit camera.updateProjectionMatrix() call.
  5. InstancedMesh and SkinnedMesh maintain their own bounding volumes that must be recomputed after transforming instances or animating bones.

Connects To

  • BufferGeometry: the core data structure this chapter's update rules apply to.
  • InstancedMesh / SkinnedMesh: both need explicit bounding-volume recomputation after their data changes.