simvx.core.world_environment

WorldEnvironment, Environment, and PostProcessEffect for SimVX.

Module Contents

Classes

PostProcessEffect

User-defined fullscreen post-processing shader effect.

WorldEnvironment

Scene-wide rendering settings: ambient, sky, fog, tonemapping and post-processing.

Environment

Environment resource that can be shared between WorldEnvironment nodes.

Data

log

API

simvx.core.world_environment.log

‘getLogger(…)’

class simvx.core.world_environment.PostProcessEffect(shader_code: str = '', *, enabled: bool = True, order: int = 0, language: str = 'glsl', wrap: str = 'clamp')[source]

User-defined fullscreen post-processing shader effect.

Holds fragment GLSL source, uniform values, enable state, and execution order. The graphics backend compiles the shader and executes it as a fullscreen pass.

Standard uniforms provided automatically to every effect: - u_time (float): elapsed time in seconds - u_resolution (vec2): screen resolution in pixels - u_colour_tex (sampler2D): current framebuffer colour - u_depth_tex (sampler2D): scene depth buffer (sample by normalised UV; under render-scale/TAAU it may be at a lower resolution than the colour)

Example::

effect = PostProcessEffect(
    shader_code="""
        void main() {
            vec2 uv = gl_FragCoord.xy / u_resolution;
            vec3 colour = texture(u_colour_tex, uv).rgb;
            frag_colour = vec4(vec3(dot(colour, vec3(0.299, 0.587, 0.114))), 1.0);
        }
    """,
    order=10,
)
effect.set_uniform("intensity", 0.5)
world_env.add_post_process(effect)

Initialization

__slots__

(‘_shader_code’, ‘_enabled’, ‘_order’, ‘_uniforms’, ‘_uniform_types’, ‘_dirty’, ‘_language’, ‘_wrap’…

WRAP_MODES

(‘clamp’, ‘repeat’, ‘mirror’)

property language: str[source]

Shader language: ‘glsl’ (default) or ‘wgsl’ (WebGPU).

property wrap: str[source]

Addressing for u_colour_tex taps outside [0,1]: ‘clamp’ (default), ‘repeat’, or ‘mirror’.

‘clamp’ matches the scene-colour behaviour of the built-in screen-space passes and is correct for edge-neighbourhood sampling. Choose ‘repeat’/’mirror’ only for an effect that deliberately tiles or reflects the framebuffer (scroll, kaleidoscope).

property shader_code: str[source]

Fragment shader source (the body; version/layout is auto-wrapped by the renderer).

property enabled: bool[source]
property order: int[source]

Execution priority: lower values run first.

property uniforms: dict[str, Any][source]

Read-only copy of current uniform values.

property dirty: bool[source]

Whether the shader or uniforms have changed since last GPU sync.

clear_dirty() None[source]

Mark as synced with GPU (called by the renderer).

set_uniform(name: str, value: Any) None[source]

Set a shader uniform value. Type is inferred from the value.

Supported: float, int, vec2/3/4 (tuple or ndarray), mat4 (4x4 ndarray).

get_uniform(name: str) Any[source]

Get current uniform value. Raises KeyError if not set.

__repr__() str[source]
class simvx.core.world_environment.WorldEnvironment(name: str = 'WorldEnvironment', **kwargs)[source]

Bases: simvx.core.node.Node

Scene-wide rendering settings: ambient, sky, fog, tonemapping and post-processing.

This node is how a scene talks to the renderer. Add one anywhere in the tree and set its properties; the backend reads them each frame. Never reach for the renderer directly.

Only the first WorldEnvironment found in the tree drives the global settings (the renderer resolves it with root.find(WorldEnvironment)), so a scene should have exactly one. Custom :class:PostProcessEffect instances are the exception: those are collected from every WorldEnvironment in the tree, so an additive effect can ride along on a sub-scene’s own node.

A scene with no WorldEnvironment renders at the backend’s built-in defaults; that absence is also what keeps a pure-2D scene out of the HDR post path entirely. Adding the node is therefore an opt-in, and every heavyweight feature on it (bloom, SSAO, SSR, SSGI, TAA, volumetric fog, occlusion culling, depth of field) is off by default so it stays zero-cost until asked for.

Properties are grouped for the inspector: Ambient, Fog, Tonemap, Bloom, Quality, Shadows, SSAO, Reflections, Global Illumination, Weather, Film Effects, Anti-Aliasing, Colour Grading, Sky, Depth of Field, Motion Blur, Culling, Performance and Debug.

How ambient works. Three layers combine, gated by ambient_mode:

  • the flat fill ambient_light_colour, which every surface always gets and which stops an unlit scene going pure black,

  • image-based lighting from the sky or environment_map, scaled by ambient_light_energy,

  • nearby ReflectionProbe3D captures, blended over the IBL.

ambient_mode is a ceiling, not a switch: "probe" (the default) allows all three, "ibl" drops the probe blend, "flat" leaves only the flat fill. Each layer also self-gates on what the scene actually has, so a scene with no sky falls back to the flat fill even under "probe".

Tuning the look. ambient_light_energy and tonemap_exposure are the two dials to reach for first: the former decides how much the sky bleeds into shadowed surfaces, the latter how bright the whole frame lands before tonemapping (and it composes with Camera3D.exposure).

Example::

env = WorldEnvironment()
env.sky_mode = "procedural"      # sun-driven Preetham sky + IBL
env.ambient_light_energy = 0.5   # let more sky bounce into the shade
env.fog_enabled = True
env.bloom_enabled = True
root.add_child(env)

Initialization

ambient_light_colour

‘Colour(…)’

ambient_light_energy

‘Property(…)’

ambient_light_mode

‘Property(…)’

ambient_mode

‘Property(…)’

ambient_light_2d

‘Colour(…)’

fog_enabled

‘Property(…)’

fog_colour

‘Colour(…)’

fog_density

‘Property(…)’

fog_start

‘Property(…)’

fog_end

‘Property(…)’

fog_mode

‘Property(…)’

fog_height

‘Property(…)’

fog_height_density

‘Property(…)’

tonemap_mode

‘Property(…)’

tonemap_exposure

‘Property(…)’

tonemap_white

‘Property(…)’

bloom_enabled

‘Property(…)’

bloom_threshold

‘Property(…)’

bloom_intensity

‘Property(…)’

bloom_soft_knee

‘Property(…)’

quality_tier

‘Property(…)’

probe_blend_count

‘Property(…)’

probe_face_size

‘Property(…)’

shadow_caster_count

‘Property(…)’

render_scale

‘Property(…)’

scene_feedback_max_depth

‘Property(…)’

shadow_debug_cascades

‘Property(…)’

debug_view

‘Property(…)’

shadow_cascade_count

‘Property(…)’

volumetric_fog_enabled

‘Property(…)’

volumetric_fog_density

‘Property(…)’

volumetric_fog_albedo

‘Colour(…)’

volumetric_fog_emission

‘Colour(…)’

volumetric_fog_anisotropy

‘Property(…)’

volumetric_fog_length

‘Property(…)’

volumetric_fog_gi_inject

‘Property(…)’

volumetric_fog_temporal_reprojection

‘Property(…)’

ssao_enabled

‘Property(…)’

ssao_radius

‘Property(…)’

ssao_bias

‘Property(…)’

ssao_intensity

‘Property(…)’

ssao_normals

‘Property(…)’

ssr_enabled

‘Property(…)’

ssr_intensity

‘Property(…)’

ssr_max_distance

‘Property(…)’

ssr_roughness_cutoff

‘Property(…)’

ssgi_enabled

‘Property(…)’

ssgi_intensity

‘Property(…)’

ssgi_max_distance

‘Property(…)’

wind_direction

‘Property(…)’

wind_strength

‘Property(…)’

wind_gustiness

‘Property(…)’

wetness

‘Property(…)’

rain_intensity

‘Property(…)’

ripple_strength

‘Property(…)’

occlusion_culling_enabled

‘Property(…)’

render_mode

‘Property(…)’

dof_enabled

‘Property(…)’

dof_focus_distance

‘Property(…)’

dof_focus_range

‘Property(…)’

dof_max_coc

‘Property(…)’

motion_blur_enabled

‘Property(…)’

motion_blur_intensity

‘Property(…)’

motion_blur_samples

‘Property(…)’

film_grain_enabled

‘Property(…)’

film_grain_intensity

‘Property(…)’

vignette_enabled

‘Property(…)’

vignette_intensity

‘Property(…)’

vignette_smoothness

‘Property(…)’

chromatic_aberration_enabled

‘Property(…)’

chromatic_aberration_intensity

‘Property(…)’

crt_enabled

‘Property(…)’

crt_intensity

‘Property(…)’

pixelate_enabled

‘Property(…)’

pixelate_size

‘Property(…)’

blur_enabled

‘Property(…)’

blur_radius

‘Property(…)’

fxaa_enabled

‘Property(…)’

taa_enabled

‘Property(…)’

colour_grading_enabled

‘Property(…)’

lut_enabled

‘Property(…)’

lut_tex_id

‘Property(…)’

sky_mode

‘Property(…)’

sky_colour_top

‘Colour(…)’

sky_colour_bottom

‘Colour(…)’

sky_texture

‘Property(…)’

sky_turbidity

‘Property(…)’

sky_ground_albedo

‘Colour(…)’

environment_map

‘Property(…)’

property env_dirty: bool[source]
clear_env_dirty() None[source]
__setattr__(name: str, value: Any) None[source]
add_post_process(effect: simvx.core.world_environment.PostProcessEffect) None[source]

Register a custom post-processing effect.

remove_post_process(effect: simvx.core.world_environment.PostProcessEffect) None[source]

Unregister a custom post-processing effect.

get_post_processes() list[simvx.core.world_environment.PostProcessEffect][source]

Return registered effects sorted by order.

strict_errors: ClassVar[bool]

True

dev_checks: ClassVar[bool]

None

script_error_raised

‘Signal(…)’

dynamic: bool

False

visible

‘Property(…)’

update_mode

‘Property(…)’

__properties__: ClassVar[dict[str, simvx.core.descriptors.Property]]

None

classmethod __init_subclass__(**kwargs)
property name: str
property visible_in_tree: bool
reset_error() None
add_child(node: simvx.core.node.T) simvx.core.node.T
remove_child(node: simvx.core.node.Node) None
reparent(new_parent: simvx.core.node.Node)
node_at(path, default=_NO_DEFAULT)
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
expect(target, *, direct: bool = False)
ancestor(target)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
property is_scene_root: bool
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_enter_tree() None
on_exit_tree() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
queue_redraw() None
property render_dirty: bool
clear_children()
destroy()
property destroying: bool
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.world_environment.Environment[source]

Environment resource that can be shared between WorldEnvironment nodes.

Initialization

add_post_process(effect: simvx.core.world_environment.PostProcessEffect) None[source]

Register a custom post-processing effect.

remove_post_process(effect: simvx.core.world_environment.PostProcessEffect) None[source]

Unregister a custom post-processing effect.

get_post_processes() list[simvx.core.world_environment.PostProcessEffect][source]

Return registered effects sorted by order.