simvx.graphics.renderer.layer_post

Per-CanvasLayer post-processing chain (design §5.6).

A :class:LayerPostChain post-processes ONE CanvasLayer band whose environment Property is set. It is created lazily, the first frame that band is both opted-in AND present, so a scene with no per-layer environment allocates nothing here (the zero-cost-when-unused contract: the renderer never instantiates this class unless Renderer._layer_post_specs is non-empty).

Pipeline (mirrors the global 2D-in-HDR + bloom path, scoped to one band):

  1. Draw the band’s 2D items into an offscreen RGBA16F HDR target (cleared transparent, alpha 0) via a band-filtered bindless submit. Only items whose layer column equals this band are drawn (submit.build_bindless_geometry only_band=).

  2. Run :class:~simvx.graphics.renderer.bloom_pass.BloomPass on that HDR colour to produce the glow (when the band env enabled bloom).

  3. Composite onto the swapchain with layer_post_composite.frag: bloom add + tonemap + vignette / grain / chromatic, with the band’s COVERAGE ALPHA preserved, alpha-blended over whatever is already on the swapchain. The host composites the bands in ascending-band order so painter order with the plain bands (drawn through the global path) is correct.

Everything is reused (RenderTarget, BloomPass, the bindless 2D submitter, the WorldEnvironment effect surface); the only new artefact is the composite shader, which is plumbing (a tonemap-with-preserved-alpha blit), not a new effect class.

Module Contents

Classes

LayerPostSpec

Resolved, render-thread-readable snapshot of a band env’s post settings.

LayerPostChain

Lazily-created per-band HDR target + bloom + composite (design §5.6).

Data

API

simvx.graphics.renderer.layer_post.__all__

[‘LayerPostChain’, ‘LayerPostSpec’]

class simvx.graphics.renderer.layer_post.LayerPostSpec(env: Any)[source]

Resolved, render-thread-readable snapshot of a band env’s post settings.

Built by environment_sync from a CanvasLayer’s environment WorldEnvironment. Flat scalars only (no node references) so the render thread never touches the live scene tree.

Initialization

__slots__

(‘bloom_enabled’, ‘bloom_threshold’, ‘bloom_intensity’, ‘vignette_enabled’, ‘vignette_intensity’, ‘v…

__eq__(other: Any) bool[source]
applies() bool[source]

Whether this band actually needs a post chain (any effect enabled).

class simvx.graphics.renderer.layer_post.LayerPostChain(engine: Any, band: int, text_pass: Any)[source]

Lazily-created per-band HDR target + bloom + composite (design §5.6).

One instance per opted-in, present band. Built against the current swapchain extent; recreated on resize. The renderer reaps it when the band’s env is cleared (mirrors the velocity/occlusion lazy-pass cleanup).

Initialization

sync_atlas_slot(slot: int) None[source]

Mirror the swapchain pass’s MSDF atlas slot (shared bindless array).

render_band_hdr(cmd: Any, view: Any, camera: tuple, ui_size: tuple[int, int]) None[source]

Draw this band’s items into the HDR target, then run bloom (outside it).

Records the offscreen HDR render pass (cleared transparent) with the band’s items, ends it, then runs bloom on the resulting colour. Bloom records its own passes (illegal to nest), so it must run after the HDR pass ends.

configure(spec: simvx.graphics.renderer.layer_post.LayerPostSpec) None[source]

Apply the band env’s settings (bloom threshold/intensity etc.).

composite(cmd: Any, width: int, height: int) None[source]

Alpha-blend this band’s post result onto the current (swapchain) pass.

cleanup() None[source]