The Moppe legacy: lighting, post, and atmosphere worth transplanting
Moppe is evidence, a tuning library, and a legacy #C4XGYX
Moppe (~/src/moppe) is the predecessor engine: a C++/Metal terrain world
with a complete cinematic renderer. It proves an ambitious end state on the
actual development machines, preserves hundreds of tuned judgment calls, and
shows what luv should improve: its answers are frozen in MSL and duplicated by
convention, where luv can hold shared material meaning as live Lisp objects.
This page now stays a source-study and transplant inventory. The native backend motivation it originally contained has become executable luv work and moved, with its stable figure IDs, to the native Metal 4 backend. Read Moppe as #H7QK3M advises: observed mechanism, source claim, and luv's possible choice are different voices.
Mentioned in: Where luv's semantic arithmetic goes beyond its sources
The post stack reveals what finished-looking means #8VA1EX
moppe/shaders/metal/post.metal supplies a concrete observed sequence:
- Auto-exposure averages wide HDR taps into a tiny CPU-read target and adapts one exposure scalar. Bloom sees the exposed scene.
- Bloom uses a soft-knee bright pass and quarter-resolution chain; a
smoothstep (0.85, 1.35, luma)threshold and five-sample linear-filter trick evaluate the nine-tap Gaussian cheaply. - Lens character adds edge-gated chromatic fringe, veil, anamorphic streak, and sun ghosts modulated by visibility.
- ACES tonemap converts the linear scene, followed by sRGB encoding.
- Color grade applies warm print-film CDL, split tone, vibrance, grain, and vignette.
- EDR output re-linearizes and permits true highlights above diffuse white within current display headroom.
The sequence matters more than any individual effect: exposure and tone mapping establish the medium in which bloom and grade make sense. #SKHDR already follows that order. Moppe's grade is especially attractive because it is cheap, separable, and made of constants which can become live uniforms or hot-redefined material methods.
Mentioned in: Logarithmic quantities as affine structure
Sun shafts are the highest-glamour transplant #BAP0QU
Moppe's shafts_gather_fragment marches view rays at half resolution through
the existing shadow map, jitters them with interleaved-gradient noise, stops
at scene depth, and weights lit spans by a forward Henyey-Greenstein lobe with
g = 0.60. A separate pass filters and adds the result.
Luvcraft already owns both inputs: a stored shadow map (#2WX9PW) and offscreen scene depth. The effect needs no new world representation. It does need the linear-HDR target (#WLHDRB) so gathered light adds in meaningful units.
Mentioned in: Transplant the post stack onto the HDR path, March the shadow map for shafts and compare against the screen sweep, One arithmetic medium, many clients, What the presentation stack became
common.h is a library of judgment calls #094ZB1
moppe/shaders/metal/common.h is valuable less for novel algorithms than for
tuning worth testing:
moppe_hemisphere_lightsplits ambient into warm ground bounce and cool sky;moppe_warmed_fogcouples fog colour to forward and backward solar lobes;moppe_sky_radiancesupplies a cheap analytic reflected environment;moppe_sun_visibilityrecords centre-weighted PCF, response shaping, and distance fade, including the observedpow 1.3response;moppe_cloud_transmissionprojects stable cloud shadow onto world points; and- coupled gust, bough, and flutter clocks coordinate foliage motion.
The strongest argument for re-expressing these in luv is duplication. The
daylight / golden pair is recomputed independently in several shaders. In
luv it can be one shader abstraction (#DXYHT4) reused with shared meaning and
one live redefinition point.
Sky, temporal reconstruction, and mesh shaders bound the proof #KK6M0T
Three larger observations describe capabilities rather than immediate ports:
sky.metalcombines a three-stop atmosphere, golden-hour band, Mie lobes, two cloud layers, stars, dithering, and a fog-matched horizon. Luvcraft's smaller sky (#SKDYCY) has the same conceptual shape.- Scene shaders emit motion vectors and a reactive mask for MetalFX temporal reconstruction. This records a heavier answer if local filtering no longer controls temporal shimmer.
- The forest shadow pass is a native Metal object + mesh shader pipeline. It proves the hardware capability while MoltenVK cannot expose the same route. That observation originally motivated #NABRMK; the resulting luv backend and its remaining shader join now live on the Metal page.
These are forcing examples, not reasons to import Moppe's renderer wholesale. The post stack is largely backend-neutral fullscreen work, while mesh stages should enter luv's shader language only when a concrete native pipeline makes their types and interfaces precise.
DONE Transplant the post stack onto the HDR path #VG8TGG
Intent: when #WLHDRB lands the linear-HDR scene target, extend it past tone map and restrained bloom toward Moppe's observed order: exposure, ACES, and a small live grade. Treat sun shafts (#BAP0QU) as the first post effect after bloom because both inputs already exist.
Observed: luvcraft's presentation stage now composes in linear light in Moppe's order --- exposure, bloom, shafts, the same Narkowicz ACES fit, and a vignette --- with every parameter a live special rather than a compiled constant (#IC14P3). The bright pass took Moppe's soft-knee threshold and its five-linear-sample gaussian directly; the difference is that each stage is a CLOS shader role rather than a named Metal fragment function, so a redefined method rebuilds its pipeline at the next frame boundary.
Two of Moppe's stages were deliberately not transplanted. The chromatic fringe, ghosts, grain, and CDL-style grade belong to a photographic look which this block world has not asked for, and none of them would be evidence of anything. Auto-exposure needs the readback probe and adaptation loop, which is its own piece of work; the sky profile's static exposure is enough while the frame has no wildly varying luminance.
The shafts departed further: they sweep the blurred bright image toward the sun's screen position rather than marching the shadow map, so the "frame-time cost for the half-resolution shaft march" this mark asked to measure has no subject yet. #94AUTK carries the marched version as the thing to compare against.
Mentioned in: Exposure as a logarithmic level in the sky model, March the shadow map for shafts and compare against the screen sweep
IDEA March the shadow map for shafts and compare against the screen sweep #94AUTK
Intent: #VG8TGG shipped the cheap radial sweep because terrain which occludes the sun is already dark in the bright image. #BAP0QU's marched version is strictly better informed: it knows about occluders which are off screen or behind the camera, and it produces beams in air the bright image says nothing about. Whether that is visible enough to pay for is a measurement, not an argument.
Evidence to gather:
- a low-sun forest capture of each, from the same pinned pose and clock; and
- frame time for each at the same resolution, with the march at half resolution and jittered as Moppe's is.
Done when: one of the two is chosen with a capture pair and a frame-time pair recorded here, or both are kept with a stated reason for choosing between them at runtime.
Mentioned in: Transplant the post stack onto the HDR path
This wiki is a place to develop an understanding of GPU programming, engine design, and implementation. Its first subject was the shape of WebGPU and the work hidden beneath that shape. The little block world now adds a second path: how a live Common Lisp game might understand worlds, materialized data, measurement,…
Intent: make the renderer capable of producing a shadow depth map as a separate GPU product owned by the luvcraft session, with light-space projection data carried through the ordinary frame uniform. Evidence: – The Vulkan backend accepts a depth-only render pass and a vertex-only graphics pipeline; the depth…
Intent: give emissive materials headroom and bloom without abusing alpha or the current LDR scene target. Observed: the scene attachment is :rgba16-float, presentation applies exposure and a fitted ACES curve, and a quarter-resolution bright/blur/sweep chain adds bloom and shafts in linear light before that curve…
Intent: add a source-expansion layer above the core shader operator set, then define shadow vocabulary there instead of teaching the compiler a special shadow primitive. Evidence: – define-shader-abstraction adds an open EQL-method source vocabulary beside the core define-shader-operator protocol;…
A sky-clock belongs to the luvcraft session because it has mutable runtime identity worth inspecting: time, rate, paused state, and an optional pinned time for deterministic capture. A sky profile is ordinary data: keyframes for sky/horizon colour, primary-light colour, ambient colour, fog, and exposure. There is no…
Moppe first supplied the motivation: its Metal renderer proves mesh shaders, MetalFX, and a finished post stack on the same Apple hardware, while MoltenVK cannot expose every native capability. That source evidence remains on the Moppe legacy page. The implementation claim now belongs here. The current backend is…
Moppe's shafts_gather_fragment marches view rays at half resolution through the existing shadow map, jitters them with interleaved-gradient noise, stops at scene depth, and weights lit spans by a forward Henyey-Greenstein lobe with g = 0.60. A separate pass filters and adds the result. Luvcraft already owns both…
The plan of #SKHDR is built, and the shape it took is worth recording because two of its decisions were made by the implementation rather than by the plan. The scene attachment is :rgba16-float and every scene-stage pipeline targets it: block surfaces, the sky triangle, world text, the terminal wall's glyph and cell…
Intent: #VG8TGG shipped the cheap radial sweep because terrain which occludes the sun is already dark in the bright image. #BAP0QU's marched version is strictly better informed: it knows about occluders which are off screen or behind the camera, and it produces beams in air the bright image says nothing about. …
Intent: when #WLHDRB lands the linear-HDR scene target, extend it past tone map and restrained bloom toward Moppe's observed order: exposure, ACES, and a small live grade. Treat sun shafts (#BAP0QU) as the first post effect after bloom because both inputs already exist. Observed: luvcraft's presentation stage now…