Type of View3D#root, inferred from the root you pass.
Type of View3D#root, inferred from the root you pass.
See View3DOptions.
ReadonlyeventsSends the pointer events pixi delivers to the view on to the 3D nodes under the pointer; the
3D counterpart of pixi's EventBoundary
It listens on the view itself, so view.removeAllListeners(), or view.off(type) without a
handler, stops 3D events for good; pass your handler to off.
const view = new View3D({ width: 800, height: 600 });
view.events.enableGlobalMoveEvents = false;
View3D#raycast For a one-off ray cast that dispatches nothing.
Brightness multiplier for the whole scene, background and fog included, applied before tone mapping
It scales unlit materials too, in linear light, so at 2 an unlit colour draws about 1.37 times as bright on screen. Free to change every frame.
Texels per logical pixel the scene is drawn at, or 'inherit' to take the resolution of the
2D target the view lands on
Absolute, like a pixi filter's resolution: 1 on a DPR 2 screen draws the scene at half the
physical size and stretches it over the view. Lower it for dynamic resolution when a device
falls behind. Post effects' textures follow it unless an effect sets its own, and
Camera3D.jitter comes out in the scene's pixels.
A resolution other than the target's turns on composite mode.
Turning composite mode on or off rebuilds the render graph on the next render, like assigning
View3D#passes, so a dynamic-resolution loop that returns to the target's resolution
rebuilds at every crossing; composite: true, or an enabled post effect, keeps that to once at
most. Any other change rebuilds nothing, and allocates new textures only when the size crosses
a power of two or the canvas size.
Root of the 3D scene
Add meshes and lights under it, at any depth, and the view finds them. Pass it in the options rather than assigning it later: the view only tracks the root it was built with.
Typed as whatever you passed as root, so a view built around a Model3D keeps the
model's API here.
Size of each shadow map; see ShadowQuality
StaticdefaultDefaults for every new View3D; an option passed as undefined keeps its default
Don't set root or camera here: every view would share the one object.
Where the view's origin sits, as a fraction of its size, like a sprite's anchor
0 puts the origin at the top-left corner, 0.5 centers it, and 1 puts it at the
bottom-right. Assign a number for both axes or a point for each.
Sets the anchor
A number for both axes, or a point.
Drawn behind the scene: a cube map, a Hemisphere gradient, a plain colour, or null
for none
Exposure and tone mapping apply to it. Set it to the same object as the environment and the sky you see matches the light and reflections the scene receives. A hemisphere's fields are read every frame, so changing them is free. A view with no meshes draws nothing, background included, until a mesh joins its scene.
A colour takes any ColorSource in display (sRGB) space and reads back as a hex number; its
alpha is ignored. Exposure and the tone curve shift it on screen: under 'aces', white draws
as light grey. To fade distant geometry into it, give the fog the same
color. For a flat backdrop with no fog that shows the exact colour, leave
background null and set the app's backgroundColor, which is never tone-mapped.
const env = await Assets.load<CubeTexture>('env.cubemap');
view.environment = env;
view.background = env; // show the same cube map behind the scene
// One hemisphere lights the scene and draws the sky behind it
const sky: Hemisphere = { skyColor: 0x88ccff, groundColor: 0x553311 };
view.environment = sky;
view.background = sky;
sky.skyColor = 0xff8800; // sunset, on the next frame
// Distant geometry fades into a plain background
view.background = 'skyblue';
view.fog = { type: 'linear', color: 'skyblue', near: 20, far: 60 };
view.background; // 0x87ceeb
Sets the background
Cube map, hemisphere gradient, display-space colour, or null for none.
The camera this view draws from
Assigning a camera with no parent adds it to root. Assigning one that has
a parent outside this view's scene throws: add it, or its ancestor, under view.root first.
A render with meshes to draw throws while the camera or any of its parents is hidden, or once
it leaves the scene without a new camera assigned.
How this view culls its meshes outside the camera's view; see CullMode
A change rebuilds nothing. A BatchedMesh3D ignores it and culls by its own cull.
Light from the surroundings, which fills in where the direct lights don't reach
CubeTexture: image-based lighting from a cube map, reflections included. The first frame
that uses a cube map prefilters it, once, into a copy 128 to 256 pixels wide per face that
lighting and reflections read, so faces wider than 256 sharpen the background but not
reflections. The copy stays on the GPU until the cube map is destroyed with destroy(true) or
Assets.unload, even after the view switches away. A float cube, such as one loadHdr
makes from an .hdr file, is read as linear light, so an HDR environment keeps highlights
brighter than white; any other format is read as sRGB. On WebGL the prefilter needs
EXT_color_buffer_float, and throws without it.null: none, and the cheapest.Switching between kinds recompiles the materials on the next frame, like changing toneMapping. Changing a hemisphere's colours is free.
Sets the environment
Cube map, hemisphere gradient, or null for none.
Distance fog, or null for none
The view keeps the object you assign, so changing its color, near, far or density
later is free. A new curve, or turning fog on or off, recompiles the materials on the next
frame, like changing toneMapping.
const haze: Fog = { type: 'linear', color: 0xadb2ba, near: 30, far: 55 };
view.fog = haze;
haze.far = 80;
view.fog = null;
Fog For the settings and their defaults.
Height of the 3D viewport in pixels; setting it resizes the viewport, as width does
View3D#setSize For setting width and height in one update.
Sets the height
Height in pixels.
Callback pixi runs at the start of every render of the stage this view is on, or null
It runs before the view updates its scene, so changes made in it show in the same frame.
Sets the per-render callback
Callback run at the start of every render; null removes it.
Passes and post effects added to this view
One list holds both kinds: a MeshPass redraws the meshes that opt in at its stage, a
PostEffect filters the scene's light or the finished picture, and any other
Pass3D runs where it says. Items at the same stage run in array order, and the post
effects run 'beforeToneMapping' ones first, then the tone curve, then 'afterToneMapping'
ones.
Assigning a new array rebuilds the render graph on the next render; changing the array in
place does nothing. Flipping an item's enabled also rebuilds the graph, which suits a
settings toggle; for changes every frame, use each item's own properties. Turning a scene
output on or off recompiles the materials on the next frame, and so does turning on the first
'beforeToneMapping' effect or turning off the last.
The items stay yours: replacing the list never destroys them, and one instance can serve several views.
Sets the pass list; null clears it
Passes and post effects to run; the array is copied.
How soft the edges of this view's shadows are; see ShadowFilter
Once a light in the view casts shadows, a change recompiles the materials on the next frame; before that it compiles nothing.
Sets the shadow filter
Edge filtering for the shadows this view draws.
Tone mapping for everything the view draws; see ToneMapping
With no enabled 'beforeToneMapping' effect in passes, the curve is
built into the material shaders, and a change recompiles them on the next frame. With one, the
scene draws as linear light, so the effects see brightness above 1, and the curve runs once
over the whole image after the last of them; a change rebuilds the render graph. Either way, don't change it every
frame.
The two look the same apart from see-through surfaces: with an effect, transparent surfaces blend, and glass refracts, in linear light before the curve.
Sets the tone mapping
The curve for everything the view draws.
Width of the 3D viewport in pixels
Unlike a plain pixi.js Container, setting it resizes the viewport instead of scaling
the view, the same as TilingSprite.width.
View3D#setSize For setting width and height in one update.
Sets the width
Width in pixels.
Destroys this view and the GPU resources it owns
The view's own GPU state always goes, whatever options says. With the children flag,
root is destroyed too, with the same options, so the geometry,
material and texture flags apply to it. Without the flag, the scene's nodes survive for you
to reuse, but they're removed from root, which is left empty.
Optionaloptions: Destroy3DOptions
Teardown options; see Destroy3DOptions. A boolean stands in for every flag. Leaving it out destroys nothing shared.
Casts a ray through a 2D point and returns the closest hit
position is in the space of event.global, as for View3D#screenToRay. Use it to pick
outside pointer events: placing decals, line of sight, drag-and-drop targets.
2D global point to cast through (e.g. event.global).
Optionalout: RaycastHit3D
Hit to write into, returned on a hit and untouched on a miss. Defaults to a new one for each hit.
The closest hit, or null on a miss or when the point falls outside the View's 2D rect.
null.out it allocates a new RaycastHit3D for each hit. Pass a hit from
createRaycastHit3D as out to pick every frame without garbage.// Drop a decal wherever the user taps.
view3d.on('pointertap', (e) => {
const hit = view3d.raycast(e.global);
if (hit) decal.position.copyFrom(hit.point); // world-space hit point
});
// Follow the pointer every frame, reusing one hit.
const hover = createRaycastHit3D();
app.ticker.add(() => {
if (view3d.raycast(pointer, hover)) cursor3d.position.copyFrom(hover.point);
});
View3D#screenToRay For the ray on its own, without a scene pick.
Builds the world-space Ray through a point in pixi's global 2D coordinates, such as
event.global
The inverse of worldToScreen: every point on the ray projects
back to position. A perspective camera's ray starts at the camera; an orthographic camera's
starts on the camera's plane and runs along its forward axis. Either way, ray.at(t) is t
world units from the camera, which for a perspective camera is distance along a slanted ray,
not depth.
When the view or the camera's viewport has zero area, it warns once and returns a ray with a zero origin and direction.
2D global point to cast through, such as event.global.
Ray the result is written into. Defaults to a new Ray.
true to use cached transforms (see Container3D#getGlobalTransform).
view3d.on('pointermove', (e) => {
const ray = view3d.screenToRay(e.global);
const hit = ray.intersectPlane(ground, cursorPos);
});
View3D#screenToWorld For going straight to a point on a plane or at a distance.
Converts a point in pixi's global 2D coordinates, such as event.global, to the world-space
point distance units along its ray
2D global point to convert.
Distance along the ray, in world units from the camera.
Optionalout: Vector3
Point the result is written into. Defaults to a new Vector3.
OptionalskipUpdate: boolean
true to use cached transforms (see Container3D#getGlobalTransform).
View3D#worldToScreen For the reverse direction.
Converts a point in pixi's global 2D coordinates, such as event.global, to where its
ray meets a plane: the usual way to find the spot on the ground
under the pointer
Returns null when the ray points away from the plane or runs parallel to it.
2D global point to convert.
World-space plane to intersect.
Optionalout: Vector3
Point the result is written into. Defaults to a new Vector3.
OptionalskipUpdate: boolean
true to use cached transforms (see Container3D#getGlobalTransform).
const ground = new Plane(new Vector3(0, 1, 0), 0);
view3d.on('pointertap', (e) => {
const hit = view3d.screenToWorld(e.global, ground);
if (hit) tree.position.copyFrom(hit);
});
View3D#worldToScreen For the reverse direction.
Frees this view's GPU memory now, for a scene you'll show again later
The next render that draws the view rebuilds everything, so nothing needs re-creating by
hand. It frees the view's draw state, shadow map, uniforms and buffers, and keeps CPU data:
the scene and every typed array, the way a 2D texture keeps its source image across unload.
The scene's geometry and textures stay on the GPU; Container3D#unload says how to free them.
pixi's garbage collector calls it for a view that has been out of the stage for
gcMaxUnusedTime. It never collects a view still in a stage, even a hidden one, nor one that
is a render group or left the stage inside one (isRenderGroup, cacheAsTexture, or rendered
directly, as extract does); set autoGarbageCollect to false to keep any view.
View3D#destroy For permanent teardown.
Projects a world-space point, such as one from Container3D#getGlobalPosition, to pixi's global 2D coordinates
The result is in the same space as event.global, so you can assign it straight to a 2D
object's position. It accounts for the view's anchor, its place on the
stage, and the camera's viewport. Convert a point in a node's own
space with Container3D#toGlobal first.
Returns null for a point at or behind a perspective camera: the cue to hide a label that
tracks it. Also returns null, and warns once, when the view or the camera's viewport has
zero area. With autoResize, the view takes the screen size only as
it draws, so a label placed from app.ticker lags a frame after a resize; size a view that
carries labels from the renderer's resize event instead.
World-space point to project.
Optionalout: P
2D point the result is written into. Defaults to a new Point.
true to use cached transforms (see Container3D#getGlobalTransform).
const label = new Text({ text: 'player' });
const world = new Vector3();
const screen = new Point();
app.stage.addChild(label);
app.ticker.add(() => {
// Reused out objects keep the per-frame code from allocating
const p = view3d.worldToScreen(mesh.getGlobalPosition(world), screen);
label.visible = p !== null;
if (p) label.position.copyFrom(p);
});
View3D#screenToRay / View3D#screenToWorld For the reverse direction.
StaticfromBuilds a view whose root is a Model3D of source, with a camera and light ready to
render it
The camera is options.camera, else the file's first camera, else a new Camera3D on
the model's +Z side, facing it, just far enough back that the sphere around the model's bounds
fits the view. An auto-sized view places that camera on its first render, once it knows its
aspect. That camera's near and far planes sit at a hundredth and a hundred times its distance
from the model. A file with no lights gets one; see View3DFromOptions#light.
The loaded glTF or GLB to build the scene from.
View options plus the per-instance model options; see View3DFromOptions.
A 3D scene drawn inside pixi's 2D display list
A
View3Dis a pixi display object: add it to the stage, then move, mask or filter it like a sprite. Everything 3D goes under its root.The view holds the camera and the settings for the whole scene: tone mapping, exposure, fog, environment light, background and shadows. A change to some of them recompiles the materials, so don't change those every frame; each one's doc says which.
The view also sends pointer events into the scene. Set eventMode on a node and it gets pixi's pointer events, hit-tested against its hitVolume. raycast picks without sending an event. The view itself starts with
eventMode'static', so it catches the pointer anywhere in its rectangle.Example
See
View3DOptions For all constructor options.