simvx.graphics.renderer.light2d_pass

2D light accumulation pass: renders Light2D nodes as additive radial gradients.

Renders each light as a screen-space quad with radial falloff. The accumulated light texture is provided to Draw2DPass for final compositing (multiply blend).

Shadow casting (desktop, POINT + DIRECTIONAL lights) follows the FROZEN Phase-0 spec (shadow_ref.py). Three GPU stages, run only when a frame has at least one shadow-casting light AND at least one occluder:

S1 rasterise occluder triangles into a screen-sized R8 coverage mask (light2d_occluder.*). S2 build a 1D shadow atlas (R16F, W columns x MAX_SHADOW_LIGHTS rows): each shadow light ray-marches the occ mask into its own row (light2d_shadowmap.*, one draw per light into a 1-px viewport strip). S3 the disk fragment shader (light2d.frag) PCF-samples its atlas row and folds visibility into the lit colour.

When no light casts a shadow the atlas/mask are never allocated and every light pushes shadow_row = -1 -> byte-identical to the pre-shadow path.

Module Contents

Classes

Light2DPass

GPU pass that renders 2D lights to an offscreen accumulation texture.

Data

API

simvx.graphics.renderer.light2d_pass.__all__

[‘Light2DPass’]

simvx.graphics.renderer.light2d_pass.log

‘getLogger(…)’

simvx.graphics.renderer.light2d_pass.PUSH_SIZE

88

simvx.graphics.renderer.light2d_pass.OCC_PUSH_SIZE

8

simvx.graphics.renderer.light2d_pass.SM_PUSH_SIZE

32

simvx.graphics.renderer.light2d_pass.SHADOW_MAP_RESOLUTION

256

simvx.graphics.renderer.light2d_pass.MAX_SHADOW_LIGHTS

16

simvx.graphics.renderer.light2d_pass.RAYMARCH_STEPS

256

simvx.graphics.renderer.light2d_pass.N_PCF

5

simvx.graphics.renderer.light2d_pass.MAX_GRADIENT_SETS

32

class simvx.graphics.renderer.light2d_pass.Light2DPass(engine: Any)[source]

GPU pass that renders 2D lights to an offscreen accumulation texture.

Usage from the forward renderer: 1. begin_frame(): clears per-frame submission lists 2. submit_light(...) / submit_occluder(...): queue data 3. render(cmd, extent): render all lights to accumulation RT 4. get_light_texture_view(): returns the image view for compositing

Initialization

setup() None[source]

Create GPU resources: shaders, pipeline, render target.

submit_light(position: tuple[float, float], colour: tuple[float, float, float], energy: float, light_range: float, falloff: float = 1.0, inner_radius: float = 0.0, falloff_gradient: Any = None, blend_mode: str = 'add', shadow_enabled: bool = False, shadow_colour: tuple[float, ...] = DEFAULT_SHADOW_COLOUR, shadow_softness: float = 1.0, light_type: str = 'point', direction: tuple[float, float] = (0.0, -1.0)) None[source]

Queue a light for rendering this frame.

falloff_gradient is an optional 1-D intensity LUT (float array in [0, 1]) that overrides the analytic falloff; it is uploaded as a 1-row texture and sampled by the remapped distance.

light_type / direction describe the light for shadow casting. "point" builds/samples a radial shadow map; "directional" builds an orthographic 1D map along perp(direction) and renders a flat fullscreen contribution.

submit_occluder(polygon_vertices: list[tuple[float, float]]) None[source]

Queue an occluder polygon for shadow casting this frame.

begin_frame() None[source]

Clear per-frame submission lists.

render(cmd: Any, extent: tuple[int, int], lights: list[dict] | None = None, occluders: list[list[tuple[float, float]]] | None = None) None[source]

Render all queued lights to the accumulation render target.

Must be called outside the main render pass (in pre_render phase).

lights / occluders default to the live self._lights / self._occluders (the synchronous path). In pipelined mode the render thread passes the packet’s OWNED snapshots so it never reads the live lists the main thread is concurrently rebuilding.

get_light_texture_view() Any[source]

Return the light accumulation image view for compositing.

get_light_sampler() Any[source]

Return the sampler for the light accumulation texture.

property has_lights: bool[source]

True if any lights were submitted this frame.

cleanup() None[source]

Destroy all GPU resources.