For What Lies Beneath · Godot 4.6.3 · 100% code

VFX Build-Out Grind

Fourteen VFX systems built, verified, and committed in one unattended run — each proven on the native render lane and frame-read before landing. Watch the clips; each has a writeup on what it is, how it works, and what to look for.

14 commits
6 waves
8 new demo studios
6 reusable modules
launch any: FWLB_STUDIO=<name>
WAVE 1

HD sprites in the pixel world

The "inverse FFT" question — can a crisp hi-res character live convincingly inside the chunky 480×270 voxel world? Two pieces: proving per-pixel depth occlusion works, and measuring why zoomed-in sprites look janky.

Depth-clip probe — per-pixel occlusion by the pixel world

FWLB_STUDIO=depthclipb304fb1 · 35e8b41

A native-resolution HD sprite (a chroma-keyed skeleton) is occluded per-pixel by the 480 world. The trick: occluders render their linear view-depth into a separate 480×270 SubViewport, and the sprite's canvas shader samples that depth with NEAREST filtering — so the bite edge snaps to the world's pixel grid (chunky, not smooth). That's deliberate: the sprite stays crisp inside, but where it meets the world it's occluded by the world's own pixels, which is what makes the res-contrast read as authored rather than a floating cutout.

It also demonstrates correctness, not just "any geometry hides it": the orange pillar bites the left, the blue block bites the head, the magenta block bites the shins — all simultaneously and per-pixel — while the teal block behind the sprite does NOT bite (the skeleton's ribs draw over it). That's true depth. A first-pass world-light + shadow transfer is wired too (the sprite tints to the scene light; a ground shadow).

Watch for: the bite edges are stair-stepped at the world's pixel size (cohesive), and as the camera orbits the bites track live; the teal behind-block never cuts into the figure.

Resolution A/B — why zoomed-in sprites go janky

FWLB_STUDIO=sprite_ab9c440f3

The same portrait, the same breathing scale-sin, three ways at matched on-screen size. 480-smooth (billboard in the world, sub-pixel scale) resamples to mush. 480-snap (scale quantized to the pixel grid) is crisp but the animation steps — it kills a smooth idle. Native-HD (on the overlay layer) is the only path that's crisp and smooth, retaining ~3× the detail.

Takeaway: the 480 buffer forces smooth-but-muddy OR crisp-but-steppy. Animated HD characters need the native layer — which is exactly what the depth-clip probe above composites. Full decision matrix in docs/SPRITE-RESOLUTION-PATHS.md.
WAVE 2

Energy trails

Plasma · electric · ember — one ribbon, three looks

FWLB_STUDIO=trailb30b7fe

A projectile/spell trail is a camera-facing ribbon rebuilt every frame from a ring buffer of the head's recent positions (the same strip technique the effects library uses for its ribbons). The shader scrolls two-rate noise along the length with a bright transverse centerline; a ridge lever thresholds it thin for the electric arc. Head→tail fade and taper are carried in the vertex color.

Watch for: the soft cyan plasma body, the thin jittery white-cyan electric filament, and the warm posterized ember trail — then a fast diagonal sword-slash arc. VfxTrail.attach() follows any moving node; sweep() is a one-shot arc.

WAVE 3

Cashing in the noise engine

One posterized FBM+domain-warp shader was already driving lava/water/orbs. This wave spends it across five real gameplay systems.

Dissolve / materialize

FWLB_STUDIO=dissolve1992f45

A sprite is eaten away (or built up) along a noise threshold, leaving a hot HDR burn edge. Directional bias sweeps the burn up for death, down for spawn.

Watch for: a blob enemy materializes (cyan burn), idles, then dissolves on death (ember burn) — the interior discards, not fades.

Status auras

FWLB_STUDIO=status9133c7a

A noise billboard per status (burning/poison/frost/shield/rage) that tracks the unit and composes with the existing emote tints. Stacks cleanly.

Watch for: the character walks under the first aura (it follows), cycles all five, then holds burning + poison stacked.

AoE fields + hazard tiles

FWLB_STUDIO=fieldf61dddc

Timed circular spell fields (fire nova / poison cloud / frost zone) that pop in, sustain, and fade; plus persistent per-cell tile hazards snapped to the game grid.

Watch for: the three fields, then an L-shaped lava strip + a toxic pool with a character crossing them.

Weather

FWLB_STUDIO=weather7c74eb4

Wires the sky sim's drifting cloud-cover (which shadows the terrain) plus a falling-particle overlay for rain/snow/ash.

Watch for: clear → rain → storm (darkened, a rumble) → snowfall; the terrain mottles as cloud shadows drift.
WAVE 4

The distortion family

Summon black hole · dimensional cut · shockwave — one kernel

FWLB_STUDIO=distort3b5ed55

The cinematic-tier screen-space posts, refactored onto a single ScreenFX rig (CanvasLayer + back-buffer copy + full-screen shader). A small diegetic in-world rift opens the reel; then the full-screen summon black hole (gravitational lensing + chromatic aberration, verified pixel-identical after the refactor), the dimensional cut (a slash tears the screen apart onto an energy void), and the new shockwave (an expanding radial impact ring).

Watch for: the world spiralling into the event horizon; the two halves sliding apart along the sword cut; the ring pushing the scene outward on impact.

Heat-haze over lava — caveat

FWLB_STUDIO=liquide3cfa58

A diegetic screen-read shimmer rising off a hot surface. Also the best look at the molten lava (Worley crust + glowing cracks + downhill flow on the real fluid sim).

Honest caveat: the underlying distort_fx is a full-replace refraction (built for the black hole), so over the very bright, high-contrast molten crust the haze reads as prominent patches, not a subtle shimmer. Shipped as a valid primitive (subtle over lower-contrast surfaces); the real fix — a dedicated additive-perturbation haze shader — is logged as a follow-on.
WAVE 5

Anti-occlusion & the info layer

Wall-fade · x-ray silhouette · gated nameplate

FWLB_STUDIO=occlusione50b125 · 29092ad

For a unit you command, total occlusion is bad UX — so this is the anti-occlusion doctrine. A camera→unit raycast (against a real collider pillar) drives three responses as the camera orbits: wall-fade (the blocking pillar goes translucent), x-ray silhouette (a cyan ghost shows the unit through the wall), and a gated nameplate (the label fades while the unit is hidden). Note: dither "screen-door" fade was verified unimplemented in this renderer, so wall-fade uses real alpha.

Watch for: the standout is the x-ray — Ryu fully behind the pillar reads as a clean cyan silhouette drawn over it, then snaps back to solid when he clears.
WAVE 6

Cellular follow-ons

Water caustics

FWLB_STUDIO=liquid ARG=wateree90f66

A drifting Worley cell-web brightens the deeper water body — the classic caustic network. Gated so only the water preset has it; lava and the other fluids are untouched.

Watch for: the bright cell-web is denser in the deep zones, fainter in the shallows.

Cracked ground · obsidian

FWLB_STUDIO=noised5b69b9

A Worley cell lever on the noise engine adds two ground presets: cracked (dark earth with glowing ember veins) and obsidian (blue-black with cyan veins). The original presets are unchanged (the lever defaults off).

Watch for: the two new pools in the lower row, alongside the original lava/toxic/ water/orbs which all still read the same.

Your decisions (when you're ready)

  1. HD sprites — which characters go HD (heroes/bosses vs all units)? Lighting depth (the v1 light-tint vs per-pixel directional + a silhouette shadow)? Asset pipeline (commission alpha cutouts vs standardize the chroma-key bake)? Detail in docs/SPRITE-RESOLUTION-PATHS.md.
  2. iso_main integration — which systems into the real battle first? My ranking: status auras + hazard tiles → dissolve (death/spawn) → readable-text migration → the rest as spell content.
  3. Tuning — several defaults are dialed for demo legibility (aura size, caustics strength, weather density). Trivial to adjust to taste.

Suggested follow-ons