How to update things

All objects by default automatically update their matrices if they have been added to the scene with

var object = new v3d.Object3D(); scene.add(object); or if they are the child of another object that has been added to the scene: var object1 = new v3d.Object3D(); var object2 = new v3d.Object3D(); object1.add(object2); scene.add(object1); //object1 and object2 will automatically update their matrices

However, if you know object will be static, you can disable this and update the transform matrix manually just when needed.

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

Geometries

BufferGeometry

BufferGeometries store information (such as vertex positions, face indices, normals, colors, UVs, and any custom attributes) in buffers - that is, typed arrays. This makes them generally faster than standard Geometries, at the cost of being somewhat harder to work with.

With regards to updating BufferGeometries, the most important thing to understand is that you cannot resize buffers (this is very costly, basically the equivalent to creating a new geometry). You can however update the content of buffers.

This means that if you know an attribute of your BufferGeometry will grow, say the number of vertices, you must pre-allocate a buffer large enough to hold any new vertices that may be created. Of course, this also means that there will be a maximum size for your BufferGeometry - there is no way to create a BufferGeometry that can efficiently be extended indefinitely.

We'll use the example of a line that gets extended at render time. We'll allocate space in the buffer for 500 vertices but draw only two at first, using BufferGeometry.drawRange.

var MAX_POINTS = 500; // geometry var geometry = new v3d.BufferGeometry(); // attributes var positions = new Float32Array(MAX_POINTS * 3); // 3 vertices per point geometry.addAttribute('position', new v3d.BufferAttribute(positions, 3)); // draw range var drawCount = 2; // draw the first 2 points, only geometry.setDrawRange(0, drawCount); // material var material = new v3d.LineBasicMaterial({ color: 0xff0000, linewidth: 2 }); // line var line = new v3d.Line(geometry, material); scene.add(line);

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

var positions = line.geometry.attributes.position.array; var x, y, z, index; x = y = z = index = 0; for (var 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; }

If you want to change the number of points rendered after the first render, do this:

line.geometry.setDrawRange(0, newValue);

If you want to change the position data values after the first render, you need to set the needsUpdate flag like so:

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

If you change the position data values after the initial render, you may need to call `.computeBoundingSphere()` in order to recalculate the geometry's bounding sphere.

line.geometry.computeBoundingSphere();

Here is a fiddle showing an animated line which you can adapt to your use case.

Examples:

WebGL / custom / attributes
WebGL / buffergeometry / custom / attributes / particles

Geometry

The following flags control updating of various geometry attributes. Set flags only for attributes that you need to update, updates are costly. Once buffers change, these flags reset automatically back to false. You need to keep setting them to true if you want to keep updating buffers. Note that this applies only to Geometry and not to BufferGeometry.

var geometry = new v3d.Geometry(); geometry.verticesNeedUpdate = true; geometry.elementsNeedUpdate = true; geometry.morphTargetsNeedUpdate = true; geometry.uvsNeedUpdate = true; geometry.normalsNeedUpdate = true; geometry.colorsNeedUpdate = true; geometry.tangentsNeedUpdate = true;

In versions prior to r66 meshes additionally need the dynamic flag enabled (to keep internal typed arrays):

//removed after r66 geometry.dynamic = true;

Examples:

WebGL / geometry / dynamic

Materials

All uniforms values can be changed freely (e.g. colors, textures, opacity, etc), values are sent to the shader every frame.

Also GLstate related parameters can change any time (depthTest, blending, polygonOffset, etc).

Flat / smooth shading is baked into normals. You need to reset normals buffer (see above).

The following properties can't be easily changed at runtime (once the material is rendered at least once):

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

material.needsUpdate = true

Bear in mind this might be quite slow and induce jerkiness in framerate (especially on Windows, as shader compilation is slower in DirectX than OpenGL).

For smoother experience you can emulate changes in these features to some degree by having "dummy" values like zero intensity lights, white textures, or zero density fog.

You can freely change the material used for geometry chunks, however you cannot change how an object is divided into chunks (according to face materials).

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

If the number of materials / chunks is small, you could pre-divide the object beforehand (e.g. hair / face / body / upper clothes / trousers for a human, front / sides / top / glass / tire / interior for a car).

If the number is large (e.g. each face could be potentially different), consider a different solution, such as using attributes / textures to drive different per-face look.

Examples:

WebGL / materials / cars
WebGL / webgl_postprocessing / dof

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.

Examples:

WebGL / materials / video
WebGL / rtt

Cameras

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

then you'll need to recompute the projection matrix:

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