Proposal: rendering & camera extras — Screen.camera/clip/blend_mode/oval + Camera.follow/shake #23
Labels
No labels
area:ci
area:docs
area:input
area:net
area:rendering
area:repo
area:stdlib
area:tooling
area:types
cleanup
dx
priority:high
priority:low
priority:medium
proposal
status:in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: workshopsoft/ludic#23
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to #2. The extended
Screen.*drawing primitives (line/circle/fill_circle/triangle/fill_triangle/sprite) shipped on branchstdlib-namespaces, but the transform/state-based rendering was deferred because it needs new renderer state inruntime/native/core.ludic.Proposed surface
Screen.camera(pos)— a world-space offset applied in the draw pathScreen.clip(rect)— a clip rectangleScreen.blend_mode(m)— additive/mix blendingScreen.oval(...)— ellipse outline (midpoint), andScreen.measure_text(alias of the existingtext_w)Camera.set(pos),Camera.follow(entity, lerp),Camera.shake(amount)— deterministic shake from the seeded RNGWork required
A camera offset + clip rect + blend accumulator threaded through the
rt_*draw functions.Blocked on: renderer state in the runtime.
Shipped in
31cfbc2(pushed tomain) — the transform/state-based rendering this issue tracked as blocked on new renderer state.The whole proposed surface landed:
Screen.camera(pos)/Camera.set— a world-space draw offset; a world point(wx, wy)draws at(wx-x, wy-y).Camera.follow(x, y, lerp)— eases the offset toward centring a target (fixedlerp0..1).Camera.shake(amount)—+/- amountjitter drawn from the seeded RNG, so a replay shakes identically;shake(0)clears it, and it composes on top of set/follow.Screen.clip(rect)/clip_reset()— a screen-space clip rectangle.Screen.blend_mode(m)—0replace (default),1additive (clamped at 255) for glow/light.Screen.oval(x, y, rx, ry, color)— axis-aligned ellipse outline (integer midpoint).Screen.measure_text(text)— advance width in the 5x7 font.On "blocked on renderer state in the runtime": the camera/clip/blend state is threaded through the two framebuffer chokepoints every draw primitive already funnels through (
rt_put_px/rt_fill_rect— I confirmed every primitive, including sprites and text, funnels through one of them). That single seam gives the entire draw API the new state at once. Crucially the defaults are neutral (camera(0,0), clip = full screen, blend = replace), so every existing golden render stays byte-identical — all 60+ render tests pass unchanged.I also added
Screen.pixel(x, y)(read a framebuffer pixel), which makes the surface verifiable by reading rendered pixels back rather than trusting a golden hash:examples/library/render.ludicasserts 18 cases — pixel round-trip, camera +Camera.set/followoffsets, clip in/out + reset, additive blend with the 255 clamp, oval extremes vs a hollow centre, and text measurement — all against the actual framebuffer. Wired intox test(now 65 passed). Everything is integer and deterministic (camera, shake, and blend reproduce exactly), so headless renders stay diffable;Camera.followinterpolates in the fixed domain to dodge the int×fixed coercion trap.Docs: 7 new
Screenpages + a newCamerasection (3 pages);x check-impl/x check-docsgreen. Seed reseeded and the C-free bootstrap fixpoint holds. Closing.