# WorldEnvironment `WorldEnvironment` is the canonical way to configure post-processing, sky, fog, and global rendering settings. Add one as a child of any node in your scene tree and set its properties: the renderer syncs them every frame. Never reach into the renderer directly. ## Basic Usage ```python from simvx.core import Node, WorldEnvironment, Camera3D class Game(Node): def on_ready(self): env = self.add_child(WorldEnvironment()) env.bloom_enabled = True env.bloom_threshold = 0.8 env.ssao_enabled = True env.tonemap_mode = "aces" env.tonemap_exposure = 1.2 self.add_child(Camera3D(position=(0, 3, 8))) ``` Only one `WorldEnvironment` should be active per scene; the renderer picks the first one it finds during scene submission. ## Property Groups All properties are real `Property` descriptors: inspector-visible, serializable, and groupable. | Group | Properties | |-------|-----------| | Ambient | `ambient_light_colour`, `ambient_light_energy`, `ambient_light_mode` | | Sky | `sky_mode`, `sky_colour`, `sky_texture`, `environment_map` | | Fog | `fog_enabled`, `fog_colour`, `fog_density`, `fog_start`, `fog_end`, `fog_mode`, `fog_height`, `fog_height_density` | | Volumetric Fog | `volumetric_fog_enabled`, `volumetric_fog_density`, `volumetric_fog_anisotropy`, `volumetric_fog_length`, `volumetric_fog_gi_inject`, `volumetric_fog_temporal_reprojection` | | Tonemap | `tonemap_mode` (`"linear"`, `"reinhard"`, `"aces"`, ...), `tonemap_exposure`, `tonemap_white` | | Bloom | `bloom_enabled`, `bloom_threshold`, `bloom_intensity`, `bloom_soft_knee` | | SSAO | `ssao_enabled`, `ssao_radius`, `ssao_bias`, `ssao_intensity` | | Depth of Field | `dof_enabled`, `dof_focus_distance`, `dof_focus_range`, `dof_max_coc` | | Motion Blur | `motion_blur_enabled`, `motion_blur_intensity`, `motion_blur_samples` | | Film Effects | `film_grain_enabled/intensity`, `vignette_enabled/intensity/smoothness`, `chromatic_aberration_enabled/intensity` | | Anti-Aliasing | `fxaa_enabled`, `taa_enabled` | | Colour Grading | `colour_grading_enabled`, `lut_enabled`, `lut_tex_id` | | Shadows | `shadow_cascade_count`, `shadow_debug_cascades` | | Quality | `quality_tier` (`"low"`, `"medium"`, `"high"`, `"auto"`) | ## Custom Post-Processing `PostProcessEffect` wraps a fragment shader as a fullscreen pass: ```python from simvx.core import PostProcessEffect grayscale = PostProcessEffect( shader_code=""" void main() { vec2 uv = gl_FragCoord.xy / u_resolution; vec3 c = texture(u_colour_tex, uv).rgb; frag_colour = vec4(vec3(dot(c, vec3(0.299, 0.587, 0.114))), 1.0); } """, order=10, ) grayscale.set_uniform("intensity", 0.5) env.add_post_process(grayscale) ``` Standard uniforms wired automatically: `u_time` (float), `u_resolution` (vec2), `u_colour_tex` (sampler2D), `u_depth_tex` (sampler2D). Effects run in `order` ascending after the built-in post chain. ## API Reference See {py:class}`simvx.core.WorldEnvironment`, {py:class}`simvx.core.Environment`, and {py:class}`simvx.core.PostProcessEffect`.