v0.15.0
·
151 commits
to master
since this release
Runtime Layer & Plugins
- Scene runtime layer: a formal per-frame orchestration layer now sits between the scene graph and the renderer. Plugins run in a defined phase order (prepare, pick, select, manipulate, animate, simulate, writeback). A fixed-timestep accumulator handles the physics pattern of running zero, one, or several fixed steps per wall-clock frame. Transform snapshots let the renderer interpolate smoothly between physics steps without jitter. The scene and selection remain owned by the host; the runtime borrows them per call and applies any changes before returning. Existing call sites are unchanged.
- Generic typed event bus: plugins can emit arbitrary typed events during a frame and read them from later plugins in the same frame, or from the host after the step returns. Events accumulate during the frame and can be read or drained once the step completes.
- Async job handoff: plugins can hand work off to a background thread and poll for the result each frame. The result transitions through pending, ready, failed, and cancelled states. Dropping the sender without signalling automatically cancels the job.
- Shared resource registry: plugins can coordinate through typed state that persists across frames without any custom wiring in the host application. Resources are stored by type and are accessible during all plugin phases. The registry can also be read and written from outside the frame loop.
- Camera command writeback: plugins can drive the viewport camera directly from within the frame loop, without any extra wiring in the host application. Emit commands to set or offset the camera center, change distance, set orientation, or blend toward a target. Commands apply in emission order, each building on the result of the previous. Camera following is unchanged and works independently.
- Debug draw: plugins can submit lines, points, AABB wireframes, sphere wireframes, and world-anchored text labels to a shared drawing layer. Primitives can be tagged as development-only and suppressed at runtime without changing plugin code. Persistent primitives survive until explicitly removed; transient ones are cleared each frame. After stepping, the results are available as standard polyline, point cloud, and label items ready for the renderer. Showcase 46 demonstrates the full path with a simulated physics scene.
Animation Plugin
- Animation, constraints, and simple physics are now available as built-in runtime plugins:
- Drive any scene node along a keyframed path. Tracks can loop, and transforms are interpolated automatically between keyframes.
- Three constraint types for the animation phase: pull a node toward a fixed world position with configurable stiffness and damping; drag its velocity toward zero over time; or keep it inside an axis-aligned box.
- Simple physics bodies with linear velocity, gravity, and restitution. The runtime integrates velocity each step and bounces bodies off optional bounding walls. Contacts with walls produce events in the runtime output each frame.
Skeletal Animation Plugn
- CPU linear blend skinning is now available as a built-in runtime plugin. Define a skeleton and set a pose each frame from an animation plugin; the plugin runs forward kinematics and produces deformed geometry ready for upload to the GPU.
- Clip player plugin: samples an animation clip each frame and feeds the resulting pose into the shared registry for the skeleton plugin to consume. Speed, looping, and play/pause are configurable; the playhead is exposed for manual seeking. Showcase 47 includes a clip-driven arm entry using a five-keyframe rotation clip on the forearm joint.
- Skinned actor plugin: drives many independently-animated actors sharing a single skeleton. Each actor has its own clip, playhead, speed, and play state; multi-mesh characters stay in sync internally. One plugin processes the whole crowd in a single phase tick. Showcase 47 adds a crowd entry with a slider for actor count, staggered playheads, and a clip choice cycled per actor.
- GPU skinning vertex stage: the renderer now includes a skinned variant of the standard lit and shadow pipelines. Linear blend skinning runs in the vertex shader from a per-mesh weights buffer and a per-instance joint palette. The bind-pose vertex buffer is never modified. Static meshes pay no overhead; only meshes explicitly marked for skinning allocate the extra storage.
Other Feature Additions
- New overlay shapes: screen-space shapes. Twelve shape types: rect, rounded rect (per-corner radii), circle, ellipse, capsule, ring (hollow circle with configurable wall thickness), arc, triangle, line, star, cross and regular polygon. Shapes are drawn before rects and labels in all render paths.
- Texture-masked overlay shapes: an overlay shape can sample an uploaded image for its interior instead of a solid colour. Textures are uploaded once and referenced by ID. Use cases include circular avatars, rounded-corner images, and textured HUD panels.
- Gradient fill for overlay shapes.
- Shadow/glow for overlay shapes.
- Hit testing for overlay shapes.
- Border mode for overlay shapes.
- Opacity animation for overlay shapes: shapes support fade-in, fade-out, and pulse animations resolved each frame from a caller-supplied time value. The host must request continuous repaints while animations are active.
Improvements
- Scene traversal acceleration: scenes with 500 or more nodes now use a spatial index to skip subtrees entirely outside the camera frustum, reducing traversal cost sub-linearly with node count. Smaller scenes use the existing flat walk. The index updates incrementally as nodes are added, removed, or moved. A bulk rebuild call is available after large scene loads to avoid accumulating many incremental updates.
- Async texture upload: texture data can be staged on the CPU and transferred to the GPU on the next frame, avoiding burst allocation overhead when streaming a new zone or loading a large material set. The texture is invisible for one frame while the transfer completes. The existing synchronous upload path is unchanged.
- VRAM budget query: the total memory and count of user-uploaded textures can be queried each frame, allowing host code to apply its own eviction logic.
- The wire grid and checkerboard ground plane now accept explicit colours. The grid colour can be set per frame; the ground plane takes two independent tile colours instead of deriving both from a single tint.
Fixes
- Render scale and dynamic resolution now work in both the LDR and HDR paths. All scene textures are allocated at the scaled resolution; the result is upscaled to native resolution before post-tone-map passes (grid, ground plane, gizmos, axes, overlays).
- Shadow cascade quality now tracks camera zoom automatically. The cascade split window is derived from the camera distance rather than the full near/far range, eliminating shadow blurriness when zoomed out without any manual tuning.
- Normal line overlays are now drawn in the HDR path. Previously they were only visible when HDR was off.
- Compute-filtered geometry (GPU-computed index buffer overrides) is now applied in the HDR draw path. Previously the HDR path always drew the full mesh, so filtered views differed between LDR and HDR.
- The HDR non-culling instanced pipeline is now created when geometry first appears, not only on the first frame. Starting with an empty scene and adding geometry later no longer leaves the pipeline uninitialised.
- Render scale now has a visible effect in the HDR path. Previously the scene rendered at scaled resolution but the tone-map and FXAA passes ran at native resolution, so no change was visible.
- Contact events now include the world-space position of the collision, for use in sound, particles, and decal placement.
- Frames assembled from manually constructed render items (such as physics-interpolated transforms) no longer freeze after the first frame. A missing generation counter meant the renderer's instance buffer cache saw an unchanging version and stopped updating.
- Eleven primitives corrected to Z-up: cylinder, cone, capsule, arrow, and spring now extend along Z; disk, ring, grid plane, torus, and hemisphere now lie in the XY plane. Triangle winding is preserved on all affected meshes.
- Selection stopped working after moving or rotating objects with the manipulation system. The pick accelerator was being rebuilt with no geometry after each manipulation session ended.
- Camera follow at low simulation rates could visibly lag behind the followed object when interpolation was enabled. The camera pivot now derives from the same interpolated position the renderer uses.