Build a box centered on the origin, six flat faces with uvs covering each face
- bevel cuts its edges and corners: 1 segment is a flat chamfer, more round them, and the biggest bevel, half
the smallest side, rounds a cube into a ball
size Vector3|number optional, default 1Full size, a number for a cube
bevel number optional, default 0Size of the cut on each edge, clamped to half the smallest side
bevelSegments number optional, default 1Steps around each edge, 1 for a flat chamfer
Build a capsule standing on the Y axis, centered on the origin: a cylinder with a half sphere on each end
size number optional, default 1Diameter
height number optional, default 1Total height including the rounded ends, at least the size
sides number optional, default 16Around
rings number optional, default 4On each end
smooth boolean optionalDefaults to render3D.smoothShading
Build a cone standing on the Y axis, centered on the origin, the point up
size number optional, default 1Diameter of the base
height number optional, default 1sides number optional, default 16Around
smooth boolean optionalDefaults to render3D.smoothShading
capped boolean optional, default trueClose the base
bevel number optional, default 0Size of the cut on the base rim, clamped to the radius and half the slanted side
bevelSegments number optional, default 1Steps around the rim, 1 for a flat chamfer
Build a cylinder standing on the Y axis, centered on the origin
size number optional, default 1Diameter
height number optional, default 1sides number optional, default 16Around
smooth boolean optionalDefaults to render3D.smoothShading
capped boolean optional, default trueClose the ends
bevel number optional, default 0Size of the cut on the top and bottom rims, clamped to the radius and half the height
bevelSegments number optional, default 1Steps around each rim, 1 for a flat chamfer
Turn a sprite into a 3D block model by giving its pixels thickness
- A pixel counts as solid when it is more than half opaque
- Each pixel keeps its own color, so white art takes the object's tint
- Runs of matching pixels merge into one face, and side walls appear only at the sprite's edges
- A texture's pixels are read once and kept, so redrawing a canvas texture will not change what this builds
- Pixels can also be an array of rows, each a Color, a truthy value for white, or a falsy value for empty
pixels TileInfo|Array<Array<(Color|number|boolean)>>A tile from a loaded texture, or rows of pixels,
each a Color (empty when see through), a truthy value for white or a falsy value for empty
size Vector2 optionalWorld width and height of the whole tile, centered like buildBox
depth number optional, default 1Thickness along Z
new EngineObject3D(vec3(), buildExtrude(tile(3, 16), vec2(2), .5)); // a chunky version of tile 3
Build a heightfield grid in the XZ plane centered on the origin
- smooth rounds the lighting across cells and colors each corner
- flat lights and colors each cell on its own, so a checkerboard stays crisp
- doubleSided, a sheet seen from both sides; turn it off for ground only ever seen from above
- One cell is a plain square, render3D.planeMesh and planeMeshDoubleSided are shared ones
size Vector2|number optionalWorld size along X and Z, a number for a square
segments Vector2|number optional, default 1Cells along X and Z, a number for both
color Color|function optionalOne Color for the whole grid, or (x, z) => Color
heightFunction function optional(x, z) => y, default flat
smooth boolean optionalDefaults to render3D.smoothShading with a heightFunction; a flat grid is flat shaded,
since its light is even anyway and smoothing would only blend its cell colors; pass smooth to blend a gradient
const ground = buildGrid(vec2(20), 10, (x, z)=> (floor(x / 2) + floor(z / 2)) & 1 ? GRAY : WHITE); // 2 unit checks
Spin a flat outline around the Y axis to make a round shape, like a vase or a wheel
- profile is [[radius, y], ...] from bottom to top
- A profile that ends where it starts makes a closed ring like a donut
- An end left open, with a radius and no cap, makes the mesh doubleSided so its inside shows
- An end on the axis smooth shades as a round pole like a sphere's when its segment is within 45 degrees of
level, and as a point like a cone's tip when it is steeper
profile Array<Array<number>>sides number optional, default 16Around the axis
smooth boolean optionalDefaults to render3D.smoothShading
capped boolean optional, default trueClose the ends that have a radius with flat discs
const vase = buildLathe([[0, -1], [.8, -.3], [.9, .2], [.4, .6], [0, 1]], 12);
Build a hull from a row of diamond shaped slices along Z, for ships, planes and cars
- Each slice is [z, width, top, bottom, sideHeight]
- sideHeight is 0 to 1 and puts the side corners between the bottom and the top
- List the slices nose first, with the nose at the largest z
stations Array<Array<number>>
const hull = buildLoft([[1.2, .4, .2, -.1], [0, 1.4, .5, -.4], [-1, 1, .3, -.3]]);
Build a lit ribbon along a path, for roads, tracks and walls
- Each segment is a flat quad, the sides are across the path in the plane of the up vector
- doubleSided, so it is seen and lit from below as well
points Array<Vector3>Center line in order
width number|Array<number> optional, default 1Full width, one for all or one per point
color Color|Array<Color> optionalOne for all or one per point
closed boolean optional, default falseJoin the last point back to the first
up Vector3 optionalWhich way the ribbon faces
const road = buildRibbon(trackPoints, 8, GRAY, true); // a loop of road
Build a sky dome: a sphere colored by direction, wound to be seen from inside
- set it as render3D.sky and the pass draws it around the camera behind everything
topColor Color optionalStraight up
horizonColor Color optionalLevel with the camera
bottomColor Color optionalStraight down, what a camera looking at the ground sees past its edge; defaults to the
horizon color
sides number optional, default 16Around
rings number optional, default 8Top to bottom
Build a sphere centered on the origin
size number optional, default 1Diameter
sides number optional, default 16Around
rings number optional, default 8Top to bottom
smooth boolean optionalDefaults to render3D.smoothShading
Build a mesh of extruded text from an image font, the engine font by default so it needs no assets
- Each glyph is extruded once per font and reused, the block is centered and faces +Z
- Newlines stack downward, spaced a little wider than the character height so the sides do not collide
- Every call builds a new mesh, dispose the old one when text changes often
- Glyphs are white in the engine font, so the object's color tints the text
text string|numbersize number optional, default 1Character height in world units
depth number optional, default 0.2Thickness along Z
font ImageFont optionalDefaults to engineImageFont
new EngineObject3D(vec3(0, 2, 0), buildText3D('HELLO'), undefined, YELLOW);
Build a donut lying flat around the Y axis
size number optional, default 1Diameter of the whole donut, outside edge to outside edge
tubeSize number optional, default 0.3Diameter of the tube
sides number optional, default 16Around the ring
tubeSides number optional, default 8Around the tube
smooth boolean optionalDefaults to render3D.smoothShading
Draw a debug wireframe box
pos Vector3Center
size Vector3|number optional, default 1Full size, a number for a cube
color Color optionaltime number optional, default 0How long to show it, 0 is one frame
rotation Vector3 optionalvec3(pitch, yaw, roll)
Draw a debug point as a small cross of three lines
pos Vector3color Color optionaltime number optional, default 0How long to show it, 0 is one frame
size number optional, default 0.2Length of the cross
Draw a debug wireframe sphere as three rings
pos Vector3Center
size number optional, default 1Diameter
color Color optionaltime number optional, default 0How long to show it, 0 is one frame
Call a function for each EngineObject3D whose box overlaps a sphere or a box
- An object destroyed by an earlier callback is skipped
pos Vector3Center of the area
size Vector3|numberDiameter of a sphere if a number, 0 for a point, full size of a box if a Vector3
callback functionobjects Array<EngineObject> optionalDefaults to every object
testCenters boolean optional, default falseTest only each object's center, see engineObjectsCollect3D
Collect the EngineObject3D objects whose boxes overlap a sphere or a box, the 3D twin of engineObjectsCollect
- Each object is its size3D box at its world position, turned as it is turned; lights, emitters and trails have no
size and are never collected
pos Vector3Center of the area
size Vector3|numberDiameter of a sphere if a number, 0 for a point, full size of a box if a Vector3
objects Array<EngineObject> optionalDefaults to every object
testCenters boolean optional, default falseTest only each object's center, a little faster, and ignores object sizes
Collect every EngineObject3D a ray passes through, nearest first, the 3D twin of engineObjectsRaycast
- The ray has no end, so everything along it counts however far away it is
- Use render3D.pick for the nearest one on its own, with the distance to it
ray Ray3DFrom render3D.screenToRay, or any ray
objects Array<EngineObject> optionalDefaults to every object; only those with a mesh or a sprite count, and
the height maps, voxel maps and mesh colliders, on their surfaces
Load a cube map from six square images of one size
- The images are a sky box set as three.js's CubeTextureLoader takes them, and show the same: each face seen from
inside as its image is drawn
sources Array<string>The images of +x, -x, +y, -y, +z and -z, as a sky box set names them right,
left, top, bottom, front and back
Fetch and parse an OBJ file
url stringsmooth boolean optionalCompute smooth normals when the file has none, defaults to render3D.smoothShading
const mesh = await loadOBJ('ship.obj'); // in an async gameInit
Make a cube map by asking a function the color of each direction
- The function gets a unit Vector3 for each pixel of each face and gives a Color
- It runs size * size * 6 times, so a size of 64 or 128 makes one at once, larger takes a moment
size numberPixels a side of each face
colorOf functionThe color seen looking that way
// a sky, blue above and pale at the horizon, with a sun
const sun = vec3(1, 1, -1).normalize();
render3D.environment = makeCubeMap(64, (d)=> hsl(.6, .7, .9 - max(d.y, 0) * .5).lerp(WHITE, max(0, d.dot(sun)) ** 64));
meshWriteVertex(floats, ints, j, x, y, z, nx, ny, nz, u, v, rgba)render3dMesh.js:48Write one vertex in the GPU layout, RENDER3D_VERTEX_FLOATS floats, for vertex data given to mesh.setVertexData:
its place, its normal, its uv and its color as RGBA bytes, in numbers so a loop over many makes no objects
floats Float32ArrayThe vertex data
ints Uint32ArrayA view of the same buffer, for the color
j numberThe vertex's first float, its number times RENDER3D_VERTEX_FLOATS
x numbery numberz numbernx numberThe normal, unit length
ny numbernz numberu numberAcross the tile, 0 to 1
v numberDown the tile, 0 to 1
rgba numberThe color as color.rgbaInt() gives it
Make a normal map from a height at each pixel, for bumps and grooves with no image file: the slope at each pixel
from its neighbors' heights, taken around the edges so the map tiles; set it as an object's normalMap
size Vector2In pixels
heightFunction functionThe height 0 to 1 at a pixel, x across and y down
strength number optional, default 1How steep the slopes are: a height change of 1 over one pixel leans the normal
by strength
- Returns
- Wraps; headless it has no image
Parse Wavefront OBJ text into a Mesh
- Reads v, vt, vn and f lines with convex polygons of any size, materials and groups are ignored
- Normals come from the file when every corner of a face has one, otherwise from the face
- Use mesh.center() and mesh.fit(size) to bring a model of unknown units to the origin
- Back faces are skipped like any mesh, set doubleSided for a model with open walls or single sided parts
text stringsmooth boolean optionalCompute smooth normals for the faces the file gives none, defaults to render3D.smoothShading
new EngineObject3D(vec3(), parseOBJ(objText).center().fit(4));
Global Render3D plugin object
Floats in each vertex of the GPU layout: position xyz, normal xyz, uv, and the color as rgba bytes in the last
one, what meshWriteVertex writes and mesh.setVertexData takes
A particle as a ParticleEmitter3D's callbacks see it: one object the emitter reuses, set from the particle for each
call and written back after it, so copy what you keep
emitter ParticleEmitter3DThe emitter it is in
pos Vector3Where it is, change it to move it
velocity Vector3How far it moves each frame
age numberSeconds it has lived
lifeTime numberSeconds it lives
scale numberHow much the emitter grows its effect, from its scale3D and its parents', as the 2D
particle's scale
destroyed booleanSet by destroy
destroy functionEnd it this update, the destroy callback gets it
The draw state's values, behind render3D's accessors, and the rgb emissiveMapColor had when it was set
blend booleanadditive booleandepthTest booleandepthWrite booleancullBackFaces booleanmirrored booleanlighting booleanemissive numberreceiveShadow booleanspecular numberpixelated booleanshader Shader|undefinednormalMap TextureInfo|undefinednormalScale numbershininess numberreflectivity numberemissiveMap TextureInfo|undefinedemissiveMapColor ColorenvironmentMap CubeMap|undefinedroundLighting booleanemissiveR numberemissiveG numberemissiveB number
What VoxelMap.raycast finds: how far along the ray, the block's cell and type, and the normal of the face it comes in
through