ThreeJS Updating Things

If an item has been added to the scene with the specified code, it will immediately update its matrices.

const object = new THREE.Object3D();
scene.add( object );

or, if they are the child of another object that has been added to the scene:

const object1 = new THREE.Object3D();
const object2 = new THREE.Object3D();


object1.add( object2 );
scene.add( object1 ); //object1 and object2 will automatically update their matrices

If you know the item will be static, though, you can disable this and manually update the transform matrix as needed.

object.matrixAutoUpdate  = false;
object.updateMatrix();

BufferGeometry

BufferGeometries use typed arrays to store data (such as vertex coordinates, face indices, normals, colours, UVs, and any custom properties). This makes them speedier than regular Geometries, but they're also a little more difficult to work with.

The most important thing to remember about changing BufferGeometries is that buffers cannot be resized (this is very costly, basically the equivalent to creating a new geometry). Buffers, on the other hand, can be updated.

This means that if you know an attribute of your BufferGeometry will grow, such as the number of vertices, you must pre-allocate a buffer large enough to accommodate any newly produced vertices. Of course, this means that your BufferGeometry will have a maximum size - there is no way to design a BufferGeometry that can be expanded indefinitely.

We'll use the example of a rendered line that gets stretched. Using BufferGeometry, we'll allocate room in the buffer for 500 vertices but only render two at initially. drawRange.

const MAX_POINTS = 500;


// geometry
const geometry = new THREE.BufferGeometry();


// attributes
const positions = new Float32Array( MAX_POINTS * 3 ); // 3 vertices per point
geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );


// draw range
const drawCount = 2; // draw the first 2 points, only
geometry.setDrawRange( 0, drawCount );


// material
const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );


// line
const line = new THREE.Line( geometry,  material );
scene.add( line );

Next, we'll randomly add points to the line using a pattern like:

const positions = line.geometry.attributes.position.array;


let x, y, z, index;
x = y = z = index = 0;


for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) {


    positions[ index ++ ] = x;
    positions[ index ++ ] = y;
    positions[ index ++ ] = z;


    x += ( Math.random() - 0.5 ) * 30;
    y += ( Math.random() - 0.5 ) * 30;
    z += ( Math.random() - 0.5 ) * 30;


}

After the first render, you can alter the number of points rendered by doing the following:

line.geometry.setDrawRange( 0, newValue );

If you want to update the values of the location data after the first render, set the needsUpdate flag as follows:

line.geometry.attributes.position.needsUpdate = true; // required after the first render

If the position data values change after the initial render, you may need to recompute bounding volumes in order for additional engine functions like view frustum culling or helpers to work properly.

line.geometry.computeBoundingBox();
line.geometry.computeBoundingSphere();

Materials

All uniform values (colours, textures, opacity, etc.) can be altered at any time, and values are given to the shader every frame.

GLstate-related characteristics may also change at any time (depthTest, blending, polygonOffset, etc).

At runtime (after the material has been rendered at least once), the following properties are not easily changed:

  • numbers and types of uniforms
  • presence or not of
    • texture
    • fog
    • vertex colors
    • morphing
    • shadow map
    • alpha test

Changes in these require building of new shader program. You'll need to set

material.needsUpdate = true

Keep in mind that this could be quite sluggish and cause framerate jerkiness (especially on Windows, as shader compilation is slower in DirectX than OpenGL).

You can simulate changes in these elements to some extent by using "dummy" variables such as zero intensity lighting, white texturing, or zero density fog for a smoother experience.

You can alter the material used for geometry chunks at any time, but you can't modify how an object is broken down into chunks (according to face materials).

If you need to have different configurations of materials during runtime:

If the object has a small number of materials/chunks, you can pre-divide it (for example, hair, face, torso, upper garments, and trousers for a human, front, sides, top, glass, tyre, and inside for an automobile).

Consider a different method, such as leveraging attributes/textures to drive diverse per-face looks, if the number is significant (e.g. each face might be possibly different).

Textures

Image, canvas, video, and data textures need to have the following flag set if they are changed:

texture.needsUpdate = true;

Render targets update automatically.

Cameras

A camera's position and target is updated automatically. If you need to change

  • fov
  • aspect
  • near
  • far

then, you'll need to recompute the projection matrix:

camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();