simvx.graphics.renderer.shadow_math

Backend-agnostic shadow math.

Computes directional-light cascaded-shadow-map (CSM) split distances and per-cascade light view-projection matrices. Pure NumPy — no Vulkan, no WebGPU — so both desktop renderer and web streaming serializer share the same implementation.

Matrices follow SimVX’s row-major convention on the Python side. The cascade VPs are returned in row-major layout; callers that hand them to a column-major GPU API (Vulkan, WebGPU) must transpose at the boundary.

Module Contents

Functions

depth_to_ndc

Convert eye-space depth to Vulkan/WebGPU NDC z [0, 1].

compute_splits

Return cascade_count + 1 split distances in eye space.

compute_cascades

Compute CSM cascade splits and row-major light VP matrices.

Data

API

simvx.graphics.renderer.shadow_math.__all__

[‘DEFAULT_CASCADE_COUNT’, ‘DEFAULT_LAMBDA’, ‘compute_cascades’, ‘compute_splits’, ‘depth_to_ndc’]

simvx.graphics.renderer.shadow_math.DEFAULT_CASCADE_COUNT

3

simvx.graphics.renderer.shadow_math.DEFAULT_LAMBDA

0.5

simvx.graphics.renderer.shadow_math.DEFAULT_PADDING

0.1

simvx.graphics.renderer.shadow_math.depth_to_ndc(z_eye: float, proj: numpy.ndarray) float[source]

Convert eye-space depth to Vulkan/WebGPU NDC z [0, 1].

proj is a row-major 4×4 perspective matrix. Uses the standard Vulkan convention (clip_z = proj[2][2]·(-z_eye) + proj[2][3], clip_w = z_eye).

simvx.graphics.renderer.shadow_math.compute_splits(near: float, far: float, cascade_count: int = DEFAULT_CASCADE_COUNT, lambda_split: float = DEFAULT_LAMBDA) numpy.ndarray[source]

Return cascade_count + 1 split distances in eye space.

Uses the practical split scheme — blends logarithmic and linear splits by lambda_split. Matches Unity URP / UE / Godot tuning.

simvx.graphics.renderer.shadow_math.compute_cascades(view: numpy.ndarray, proj: numpy.ndarray, light_dir: numpy.ndarray, near: float | None = None, far: float | None = None, cascade_count: int = DEFAULT_CASCADE_COUNT, lambda_split: float = DEFAULT_LAMBDA, padding: float = DEFAULT_PADDING, max_far: float = 300.0) tuple[numpy.ndarray, numpy.ndarray][source]

Compute CSM cascade splits and row-major light VP matrices.

near / far default to values extracted from proj and are clamped at max_far to keep shadow-map resolution reasonable for wide-open scenes.

Returns (cascade_vps[cascade_count, 4, 4], splits[cascade_count + 1]) where cascade_vps are row-major 4×4 (transpose at the GPU boundary).