LittleJS 1.30.0

Render3D

InstancedMesh3D

InstancedMesh3D - Many copies of one mesh drawn as one call, with their transforms kept on the GPU

  • For big sets that mostly stay put: an instance costs nothing per frame until it changes, so a hundred thousand trees cost what one tree does; objects and drawMesh batch by themselves too, but rebuild their batch every frame
  • setTransformAt, setMatrixAt and setColorAt change one instance, and only the changed range uploads before the next draw; the matrices and the colors are kept apart, so moving instances uploads 64 bytes each
  • For many instances moving every frame, setTransforms places a run of them from arrays of positions, rotations and scales in one loop, the fastest way; or write matrixData directly and call markDirtyRange
  • The instances are in world space; the object's own pos3D, rotation3D and scale3D do not move them
  • The whole set is culled by one bounding sphere around the origin, worked out when culling reads it, or set by hand with radius; it casts and receives shadows like any object
  • The object's flags cover the whole set, one emissive, one tileInfo, one shader; only the colors are per instance
  • A mirrored instance, one with a negative scale, shows its inside unless the mesh is doubleSided
  • A transparent set draws in one go in the transparent stage, its instances are not sorted against each other; the set sorts against other transparent draws by the object's position, so put pos3D at its middle
  • pick, the raycast and the collect helpers do not see the instances, test them yourself from matrixData

Extends EngineObject3D

Constructor

new InstancedMesh3D(mesh, count, tileInfo, color)render3dObject.js:1267

Create a set of instances of a mesh, each at the origin in the object's color until it is set

mesh Mesh
count number

How many instances there is room for, all of them draw until count is lowered

tileInfo TileInfo|TextureInfo optional

Texture for all of them

color Color optional

The color they start with

const forest = new InstancedMesh3D(treeMesh, 1000);
for (let i = 0; i < 1000; ++i)
    forest.setTransformAt(i, randomGroundPos(), vec3(0, rand(2*PI), 0));

Members

Methods

Inherited from EngineObject3D

Inherited from EngineObject

Members

colorBuffer : WebGLBuffer|undefinedrender3dObject.js:1317
colorData : Float32Arrayrender3dObject.js:1289

Each instance's color and uv rect, 8 floats, uploaded only when they change; edit it directly and call markColorDirty for the instances changed

colorDirtyEnd : numberrender3dObject.js:1297

One past the last instance whose color uploads

colorDirtyStart : numberrender3dObject.js:1295

First instance whose color uploads before the next draw

How many instances draw, the first ones, up to the count it was made with

dataBuffer : WebGLBuffer|undefinedrender3dObject.js:1306
dataValues : Float32Array|undefinedrender3dObject.js:1302

Each instance's data, 4 floats, made by the first setDataAt: what a Shader's snippets read as vec4 instanceData; edit it directly and call markDataDirty for the instances changed

dirtyEnd : numberrender3dObject.js:1293

One past the last instance whose matrix uploads, nothing when it is not past dirtyStart

dirtyStart : numberrender3dObject.js:1291

First instance whose matrix uploads before the next draw

fixedRadius : number|undefinedrender3dObject.js:1314
matrixData : Float32Arrayrender3dObject.js:1286

Each instance's matrix, 16 floats, what moving them uploads; edit it directly and call markDirty for the instances changed

maxCount : numberrender3dObject.js:1283

How many instances it was made with

radius : numberrender3dObject.js:1490

Radius of the sphere around the origin that holds every instance set so far, for culling: the farthest instance, and the mesh's size at the largest scale; it only grows, and takes in the instances set since it was last read, so with frustum culling off it is never worked out. Set it to fix the sphere, which a big set that is culled can use to skip that work, and set it to undefined to go back to the bounds

Methods

destroy(immediate)render3dObject.js:1588

Destroy the set and free its GPU buffer

immediate boolean optional

The matrix of an instance

i number
markColorDirty(i)render3dObject.js:1479

Note that an instance's color changed, so it uploads before the next draw; setColorAt calls this, and so must an edit made straight to colorData

i number
markDataDirty(start, end)render3dObject.js:1444

Note that a run of instances' data changed, for code that writes dataValues directly; setDataAt calls this

start number

First instance

end number optional

One past the last

Note that an instance's matrix changed, so it uploads before the next draw and the bounds take it in when they are read; setTransformAt and setMatrixAt call this, and so must an edit made straight to matrixData

i number
markDirtyRange(start, end)render3dObject.js:1467

Note that a run of instances' matrices changed, for code that writes matrixData directly, the lowest level way to move many: they upload before the next draw and the bounds take them in when they are read

start number

First instance

end number

One past the last

render3D() → voidrender3dObject.js:1515

Draws every instance as one call, uploading the ones that changed first

setColorAt(i, color)render3dObject.js:1416

Color an instance

i number
color Color
setDataAt(i, x, y, z, w)render3dObject.js:1433

Give an instance four numbers of the game's own, which a Shader's snippets read as vec4 instanceData, in the vertex code and the fragment code, the shadow map too, like a tile's height or a sprite's foot line; an instance not given any reads zeros, and so does every draw that is not of a set with data

i number
x number optional, default 0
y number optional, default 0
z number optional, default 0
w number optional, default 0
setMatrixAt(i, matrix)render3dObject.js:1393

Place an instance, in world space

i number
matrix Matrix4
setTransformAt(i, pos, rotation, scale)render3dObject.js:1336

Place an instance by its position, rotation and scale, what buildMatrix takes, written straight in with no matrix made; in world space

i number
pos Vector3 optional
rotation Vector3 optional

Euler angles in radians

scale Vector3 optional
setTransforms(start, count, x, y, z, rx, ry, rz, sx, sy, sz)render3dObject.js:1357

Place a run of instances from arrays indexed by instance, plain or typed, as a game keeps them: each is placed as setTransformAt places it, all in one loop with nothing made, the fastest way to move many every frame; in world space

start number

First instance

count number

How many

x ArrayLike<number>

Positions

y ArrayLike<number>
z ArrayLike<number>
rx ArrayLike<number> optional

Euler angles in radians, all three or none for upright

ry ArrayLike<number> optional
rz ArrayLike<number> optional
sx ArrayLike<number> optional

Scales, all three or none for 1

sy ArrayLike<number> optional
sz ArrayLike<number> optional