Skip to main content

Crate unlit3d_examples

Crate unlit3d_examples 

Source
Expand description

English | 简体中文

§unlit3d_examples

A windowed example with selectable scenes, presented through unlit3d::winit::presenter. Its scenes are also drawn offscreen by tests/gpu_suite.rs, which compares every frame against a stored snapshot, so the crate is both the workspace’s example program and a rendering regression check. The Android APK packages it as one of its two examples, the other being unlit3dx_examples.

It is at an early stage along with the crates it uses, and it exercises parts of them that are still under construction.

§Scenes

The example’s scenes are the snapshot scenes the GPU tests used to draw in crates/unlit3d/tests: every one of them is now a selectable scene, and tests/gpu_suite.rs is the check that replaced those tests. The windowed loop shows the scene the command line selected and lists every scene in a panel, so one can be switched to at runtime. --list-scenes prints the table:

Scenes:
  spin_cube              the example's own scene: a textured cube with two panels
  ui_only                a rich egui panel, no mesh source and no camera
  mesh_and_ui            a cube with the rich egui panel over it, one pass
  animated               a grid of cubes filling, moving and recycling over eight frames
  skinned                a cube bent by a two-joint skin over six frames
  morphed                a cube blended by two morph targets over six frames
  instanced_skinned_morph three cubes sharing one mesh, deformed per instance
  lit                    one relief surface under directional, point, spot and quad lights
  lit_clusters           every light kind in a per-cell local-light-count heatmap
  gltf                   a skinned fox and a morph-target cube playing their glTF clips
  mesh_topologies        every primitive topology, indexed and non-indexed
  transparent            translucent panes composited back to front over opaque cubes
  custom_pipeline        a caller-registered sky family and particle family
  outline                inverted-hull bands beside screen-space strokes
  outline_msaa           the outline scene on a four-sample target

Each scene reproduces exactly what its test froze: the same world, camera and frame sequence, so the stored snapshots still verify it. mesh_topologies and transparent are the exceptions: they are not ported from a test but add the coverage the ported scenes lack — every primitive topology drawn both indexed and non-indexed, and overlapping translucent draws whose composite depends on both the z-sort and the blend state. gltf is the other exception: it draws the glTF documents in unlit3d_asset_files/assets through LitGltf, so the loader’s skinning and morph-target animation are checked against real assets rather than the hand-written ones the unit tests use. The example reaches those documents through asset_bytes, the crate that embeds them, so the binary carries the models it draws and needs no file at run time.

custom_pipeline is the third: it registers two families of its own rather than drawing through the built-in lit one. A sky family reconstructs a view ray from the frame’s camera, samples a procedurally generated cube map and blends a gradient and a sun from a uniform block the example writes every frame; a particle family takes its per-instance records from an ordinary world component and animates each sprite from a clock the example advances. Neither mesh carries a vertex attribute — the sky’s three vertices and each particle’s six come from the vertex index — so the scene is what checks that a caller can own a pipeline, its bind groups, its vertex layout and its instance stream, and still read the frame’s camera. It is also the example’s longest animated scene, at eight frames of an orbit.

outline is the fourth: it draws two kinds of line the library offers and lets one picture argue for both. Three bodies wear an inverted-hull band — each is one mesh drawn twice from one buffer, lit and then spread along its own normals with its front faces culled — so the band is a width in world units and the bodies standing further back wear a thinner one. Beside them a LineSource draws the orbit, its ticks and a pair of armillary rings as screen-space strokes, a width in physical pixels, so the rings keep one weight from the near side to the far side. The ticks are opaque, the rings and the orbit are washes blended over the frame, so a ring shows the body it passes in front of, two crossings deepen where they share a pixel, and a body hides the ring half behind it. One frame holds all of it because neither kind alone shows what the other is for. Two of the five bodies carry no vertex normals at all and are lit through the screen-space derivative fallback, so the one frame covers both normal paths — the baked one the band needs and the derived one a mesh without a normal channel falls back to.

The scene is declared twice: outline captures it on a single-sampled target, outline_msaa on a four-sample one. The difference is only how an opaque stroke is antialiased — cut at half its coverage on the single-sampled target, its edge carried in the alpha on the multisampled one — so a frame that lost either path still matches its own snapshot and fails the other.

Every scene is built with the same public unlit3d API any caller would use — nothing in the example reaches into the crates’ internals.

§How it runs

The windowed path is the whole frame loop a windowed app needs. The renderer is spawned once as a resource entity, a scene’s meshes and materials are allocated through its mesh source, and every RedrawRequested acquires the swap chain’s next image, renders the ECS world into it and presents it. A resize is handed to the surface, which reconfigures the swap chain, and to the frame’s FrameAttachments, which rebuilds the depth-stencil and multisample attachments it holds at the new size.

A scene that draws 3D content declares a baseline aspect — 960×720, the shape the ported scenes were captured at. The windowed path draws such a scene through the largest rectangle of that aspect the target fits, and hands the scene that rectangle’s own size, so every scene takes its camera aspect from the region it is actually drawn into. The target only ever adds bars around the picture: a wide window shows the same view a narrow one does, larger, rather than more of it, and nothing is ever stretched. The UI is drawn over the whole target rather than the letterboxed region, because a panel has no aspect of its own. The snapshot tests turn the letterbox off and draw at the scene’s own size, so a capture is unchanged.

A readout at the top of the window, centred, reports the smoothed frame rate and frame time. The scene selector opens in the bottom-right corner, its bottom-right held a margin from the screen’s edge, and can be dragged anywhere from there; the rectangle it is left at is carried into the next scene when one is chosen. When the window changes shape — a phone rotating as fullscreen takes it — the panel follows the corner it belongs to, keeping its distance from that corner instead of staying where the old shape left it. A button in the top-right corner — sized so a finger can land on it — offers fullscreen on every platform, and is labelled for whichever the window is not. On the desktop and in a browser it takes the window fullscreen and back: in a browser the click is the one gesture the page is granted as permission, and a device being held upright is then locked to landscape, so the picture fills a phone’s screen. The lock follows from the fullscreen: the browser releases it when fullscreen ends, and it is never applied to a device already held sideways. Where the platform cannot change the window — Android, whose activity already takes the whole screen — or refuses the request — a page in an iframe without the fullscreen permission — the button is still drawn, and the press simply does nothing.

A GPU panel reports the device the example is running on: the adapter’s name and description, the backend, the driver, the features the device was created with, and every limit it reports. It opens in the bottom-left corner and, like the scene selector, is a window that can be dragged anywhere and whose rectangle is carried into the next scene. The facts are read once, when the scene is built — a device’s features and limits cannot change — and the list scrolls within a share of the window’s height, so even a long one never covers the scene.

The GPU context is requested asynchronously, because the adapter and device requests are: on the web they resolve on the browser’s task queue, so the frame loop must not block on them. The window is created on the main thread — winit hands out a window’s raw handle only from the thread that owns it — and the context arrives back through the event loop’s proxy, where the scene is built on the thread that owns the ECS world.

A suspension does not reset any of that. The platform invalidates the render surface, and on Android destroys the native window under it, but the window handle, the GPU context and the whole ECS world stay: the swap chain alone is released and built again on the next resume, so the app comes back to the state it left — the same spin angle, camera orbit and panel values.

No application logic lives in a winit callback. unlit3d::winit::event::WinitHost is the one ApplicationHandler the example implements — it is not implemented at all, only driven — and every callback is an ordinary behaviour component on an entity of the host world: the window is requested on resume, close and Esc set an exit request, the library’s pump keeps frames coming between compositor redraws, a resize re-letterboxes the scene, and the app’s own UserEvent carries the GPU context back. The example’s state is the same kind of component, so a callback writes a sibling cell and never borrows the one it is running from.

A frame’s own work is split the same way. The frame command the pump and the redraw requests queue computes the delta time and dispatches the host world’s OnFrame behaviours, which make sure the scene is presented, serve the scene switch and the fullscreen request, advance the scene, and present it through the library’s present_frames. The scene’s own world dispatches the same family for input distribution, sequence stepping and the scene’s advance closure, which runs through a queued command because it needs &mut World. The dispatch is not stable within one order value, so every behaviour that takes part states the order that encodes what it reads and writes — the readiness check first, then the controls, the advance, the region restate, the library’s present, and the scene’s command flush in the host world, and the advance after the index in the scene world — so the dependency holds however the setup spawns them. A caller adds a behaviour of its own the same way: spawn it, and state an order only if it reads or writes what another behaviour does.

§Running it

cargo run -p unlit3d_examples

A window opens with the default scene — a spinning, textured cube and two egui panels — plus a panel that lists every scene. Esc closes it; the cube’s panel’s button, checkbox and slider drive the spin, and dragging with the left button orbits the camera. A scene can be selected from the command line instead:

cargo run -p unlit3d_examples -- --scene skinned

To run the same example in a browser — where WebGPU needs a secure context, so localhost rather than file:// — use the task runner:

cargo xtask run-wasm --app unlit3d

The task builds this example and unlit3dx_examples into one site by default and serves a landing page linking both, so --app unlit3d builds only this one. The page it serves sizes the canvas to the viewport less a small margin of its own, rather than to the window the example asks for, so the example fills a phone’s screen and follows a window that is resized. The canvas is not the picture, though: each 3D scene is drawn into the baseline-aspect region of it, so the same picture fills whatever shape the page gives the canvas.

It is a library as well as a binary, because Android starts neither a process nor a command line: the activity loads a shared library and calls its android_main, and the command-line path is the binary. Both end in the same windowed loop, so the example only has one frame loop to maintain.

The shared library is unlit3d_examples_android, a crate of its own holding nothing but the export: crate-type applies to every target a package is built for, so a cdylib here would link a shared library on the desktop and in the browser too, where nothing loads one. The library keeps this crate’s name, so the activity’s android.app.lib_name entry is unchanged.

§Model Context Protocol

--mcp serves the scene the example would otherwise have rendered, over stdio, as a Model Context Protocol server. The chosen scene is built first — --scene still selects it — and the client then reads and drives it through the tools. The example’s own event loop serves it, on the thread that owns it, so the window goes on drawing and input still reaches the scene: the scene’s pass renders offscreen and a second pass in the same world copies that frame into the swap chain, so the picture follows the client. The copying pass declares no depth state and samples the offscreen frame’s resolved colour texture, so its frames carry neither a depth nor a multisample attachment. The world is one component of the host World, and a tool names it. See unlit_ecs for the server, the tools each crate registers, and the transport.

cargo run -p unlit3d_examples --bin unlit3d-examples -- --mcp --scene spin_cube

§Android

Android starts an activity, not a process: the activity loads the shared library and calls its android_main on a thread of its own. android_main builds the event loop with the activity winit requires on that platform and hands it to the same windowed loop the binary drives, starting with the default scene.

The APK carries one activity per example, because GameActivity reads the library name out of its own android.app.lib_name manifest entry once and has no way to load a second one. A floating tab bar over the game surface switches between them; picking the other tab starts its activity and finishes the one it leaves, so only one native window is ever alive.

To build the APK, which cross-compiles the library, stages it in the Gradle project’s jniLibs directory and then runs the Gradle wrapper there:

cargo xtask build-android

The result is android/app/build/outputs/apk/debug/app-debug.apk, installable with adb install. --release builds a release APK instead, which this project leaves unsigned. The project’s Gradle setup and the task’s own constants have to agree; see the task runner’s README.

The activities are MainActivity.kt and Unlit3dxActivity.kt. Each is a few lines over TabbedExampleActivity.kt, which extends GameActivity, installs the floating tab bar and takes the screen over; the activity only says which example it is and which tab is selected. GameActivity loads the library named by the android.app.lib_name manifest entry and calls into it, so the whole application — window, GPU context, frame loop — is the example crate’s.

§Snapshot tests

tests/gpu_suite.rs is where the example’s rendering is checked. It draws every scene offscreen, with no window and no event loop, advancing it by a fixed timestep so the same code produces the same picture, and compares each frame the scene freezes against the scene’s stored snapshot:

cargo nextest run -p unlit3d_examples

The test is a library test rather than a command line: the same body runs natively and, because the test binary is what the wasm test page loads, in a browser too. cargo xtask test runs it twice, once per device tier, and cargo xtask test-wasm runs it against a real WebGL2 implementation.

§Options

The options are declared and parsed with argh. Every option is --name value or a bare flag; the value must be the next argument, so --name=value is not accepted.

OptionDefaultMeaning
--scene <ID>spin_cubeThe scene to start from
--list-scenesoffPrint the scene table and exit
--size <WxH>the scene’s ownInitial window size in pixels
--mcpoffServe the world over stdio, showing its frames in the window

§Playback pace

A snapshot test draws a multi-frame scene’s frames back to back, so one run matches its snapshots frame by frame. The windowed loop instead plays them over time: a scene whose animation was frozen as a few frames holds each one for SEQUENCE_STEP (currently 0.5 s), so the sequence is watchable rather than flashing past at the refresh rate. At most one sequence step is taken per windowed frame, so a stall does not skip frames.

A scene whose animation carries its own timing declares no step at all and advances from the frame delta instead, so the window runs it at the pace the display refreshes rather than in the two steps a second a held sequence gives. Two scenes do this. gltf plays the fox’s Walk and the morph cube’s Pulse at each clip’s own duration, looping in real time, so the window shows the documents as an application would rather than through a six-frame sequence. custom_pipeline is parametric — the orbit angle and the particle clock are both functions of time — so it accumulates the frame delta and moves every frame. The snapshot capture still walks each scene’s sequence, because a stored frame has to be reproducible.

§Choosing a device tier

UNLIT3D_DEVICE_TIER sets how much of the WebGPU baseline every offscreen device a test builds is asked for. Unset, it is webgpu: the guaranteed baseline limits, so the device is no larger than the API promises and the frame runs wherever WebGPU does. Only the texture resolution is taken from the adapter, so the device is never smaller than the machine allows. native asks for the adapter’s own limits instead, which on a desktop is its full Vulkan, Metal or DX12 capabilities.

webgl2 asks for WebGL2’s limits — no storage buffers — and the frame is recorded as WebGL2 would record it, with the shader’s arrays read through textureLoad and each mesh’s vertex offset baked into its indices. Any other value is refused rather than guessed at, since running the wrong tier would pass while testing nothing.

UNLIT3D_DEVICE_TIER=webgl2 cargo nextest run -p unlit3d_examples

WGPU_BACKEND selects the backend in the usual wgpu way and is independent of the tier; WGPU_BACKEND=gles together with the tier is the closest a desktop machine comes to a browser’s WebGL2, since the limits and flags are WebGL2’s even where the GL context is not.

§Snapshots

Each test compares every frame the scene declares a snapshot for against the snapshot directory. The comparison uses SSIMULACRA2 and fails when the score falls below the tolerance, which the test states for the scene it draws. A missing snapshot is written from the frame rather than failed on, so the first run of a new test records its baseline, and SNAPSHOT_UPDATE=1 rewrites one that exists.

The default tolerance suits a frame of whole surfaces, where a regression moves large regions and so lands far below the line. A frame of thin primitives is different: its pixels are outlines, and which triangle an outline pixel belongs to is a rasterizer’s tie-breaking rule to decide — one the API leaves to each implementation. A scatter of such pixels is worth tens of points there, so mesh_topologies is given a tolerance of its own, stated with the measurements that put its bound above every correct frame and below every broken one.

A scene’s own snapshots only describe a run that reproduces the scene’s stored settings, so a test draws at the scene’s own size and frame count. The letterbox fitting the windowed path applies is checked by a test of its own, which draws the default scene at a target narrower than its baseline and compares the fitted picture against a capture made for it.

A mismatch is frequently the platform showing through rather than a regression: the stored images come from one GPU stack, and another driver’s rounding can put a scene below the line with nothing wrong. A frame that fails is therefore written before the test fails — natively under UNLIT3D_SNAPSHOT_MISMATCH_DIR, and in a browser through the runner, which is the process that has a filesystem — so the frame can be looked at instead of guessed at from a score. CI uploads those directories as artifacts when a test fails.

To re-bless a snapshot after an intentional rendering change, run with SNAPSHOT_UPDATE=1, then review the image diffs in unlit3d_asset_files before committing them. That submodule is checked out with git submodule update --init --checkout, which is what gets past its update = none.

§Tests

The crate’s own tests cover the command line (src/cli.rs) and the fixed-step playback clock (src/lib.rs), and tests/gpu_suite.rs covers the rendering. Where each test layer sits across the workspace, and what CI runs, is in the root README.

§License

Dual-licensed under MIT or Apache-2.0, at your option.

Re-exports§

pub(crate) use cli::Args; 🔒
pub(crate) use cli::Parsed; 🔒
pub(crate) use scenes::Advance; 🔒
pub(crate) use scenes::SceneControl; 🔒
pub(crate) use std::collections::VecDeque; 🔒
pub(crate) use std::io::Write; 🔒
pub(crate) use std::process::ExitCode; 🔒
pub(crate) use Bundle; 🔒
pub(crate) use DynamicBundle; 🔒
pub(crate) use bundle; 🔒
pub(crate) use unlit_wgpu::resources::ResourceGraph; 🔒
pub(crate) use unlit_wgpu::scene::ViewportRect; 🔒
pub(crate) use unlit3d::frame::Frame; 🔒
pub(crate) use unlit3d::input::winit::WinitInput; 🔒
pub(crate) use UiSource; 🔒
pub(crate) use egui; 🔒
pub(crate) use DisplayHandle; 🔒
pub(crate) use ExitOn; 🔒
pub(crate) use ExitRequest; 🔒
pub(crate) use ExitTrigger; 🔒
pub(crate) use Resumed; 🔒
pub(crate) use WindowSetup; 🔒
pub(crate) use WinitProxy; 🔒
pub(crate) use request_redraw_while_foreground; 🔒
pub(crate) use window; 🔒
pub(crate) use winit_input_behaviour; 🔒
pub(crate) use OnUserEvent; 🔒
pub(crate) use OnWindowEvent; 🔒
pub(crate) use WinitHost; 🔒
pub(crate) use unlit3d::winit::presenter::SCENE_PASS_ORDER; 🔒
pub(crate) use winit::event::WindowEvent; 🔒
pub(crate) use ControlFlow; 🔒
pub(crate) use EventLoop; 🔒
pub(crate) use EventLoopProxy; 🔒
pub(crate) use winit::window::Window; 🔒
pub(crate) use unlit3d::prelude::*; 🔒

Modules§

cli 🔒
The example’s command line.
fullscreen 🔒
The fullscreen button, and the landscape lock that only a browser permits. Fullscreen: the button that takes the window fullscreen, and the landscape lock that only a browser permits.
scenes
The example’s selectable scenes.

Structs§

App 🔒
The application’s state, spawned as one object.
BuildPresenter 🔒
Build the presentation path once the scene’s queued world has landed.
FrameRate 🔒
The frame rate the windowed shell reports, as a component so the panel that displays it and the loop that measures it share one value.
FullscreenActive 🔒
Whether the window is fullscreen, written once per frame by the frame loop.
FullscreenRequest 🔒
Set by the windowed shell’s fullscreen button, read once by the frame loop.
Gpu 🔒
The GPU context a scene draws with, requested asynchronously.
GpuInfo 🔒
The device facts the GPU-info panel shows, read once when it is mounted.
GpuInfoPos 🔒
The GPU-info panel’s rectangle the last time a scene was live, so a scene switch can rebuild it where the user left it.
InitialScene 🔒
The scene the example starts with; a switch replaces it.
McpEnabled 🔒
Whether to serve the world over the Model Context Protocol rather than drive a scene on this thread.
PanelRects
Where the scene’s draggable panels opened, carried from the scene a switch replaced.
PresenterEntity 🔒
The entity carrying the presentation path, absent until the scene and surface are ready.
RenderWorld 🔒
The render world an application presents through, under the name it reports to the MCP tools.
RunInHost 🔒
Run one MCP command against the host world itself.
RunInWorld 🔒
Run one MCP command against a nested world of the host.
RunSceneAdvance 🔒
Run the scene’s own per-frame behaviour, which needs &mut World.
Scene
The scene’s world and the frame loop that drives it.
SceneAdvance 🔒
A scene’s own per-frame behaviour, stored in its world so the frame behaviour that drives it can call it with the world it mutates.
SceneEntity 🔒
The host entity carrying the scene’s world and its Scene.
SceneFrame 🔒
The scene’s per-frame state, spawned with its own advance.
SceneSwitch 🔒
Set by the windowed shell’s scene-selector panel, read once by the frame loop.
SelectorPos 🔒
The selector window’s rectangle the last time a scene was live, so a scene switch can rebuild it in the same place and at the same size.
SequenceClock 🔒
Seconds accumulated towards the next advance of a scene’s index.
SequenceStep 🔒
The interval a scene’s index advances at, in seconds, or None to advance it once per drawn frame.
SequenceStepped 🔒
Whether this frame advanced the scene’s index, decided by the sequence step and read by the behaviour that runs the scene’s own advance.
WorldName 🔒
The name this example reports a host world under to the MCP tools.

Enums§

GpuInfoLine 🔒
One line of the GPU-info panel.
GpuState 🔒
Where the one-time GPU setup stands.
UserEvent 🔒
Events delivered to the winit loop from outside a WindowEvent.

Constants§

ADVANCE_ORDER 🔒
The order the scene advances at: after the controls, which may have skipped the frame, and before the present, which draws what the advance produced.
API_DOCS_AREA 🔒
The id of the API-docs button’s area.
API_DOCS_LABEL 🔒
The label the API-docs button carries.
API_DOCS_URL 🔒
The API docs the Pages workflow publishes beside the example page.
CONTROLS_ORDER 🔒
The order the controls run at: after ensure_presented, which may have skipped the frame, and first of the readers that act on the flag, since switching a scene skips the frame for the two after them.
FIXED_STEP
The timestep a scene is stepped by when it is drawn without a display.
FLUSH_ORDER 🔒
The order the scene world’s queued commands are applied at: after the library’s present, whose render is what queued them.
FRAME_RATE_AREA 🔒
The id of the frame-rate readout’s area.
FULLSCREEN_AREA 🔒
The id of the fullscreen button’s area.
GPU_INFO_AREA 🔒
The id of the GPU-info panel’s area, which is also the id egui remembers the panel’s rectangle under.
GPU_INFO_HEIGHT_FRACTION 🔒
The share of the window’s height the GPU-info panel may take.
GPU_INFO_MAX_WIDTH_FRACTION 🔒
The share of the window’s width the GPU-info panel may take, at most.
GPU_INFO_MIN_WIDTH 🔒
The narrowest the GPU-info panel may be dragged, in points.
GPU_INFO_TITLE 🔒
The GPU-info panel’s title, shown in its title bar.
GPU_INFO_WIDTH_SLACK 🔒
Slack added to the GPU-info panel’s measured width.
MCP_SUPPORTED 🔒
Whether this build can serve the Model Context Protocol.
OVERLAY_BUTTON_MIN_SIZE 🔒
The smallest a corner button is drawn, in points.
OVERLAY_BUTTON_PADDING 🔒
A corner button’s inner padding, symmetric so the label is centred within the button it is grown to.
OVERLAY_GAP 🔒
The gap between the frame-rate readout and the fullscreen button when a window is too narrow to hold them on the same row.
OVERLAY_MARGIN 🔒
The distance every overlay keeps from the edge of the screen.
READY_ORDER 🔒
The order the scene and its presentation path come up at.
SAMPLE_COUNT 🔒
The number of samples the windowed loop presents every frame with.
SCENE_ADVANCE_ORDER 🔒
The order the scene world advances its scene at: after step_sequence, which decides whether this frame advances and records the decision for the behaviour that runs it. The value shares nothing with the host world’s orders: the two worlds dispatch separately.
SELECTOR_DEFAULT_WIDTH 🔒
The width the selector window opens at, in points.
SELECTOR_WINDOW 🔒
The scene-selector window’s title, which is also its egui area id: the shell reads the window’s remembered rectangle by this same id.
VIEWPORT_ORDER 🔒
The order the scene’s region is restated at: after the advance, and before the library’s present, which draws the pass the region belongs to.

Functions§

advance_scene 🔒
Advance the scene by the frame’s delta.
api_docs_button 🔒
Draw the API-docs link under the fullscreen button, and report whether it was pressed.
corner_button 🔒
Draw a button that owns a corner, and report whether it was pressed.
device_type_name 🔒
The name of a [wgpu::DeviceType], for the panel’s summary line.
dispatch_command 🔒
Queue one MCP command against the world it names.
dispatch_input_on_frame 🔒
Run the scene world’s input dispatch for the frame.
ensure_presented 🔒
Build the scene and its surface, and short-circuit the frame until both are ready.
flush_scene 🔒
Apply the commands the scene world queued while presenting.
follow_screen_corner 🔒
Shift a movable window by however far the screen corner it belongs to moved when the screen changed shape.
frame_rate_readout 🔒
Draw the frame-rate readout, showing text, centred along the top edge of ui’s screen.
fullscreen_button 🔒
Draw the fullscreen button, labelled for what pressing it does, and report whether it was pressed.
gpu 🔒
The GPU context, once the asynchronous setup has landed.
gpu_info_default_pos 🔒
Where the GPU-info panel opens when no position was carried over.
gpu_info_lines 🔒
The lines the GPU-info panel shows, top to bottom.
gpu_info_panel 🔒
Draw the GPU-info panel for info, seeded at initial or the bottom-left corner of ui’s screen.
gpu_info_width 🔒
How wide the GPU-info panel has to be to keep every line on one row.
handle_user_event 🔒
Serve the events the app posts to itself.
init_logging 🔒
Install the logger backend and the panic hook the example reports through.
json_scalar 🔒
One limit’s value as text.
letterbox 🔒
The region a scene’s content is drawn into and the size its camera is built for, for a target-pixel render target.
limit_rows 🔒
The device’s limits as label/value pairs, in the order the device reports them.
mount_api_docs 🔒
Mount the link to the API docs in the window’s top-right corner.
mount_frame_rate 🔒
Mount the frame-rate readout at the top of the window, centred.
mount_fullscreen 🔒
Mount the fullscreen button in the window’s top-right corner.
mount_gpu_info 🔒
Mount the GPU-info panel, a draggable window in the bottom-left corner.
mount_selector 🔒
Mount the windowed shell’s scene-selector panel.
open_url 🔒
Open a URL the UI asked for, in a new tab when it asked for one.
overlay_button_top 🔒
The vertical offset a corner button’s anchor is drawn at, given the area above it in the same corner.
pivot_factor 🔒
The fraction of a window’s size at which its pivot sits, per axis.
present 🔒
Bring the scene and its presentation path up, as far as the state allows.
presenter_entity 🔒
The entity carrying the presentation path, while one is up.
release_presenter 🔒
Release the presentation path and drop it, before its scene goes.
release_surface 🔒
Release the swap chain, keeping the presentation path for a later resume.
request_gpu 🔒
Request the GPU context once a window exists to present through.
resize_scene 🔒
Re-state the scene and the surface for a new window size.
restate_viewport 🔒
Restate the scene’s letterboxed region on the pass that draws it.
run
Run the example from the command line.
run_scene_advance 🔒
Run the scene’s own per-frame behaviour when the sequence advanced, and count the frame.
selector_default_pos 🔒
Where the selector window opens when no position was carried over — the first build of a session.
serve_scene_controls 🔒
Serve the scene selector, the fullscreen button and the UI’s URL requests.
spawn 🔒
Run future concurrently: on a worker thread on native, in the browser’s task queue on the web (where a thread cannot be blocked).
start_mcp 🔒
Start the MCP stdio transport, which posts each command back to the loop.
stderr 🔒
Write text to standard error.
stdout 🔒
Write text to standard output.
step_sequence 🔒
Decide whether this frame advances the scene’s sequence.
switch_scene 🔒
Rebuild the app around a different scene.
tick 🔒
Accumulate delta_time into clock and report whether a step-long interval has passed, subtracting it from the clock if so.
windowed 🔒
Drive the windowed example on event_loop until it exits.