LittleJS 3D Rendering Plugin
- Adds a 3D scene that draws into the same WebGL canvas as the 2D game
- Call new Render3DPlugin() in gameInit, then move render3D.camera and make EngineObject3D objects
- EngineObject3D is an EngineObject with a 3D position, rotation and mesh
- The 3D scene draws under the 2D sprites, so HUD and text land on top
- Lighting is one directional light plus ambient, with optional extra lights, fog and shadows
- Build shapes with buildBox, buildSphere and friends, or load a model with loadOBJ
- Requires the Math3D plugin
- Source
Classes
Members
(static) render3D :Render3DPlugin
Global Render3D plugin object
- Render3DPlugin
- Source
Methods
(static) buildBox(sizeopt) → {Mesh}
Build a box centered on the origin, six flat faces with uvs covering each face
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
size | Vector3 | | <optional> | 1 | Full size, a number for a cube |
- Source
- Type:
- Mesh
(static) buildCapsule(sizeopt, heightopt, sidesopt, ringsopt, smoothopt) → {Mesh}
Build a capsule standing on the Y axis, centered on the origin: a cylinder with a half sphere on each end
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
size | number | <optional> | 1 | Diameter |
height | number | <optional> | 1 | Total height including the rounded ends, at least the size |
sides | number | <optional> | 16 | Around |
rings | number | <optional> | 4 | On each end |
smooth | boolean | <optional> | Defaults to render3D.smoothShading |
- Source
- Type:
- Mesh
(static) buildCone(sizeopt, heightopt, sidesopt, smoothopt, cappedopt) → {Mesh}
Build a cone standing on the Y axis, centered on the origin, the point up
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
size | number | <optional> | 1 | Diameter of the base |
height | number | <optional> | 1 | |
sides | number | <optional> | 16 | Around |
smooth | boolean | <optional> | Defaults to render3D.smoothShading | |
capped | boolean | <optional> | true | Close the base |
- Source
- Type:
- Mesh
(static) buildCylinder(sizeopt, heightopt, sidesopt, smoothopt, cappedopt) → {Mesh}
Build a cylinder standing on the Y axis, centered on the origin
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
size | number | <optional> | 1 | Diameter |
height | number | <optional> | 1 | |
sides | number | <optional> | 16 | Around |
smooth | boolean | <optional> | Defaults to render3D.smoothShading | |
capped | boolean | <optional> | true | Close the ends |
- Source
- Type:
- Mesh
(static) buildExtrude(pixels, sizeopt, depthopt) → {Mesh}
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
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
pixels | TileInfo | | 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 | <optional> | World width and height of the whole tile, centered like buildBox | |
depth | number | <optional> | 1 | Thickness along Z |
- Source
- Type:
- Mesh
new EngineObject3D(vec3(), buildExtrude(tile(3, 16), vec2(2), .5)); // a chunky version of tile 3(static) buildGrid(sizeopt, segmentsopt, coloropt, heightFunctionopt, smoothopt) → {Mesh}
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
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
size | Vector2 | <optional> | World size along X and Z | |
segments | Vector2 | | <optional> | 1 | Cells along X and Z, a number for both |
color | Color | | <optional> | One Color for the whole grid, or (x, z) => Color | |
heightFunction | function | <optional> | (x, z) => y, default flat | |
smooth | boolean | <optional> | Defaults to render3D.smoothShading |
- Source
- Type:
- Mesh
const ground = buildGrid(vec2(20), 10, (x, z)=> (floor(x / 2) + floor(z / 2)) & 1 ? GRAY : WHITE); // 2 unit checks(static) buildLathe(profile, sidesopt, smoothopt, cappedopt) → {Mesh}
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
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
profile | Array.<Array.<number>> | |||
sides | number | <optional> | 16 | Around the axis |
smooth | boolean | <optional> | Defaults to render3D.smoothShading | |
capped | boolean | <optional> | true | Close the ends that have a radius with flat discs |
- Source
- Type:
- Mesh
const vase = buildLathe([[0, -1], [.8, -.3], [.9, .2], [.4, .6], [0, 1]], 12);(static) buildLoft(stations) → {Mesh}
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
| Name | Type | Description |
|---|---|---|
stations | Array.<Array.<number>> |
- Source
- Type:
- Mesh
const hull = buildLoft([[1.2, .4, .2, -.1], [0, 1.4, .5, -.4], [-1, 1, .3, -.3]]);(static) buildRibbon(points, widthopt, coloropt, closedopt, upopt) → {Mesh}
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
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
points | Array.<Vector3> | Center line in order | ||
width | number | | <optional> | 1 | Full width, one for all or one per point |
color | Color | | <optional> | One for all or one per point | |
closed | boolean | <optional> | false | Join the last point back to the first |
up | Vector3 | <optional> | Which way the ribbon faces |
- Source
- Type:
- Mesh
const road = buildRibbon(trackPoints, 8, GRAY, true); // a loop of road(static) buildSky(topColoropt, horizonColoropt, bottomColoropt, sidesopt, ringsopt) → {Mesh}
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
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
topColor | Color | <optional> | Straight up | |
horizonColor | Color | <optional> | Level with the camera | |
bottomColor | Color | <optional> | Straight down, what a camera looking at the ground sees past its edge; defaults to the horizon color | |
sides | number | <optional> | 16 | Around |
rings | number | <optional> | 8 | Top to bottom |
- Source
- Type:
- Mesh
(static) buildSphere(sizeopt, sidesopt, ringsopt, smoothopt) → {Mesh}
Build a sphere centered on the origin
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
size | number | <optional> | 1 | Diameter |
sides | number | <optional> | 16 | Around |
rings | number | <optional> | 8 | Top to bottom |
smooth | boolean | <optional> | Defaults to render3D.smoothShading |
- Source
- Type:
- Mesh
(static) buildText3D(text, sizeopt, depthopt, fontopt) → {Mesh}
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
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
text | string | | |||
size | number | <optional> | 1 | Character height in world units |
depth | number | <optional> | 0.2 | Thickness along Z |
font | ImageFont | <optional> | Defaults to engineImageFont |
- Source
- Type:
- Mesh
new EngineObject3D(vec3(0, 2, 0), buildText3D('HELLO'), undefined, YELLOW);(static) buildTorus(sizeopt, tubeSizeopt, sidesopt, tubeSidesopt, smoothopt) → {Mesh}
Build a donut lying flat around the Y axis
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
size | number | <optional> | 1 | Diameter of the whole donut, outside edge to outside edge |
tubeSize | number | <optional> | 0.3 | Diameter of the tube |
sides | number | <optional> | 16 | Around the ring |
tubeSides | number | <optional> | 8 | Around the tube |
smooth | boolean | <optional> | Defaults to render3D.smoothShading |
- Source
- Type:
- Mesh
(static) debugBox3D(pos, sizeopt, coloropt, timeopt, rotationopt)
Draw a debug wireframe box
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
pos | Vector3 | Center | ||
size | Vector3 | | <optional> | 1 | Full size, a number for a cube |
color | Color | <optional> | ||
time | number | <optional> | 0 | How long to show it, 0 is one frame |
rotation | Vector3 | <optional> | vec3(pitch, yaw, roll) |
- Source
(static) debugLine3D(posA, posB, coloropt, widthopt, timeopt)
Draw a debug line
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
posA | Vector3 | |||
posB | Vector3 | |||
color | Color | <optional> | ||
width | number | <optional> | ||
time | number | <optional> | 0 | How long to show it, 0 is one frame |
- Source
(static) debugPoint3D(pos, coloropt, timeopt, sizeopt)
Draw a debug point as a small cross of three lines
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
pos | Vector3 | |||
color | Color | <optional> | ||
time | number | <optional> | 0 | How long to show it, 0 is one frame |
size | number | <optional> | 0.2 | Length of the cross |
- Source
(static) debugSphere3D(pos, sizeopt, coloropt, timeopt)
Draw a debug wireframe sphere as three rings
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
pos | Vector3 | Center | ||
size | number | <optional> | 1 | Diameter |
color | Color | <optional> | ||
time | number | <optional> | 0 | How long to show it, 0 is one frame |
- Source
(static) engineObjectsCallback3D(pos, size, callback, objectsopt)
Call a function for each EngineObject3D whose box overlaps a box
| Name | Type | Attributes | Description |
|---|---|---|---|
pos | Vector3 | Center of the box | |
size | Vector3 | | Full size of the box, a number for a cube | |
callback | function | ||
objects | Array.<EngineObject> | <optional> | Defaults to every object |
- Source
(static) engineObjectsCollect3D(pos, size, objectsopt) → {Array.<EngineObject3D>}
Collect the EngineObject3D objects whose boxes overlap a box, sizes are full sizes
- Boxes are axis aligned around the world position, rotation3D is ignored; lights, emitters and trails have no size
| Name | Type | Attributes | Description |
|---|---|---|---|
pos | Vector3 | Center of the box | |
size | Vector3 | | Full size of the box, a number for a cube | |
objects | Array.<EngineObject> | <optional> | Defaults to every object |
- Source
- Type:
- Array.<EngineObject3D>
(static) engineObjectsRaycast3D(ray, objectsopt) → {Array.<EngineObject3D>}
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
| Name | Type | Attributes | Description |
|---|---|---|---|
ray | Ray3D | From render3D.screenToRay, or any ray | |
objects | Array.<EngineObject> | <optional> | Defaults to every object; only those with a mesh or a sprite count |
- Source
- Type:
- Array.<EngineObject3D>
(async, static) loadOBJ(url, smoothopt) → {Promise.<Mesh>}
Fetch and parse an OBJ file
| Name | Type | Attributes | Description |
|---|---|---|---|
url | string | ||
smooth | boolean | <optional> | Compute smooth normals when the file has none, defaults to render3D.smoothShading |
- Source
- Type:
- Promise.<Mesh>
const mesh = await loadOBJ('ship.obj'); // in an async gameInit(static) parseOBJ(text, smoothopt) → {Mesh}
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
| Name | Type | Attributes | Description |
|---|---|---|---|
text | string | ||
smooth | boolean | <optional> | Compute smooth normals when the file has none, defaults to render3D.smoothShading |
- Source
- Type:
- Mesh
new EngineObject3D(vec3(), parseOBJ(objText).center().fit(4));