simvx.core.water¶
WaterSurface3D + WaterMaterial: a built-in animated water plane (design D16).
Water is a dedicated built-in render pass (its own GLSL + WGSL shader pair,
like the tilemap / grid passes), NOT a ShaderMaterial. A :class:WaterSurface3D
node places a horizontal grid whose vertices are displaced by a sum of Gerstner
waves in the vertex stage (direction + strength taken from the FrameGlobals wind
slot, phase from FrameGlobals time), and whose fragment stage refracts the scene
behind it (sampling the scene-colour/depth copy), fades to a deep-water tint with
depth, mixes a Fresnel reflection from the environment, and adds shore foam where
the water meets geometry.
The appearance knobs live on the :class:WaterMaterial value object (mirrors
FogMaterial / Material); geometry (extent + tessellation) lives on the
node. The presence of any visible WaterSurface3D in the scene is what makes
the desktop renderer split the opaque/transparent pass to produce the scene
colour/depth copy the refraction reads; with no water surface the split never
happens and the frame is byte-identical (zero-cost when unused).
Module Contents¶
Classes¶
Appearance of a :class: |
|
A horizontal animated water plane rendered by the built-in water pass. |
Data¶
API¶
- simvx.core.water.__all__¶
[‘WaterMaterial’, ‘WaterSurface3D’]
- class simvx.core.water.WaterMaterial(*, shallow_colour: tuple[float, float, float] = (0.1, 0.38, 0.42), deep_colour: tuple[float, float, float] = (0.02, 0.09, 0.16), depth_fade_distance: float = 3.0, wave_amplitude: float = 0.18, wave_steepness: float = 0.55, wave_length: float = 6.0, wave_direction: float = 0.6, direction_spread: float = 0.8, wave_speed: float = 1.0, normal_scroll_speed: float = 0.05, normal_strength: float = 0.5, foam_colour: tuple[float, float, float] = (0.9, 0.95, 1.0), foam_amount: float = 0.6, refraction_strength: float = 0.35, fresnel_power: float = 5.0, roughness: float = 0.04, opacity: float = 0.92)[source]¶
Appearance of a :class:
WaterSurface3D(a plain value object).Assign one to
WaterSurface3D.material; the renderer reads these fields each frame. All colours are linear RGB. Wave direction and strength are modulated by the sceneWorldEnvironmentwind (FrameGlobals): with no wind the base direction/amplitude below drive the motion, so water animates out of the box.Attributes: shallow_colour: Water tint over shallow geometry (RGB, near the shore). deep_colour: Water tint over deep geometry (RGB, far from the shore). depth_fade_distance: World distance over which shallow blends to deep and transparency ramps to opaque. wave_amplitude: Base peak height of the Gerstner sum, in world units. wave_steepness: Gerstner steepness 0..1 (0 rolling swell, 1 sharp crests). wave_length: Base wavelength of the longest Gerstner wave, world units. wave_direction: Base travel direction, radians in the XZ plane (used when the wind strength is ~0; otherwise wind direction leads). direction_spread: Angular fan of the four Gerstner components, radians. wave_speed: Multiplier on wave phase speed. normal_scroll_speed: Scroll rate of the two detail-ripple normal layers. normal_strength: Intensity of the detail ripples added to the wave normal. foam_colour: Shore-foam colour (RGB). foam_amount: Depth band (world units) over which shore foam appears. refraction_strength: Screen-space refraction offset scale (world units). fresnel_power: Fresnel exponent for the reflection/refraction blend. roughness: Surface roughness for the environment reflection sample. opacity: Overall surface opacity ceiling (deep water) 0..1.
Initialization
- __slots__¶
(‘shallow_colour’, ‘deep_colour’, ‘depth_fade_distance’, ‘wave_amplitude’, ‘wave_steepness’, ‘wave_l…
- class simvx.core.water.WaterSurface3D(material: simvx.core.water.WaterMaterial | None = None, reflection=None, **kwargs)[source]¶
Bases:
simvx.core.nodes_3d.node3d.Node3DA horizontal animated water plane rendered by the built-in water pass.
Place the node at the water level: its world XZ plane (local +Y up) is the still surface, extended to
sizeworld units and tessellated intosubdivisions×subdivisionscells for the Gerstner displacement. The fragment stage refracts and depth-fades against the scene behind it, so put submerged geometry below the plane and a directional light + sky above.Example::
water = WaterSurface3D(position=(0, 0, 0), size=(40, 40)) water.material = WaterMaterial(wave_amplitude=0.25) scene.add_child(water)
Properties: size: Water plane extent in world units (x, z). subdivisions: Grid resolution per axis (higher = smoother crests). visible: Standard Node visibility; a hidden surface neither draws nor triggers the scene colour/depth copy.
Initialization
- size¶
‘Property(…)’
- subdivisions¶
‘Property(…)’
- gizmo_colour¶
‘Property(…)’
- property material: simvx.core.water.WaterMaterial[source]¶
The :class:
WaterMaterialcontrolling this surface’s appearance.
- property reflection[source]¶
Optional :class:
PlanarReflection3Dfeeding a true planar mirror (RM-E2).When set, the surface samples this node’s live capture as its reflection (a real mirror of the world above the water) instead of the environment cubemap, blended against the refraction below by Fresnel and rippled by the wave normal. The node must sit on the water plane (same world Y, its world +Y as the plane normal), exactly like a mirror floor; drop it in as a child and assign it here.
Nonekeeps the cubemap/sky reflection, so a surface with no reflection is byte-identical to the RM-E1 water.
- get_gizmo_lines() list[tuple[simvx.core.math.types.Vec3, simvx.core.math.types.Vec3]][source]¶
Editor gizmo: the still-surface rectangle at the node’s world plane.
- position¶
‘_SpatialVecProperty(…)’
- rotation¶
‘Property(…)’
- scale¶
‘_SpatialVecProperty(…)’
- render_layer¶
‘Property(…)’
- property rotation_degrees: simvx.core.math.types.Vec3¶
- property world_position: simvx.core.math.types.Vec3¶
- property world_rotation: simvx.core.math.types.Quat¶
- property world_scale: simvx.core.math.types.Vec3¶
- property forward: simvx.core.math.types.Vec3¶
- property right: simvx.core.math.types.Vec3¶
- property up: simvx.core.math.types.Vec3¶
- translate(offset: tuple[float, float, float] | numpy.ndarray)¶
- translate_global(offset: tuple[float, float, float] | numpy.ndarray)¶
- rotate(axis: tuple[float, float, float] | numpy.ndarray, angle: float)¶
- rotate_x(angle: float)¶
- rotate_y(angle: float)¶
- rotate_z(angle: float)¶
- look_at(target: tuple[float, float, float] | numpy.ndarray, up=None)¶
- face_along(forward: tuple[float, float, float] | numpy.ndarray, up: tuple[float, float, float] | numpy.ndarray | None = None) None¶
- set_render_layer(index: int, enabled: bool = True) None¶
- is_on_render_layer(index: int) bool¶
- wrap_bounds(bounds: tuple[float, float, float] | numpy.ndarray, margin: float = 1.0)¶
- strict_errors: ClassVar[bool]¶
True
- script_error_raised¶
‘Signal(…)’
- dynamic: bool¶
False
- classmethod __init_subclass__(**kwargs)¶
- property name: str¶
- property update_mode: simvx.core.descriptors.UpdateMode¶
- property visible: bool¶
- reset_error() None¶
- add_child(node: simvx.core.node.Node) simvx.core.node.Node¶
- remove_child(node: simvx.core.node.Node)¶
- reparent(new_parent: simvx.core.node.Node)¶
- get_node(path: str) simvx.core.node.Node¶
- get_node_or_none(path: str) simvx.core.node.Node | None¶
- find(target, *, direct: bool = False)¶
- find_all(target, *, direct: bool = False)¶
- walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]¶
- property path: str¶
- 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()¶
- 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__()¶