simvx.graphics.renderer.shadow_data

ShadowBuffer: the one shadow/ambient SSBO layout, defined once.

A single fixed std430 block on the forward descriptor set (set 0, binding 3), carrying the directional CSM matrices, the positional (point/spot) shadow caster slots, the ambient term and the debug gates. The layout is declared ONCE, as the GLSL text that cube_textured.frag embeds verbatim: the byte offsets and the block size are computed from that text by std430 rules, so the table and the shader cannot drift apart (a layout test pins the published offsets and the frag mirror).

Writers pack fields by name through :func:write_uint, :func:write_vec4 and

func:

write_mat4, so a misspelled field, a wrong-typed field or an out-of-range array index raises instead of silently shifting lighting data by one slot.

No published offset ever moves: a new field goes at the end, or takes over one of the reserved words already sitting in the block (which is how the atlas row count arrived, so a zeroed block still reads as the historical single row). Positional caster slot 0 therefore keeps the original point_light_pos_range / spot_vp / spot_light_pos_range fields, and slots 1.. live in the appended *_caster_* arrays indexed by slot - 1. A single-caster frame writes nothing into the appended region.

Module Contents

Functions

field_offset

Byte offset of field (element index for an array field).

caster_field

Resolve a positional caster slot to the field and index that hold it.

write_uint

Write a uint field by name.

write_vec4

Write a vec4 field by name from any 4-float sequence or array.

write_mat4

Write a mat4 field by name from a 4x4 (or 16-element) array.

zeroed

Return an all-zero block of the canonical size.

write_ambient

Pack the scene ambient: colour decoded into rgb, energy into a.

defaults

Return the no-shadow default block: lit sentinels plus the ambient fill.

Data

API

simvx.graphics.renderer.shadow_data.__all__

[‘CASCADE_COUNT’, ‘DEFAULT_AMBIENT_COLOUR’, ‘DEFAULT_SHADOW_CASTER_COUNT’, ‘MAX_SHADOW_CASTERS’, ‘NO…

simvx.graphics.renderer.shadow_data.SHADOW_DATA_BINDING

3

simvx.graphics.renderer.shadow_data.CASCADE_COUNT

None

simvx.graphics.renderer.shadow_data.MAX_SHADOW_CASTERS

8

simvx.graphics.renderer.shadow_data.DEFAULT_SHADOW_CASTER_COUNT

1

simvx.graphics.renderer.shadow_data.NO_SHADOW_TEXTURE

4294967295

simvx.graphics.renderer.shadow_data.DEFAULT_AMBIENT_COLOUR

(0.15, 0.15, 0.2, 1.0)

simvx.graphics.renderer.shadow_data.SHADOW_DATA_GLSL

None

simvx.graphics.renderer.shadow_data.SHADOW_DATA_FIELD_OFFSETS: dict[str, int]

None

simvx.graphics.renderer.shadow_data.field_offset(field: str, index: int = 0) int

Byte offset of field (element index for an array field).

simvx.graphics.renderer.shadow_data.caster_field(base: str, slot: int) tuple[str, int]

Resolve a positional caster slot to the field and index that hold it.

base is the slot-0 field name (point_light_pos_range, spot_vp or spot_light_pos_range). Slot 0 answers with that field itself, since the block is append-only and those offsets are published; slots 1.. answer with the appended array and index slot - 1.

simvx.graphics.renderer.shadow_data.write_uint(block: numpy.ndarray, field: str, value: int, index: int = 0) None

Write a uint field by name.

simvx.graphics.renderer.shadow_data.write_vec4(block: numpy.ndarray, field: str, values: object, index: int = 0) None

Write a vec4 field by name from any 4-float sequence or array.

simvx.graphics.renderer.shadow_data.write_mat4(block: numpy.ndarray, field: str, matrix: object, index: int = 0) None

Write a mat4 field by name from a 4x4 (or 16-element) array.

The matrix is written as-is: callers transpose to the shader’s column-major convention before packing, as they always have.

simvx.graphics.renderer.shadow_data.zeroed() numpy.ndarray

Return an all-zero block of the canonical size.

simvx.graphics.renderer.shadow_data.write_ambient(block: numpy.ndarray, colour: tuple[float, float, float], energy: float) None

Pack the scene ambient: colour decoded into rgb, energy into a.

Both writers of the live ambient go through this, so the shadow path and the shadow-free path cannot disagree about where the scene’s ambient lives. (defaults() and the buffer init write only the compiled-in default.)

The ambient is authored in sRGB and the shader multiplies it against an albedo the material packer has already decoded, so it decodes here. Here rather than at EnvironmentSync, because Renderer._ambient_colour is an attribute other code reads back and holds its own same-space default beside; this function is the one place every ambient value passes through. energy is an IBL scale, not a channel, and is untouched.

simvx.graphics.renderer.shadow_data.defaults() numpy.ndarray

Return the no-shadow default block: lit sentinels plus the ambient fill.

Every shadow texture index reads as “no shadow map”, so a frame uploaded from this block is lit exactly as an unshadowed scene.