Skip to main content
realtime-wet-surfaces is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Real-time wetness on existing materials without losing their values — value-copying wet shader, geometry-driven wet mask, instance-uniform wet amount.

When your agent uses it

  • Make surfaces look wet when it rains and dry off afterwards
  • Add rain wetness to the level without redoing every material
  • Darken and gloss up the ground after rain, driven by a weather system
  • Wet cave, shoreline, or post-rain look on existing PBR materials

Install

summer setup installs every skill for your agent. To add only this one:
Swap claude-code for your agent, such as codex or cursor. See Skills for every option.

The skill

Outcome

Implement a real-time wetness effect in Summer Engine that can be applied to existing materials without losing their configured values (albedo, metallic, roughness, textures). The wet mask is driven by geometry alone (upward-facing surfaces collect wetness first), with a global/per-instance wet amount that can be animated at runtime. This follows the source technique: a pre-configured shader swap that keeps the standard material’s values, fed by a custom-function bridge.

When to Use

  • Rain, wet caves, shorelines, or post-rain scenes where surfaces should darken and become glossy in real time.
  • You need to wet many existing materials without re-authoring each one or losing its parameter values.
  • You want a wetness amount that a gameplay system (rain zone, weather controller) can drive at runtime.

Core Principle

The source technique’s key idea is separation of wetness from material authoring: the wet logic is a self-contained graph/function that receives material values and injects a wet mask, so enabling wetness is a swap, not a rewrite. How the source concepts map to Summer Engine: Constraint: the engine cannot inject custom nodes into a StandardMaterial3D at runtime. The equivalent of “swap in the pre-configured shader while keeping all values” is a converter that copies StandardMaterial3D parameters into the wet shader (below). The alternative — leaving StandardMaterial3D untouched and overlaying wetness via decals or post-processing — does not match the source’s material-preserving architecture and is not recommended here.

Scene / Node Shape

Implementation Steps

1. Write the shared wet-enabled spatial shader

Preserve the PBR parameters as uniforms and compute the wet mask from geometry. Fragment-stage NORMAL is view-space, so pass a world-space normal from the vertex stage — otherwise the “upward-facing” mask rotates with the camera.
Assumes near-uniform mesh scale; for heavily non-uniform scale, use the inverse-transpose normal transform instead of MODEL_MATRIX directly.

2. Convert existing materials while preserving their values

This is the source’s “swap in the pre-configured shader; all values retained” step. Run once (editor tool or import-time), not per frame.
Extend the copy list for any extra StandardMaterial3D properties your project uses (normal maps, emission, UV transforms). Keep the converter in one place so every wet-enabled material is produced identically.

3. Drive wetness at runtime with instance uniforms

Use Area3D rain zones to toggle raining for objects inside them. For scene-wide weather without enumerating targets, register a global shader parameter once (RenderingServer.global_shader_parameter_add("global_wet_amount", RenderingServer.GLOBAL_VAR_TYPE_FLOAT, 0.0)) and set it per frame with RenderingServer.global_shader_parameter_set; read it in the shader instead of the instance uniform.

4. Planned extension: heightmap-guided flow

The source author states heightmap support so wetness flows along map bumps is planned, not shipped. To implement it: sample a heightmap texture in the fragment stage and bias the wet mask along its gradient (e.g., offset world_pos.xz lookups downhill using the height texture derivatives) so streaks follow surface relief. Do not treat this as part of the evidenced technique.

Tunables

Failure Modes & Gotchas

  • View-space normal mistake: using fragment NORMAL directly makes the up-facing mask rotate with the camera. Always pass world normal from vertex() via a varying.
  • Expecting in-place injection: the engine cannot add wet logic to a live StandardMaterial3D. The value-preserving step is the one-time conversion, not runtime patching.
  • Duplicate shaders per material: keep ONE shared .gdshader; per-material differences live in uniforms, per-object state in instance uniforms. Otherwise you pay shader compilation and draw-call overhead.
  • Over-darkening: on already-dark albedos, clamp the darkened result or lower darkening.
  • Transparent/unshaded materials: out of scope; this skill targets opaque PBR surfaces.
  • Skinned meshes: verify the MODEL_MATRIX world-normal transform still behaves with skeletal animation before relying on the up-facing mask.

Verification

  1. With wet_amount = 0, converted materials render identically to their original StandardMaterial3D values (compare albedo/roughness response under a fixed light).
  2. Raising wet_amount darkens and glosses upward-facing surfaces; downward-facing and underside faces stay mostly dry.
  3. Rotating the camera does NOT shift the wet mask boundaries (confirms world-space normal).
  4. WetnessController animates wet/dry transitions smoothly with no per-material edits during play.
  5. Multiple meshes share one shader resource; adding wet-enabled objects does not add new shader variants.

Confidence

extracted — the architecture (material-preserving wet swap, custom-function value bridge, geometry-only mask, planned heightmap flow) comes from a public post that showed the technique in another engine; no code was published. The mapping, shader, and scripts here are engineering guidance consistent with that post, not source-extracted implementation and not verified inside Summer Engine.

Evidence

  • A public X post describing the technique (demo video only, no code).
  • vfx-water-ripple: Water-ripple effect: animated normal-distortion ripples on a water plane or Decal, set off by impacts.
  • 3d-lighting: Light a 3D scene: sun, omni and spot lights, WorldEnvironment, sky, shadows and ambient.

Source: library/skills/realtime-wet-surfaces/SKILL.md, rendered from summer-engine@4.3.0 on npm.