feat(render3d): rain that leaves something behind
Rain fell and the ground did not change: the weather was a curtain of particles in front of a dry valley. u_wet, 0 dry to 1 soaked, does the three things a wet surface does. Darkens the albedo. Drops the roughness hard - which is what makes a soaked meadow read as soaked rather than merely dark, because the sky glances off it. And pools: water finds the low places and flat ground holds what a slope sheds, so the puddle mask is the macro noise the materials already use gated on slope, and a puddle takes the world's up for its normal rather than the ground's relief. It joins the shore's existing wet band rather than fighting it - the same term from a different cause. 34.1% of the frame changes between dry and soaked. GL 7.1 s either way over 400 frames. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
6169cd05b9
commit
031137a5fa
10 changed files with 98 additions and 42 deletions
20
changes/rain-that-leaves-something.md
Normal file
20
changes/rain-that-leaves-something.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
bump: minor
|
||||
type: feat
|
||||
Rain that leaves something behind.
|
||||
|
||||
Rain fell and the ground did not change: the weather was a curtain of particles in front
|
||||
of a dry valley, and a shower was something you waited out rather than something that
|
||||
happened to the place.
|
||||
|
||||
One scalar, u_wet, 0 dry to 1 soaked, doing the three things a wet surface does. It
|
||||
darkens the albedo. It drops the roughness hard, which is what makes a soaked meadow read
|
||||
as SOAKED rather than merely dark - the sky glances off it. And it pools: a wet ground
|
||||
does not darken evenly, water finds the low places and the flat ground holds what a slope
|
||||
sheds, so the puddle mask is the macro noise the materials already use gated on slope,
|
||||
and a puddle takes the world's up for its normal rather than the ground's relief.
|
||||
|
||||
It joins the shore's existing wet band rather than fighting it - the same term, from a
|
||||
different cause.
|
||||
|
||||
Measured: 34.1% of the frame changes between dry and soaked, and no cost - GL 7.1 s
|
||||
either way over 400 frames.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -2566,7 +2566,7 @@ U 2e2908c8 vert u_node 176 vec3 1 0
|
|||
U 2e2908c8 vert u_morph 192 vec2 1 0
|
||||
U 2e2908c8 vert u_grid 200 float 1 0
|
||||
I 2e2908c8 a_xz 0 vec2
|
||||
B 2e2908c8 frag 1 952
|
||||
B 2e2908c8 frag 1 968
|
||||
U 2e2908c8 frag u_cascade_vp 0 mat4 5 64
|
||||
U 2e2908c8 frag u_cascade_split 320 float 5 16
|
||||
U 2e2908c8 frag u_cascade_range 400 float 5 16
|
||||
|
|
@ -2607,12 +2607,13 @@ U 2e2908c8 frag u_ortho_on 828 float 1 0
|
|||
U 2e2908c8 frag u_carpet_on 832 float 1 0
|
||||
U 2e2908c8 frag u_snow_line 836 float 1 0
|
||||
U 2e2908c8 frag u_lake_level 840 float 1 0
|
||||
U 2e2908c8 frag u_sea_level 844 float 1 0
|
||||
U 2e2908c8 frag u_lake 848 vec4 1 0
|
||||
U 2e2908c8 frag u_origin 864 vec2 1 0
|
||||
U 2e2908c8 frag u_view 880 mat4 1 0
|
||||
U 2e2908c8 frag u_far_split 944 float 1 0
|
||||
U 2e2908c8 frag u_far_band 948 float 1 0
|
||||
U 2e2908c8 frag u_wet 844 float 1 0
|
||||
U 2e2908c8 frag u_sea_level 848 float 1 0
|
||||
U 2e2908c8 frag u_lake 864 vec4 1 0
|
||||
U 2e2908c8 frag u_origin 880 vec2 1 0
|
||||
U 2e2908c8 frag u_view 896 mat4 1 0
|
||||
U 2e2908c8 frag u_far_split 960 float 1 0
|
||||
U 2e2908c8 frag u_far_band 964 float 1 0
|
||||
T 2e2908c8 u_brdf 2
|
||||
T 2e2908c8 u_carpet 3
|
||||
T 2e2908c8 u_grass_a 4
|
||||
|
|
@ -2641,7 +2642,7 @@ U 1f95f31b vert u_node 176 vec3 1 0
|
|||
U 1f95f31b vert u_morph 192 vec2 1 0
|
||||
U 1f95f31b vert u_grid 200 float 1 0
|
||||
I 1f95f31b a_xz 0 vec2
|
||||
B 1f95f31b frag 1 952
|
||||
B 1f95f31b frag 1 968
|
||||
U 1f95f31b frag u_cascade_vp 0 mat4 5 64
|
||||
U 1f95f31b frag u_cascade_split 320 float 5 16
|
||||
U 1f95f31b frag u_cascade_range 400 float 5 16
|
||||
|
|
@ -2682,12 +2683,13 @@ U 1f95f31b frag u_ortho_on 828 float 1 0
|
|||
U 1f95f31b frag u_carpet_on 832 float 1 0
|
||||
U 1f95f31b frag u_snow_line 836 float 1 0
|
||||
U 1f95f31b frag u_lake_level 840 float 1 0
|
||||
U 1f95f31b frag u_sea_level 844 float 1 0
|
||||
U 1f95f31b frag u_lake 848 vec4 1 0
|
||||
U 1f95f31b frag u_origin 864 vec2 1 0
|
||||
U 1f95f31b frag u_view 880 mat4 1 0
|
||||
U 1f95f31b frag u_far_split 944 float 1 0
|
||||
U 1f95f31b frag u_far_band 948 float 1 0
|
||||
U 1f95f31b frag u_wet 844 float 1 0
|
||||
U 1f95f31b frag u_sea_level 848 float 1 0
|
||||
U 1f95f31b frag u_lake 864 vec4 1 0
|
||||
U 1f95f31b frag u_origin 880 vec2 1 0
|
||||
U 1f95f31b frag u_view 896 mat4 1 0
|
||||
U 1f95f31b frag u_far_split 960 float 1 0
|
||||
U 1f95f31b frag u_far_band 964 float 1 0
|
||||
T 1f95f31b u_brdf 2
|
||||
T 1f95f31b u_carpet 3
|
||||
T 1f95f31b u_grass_a 4
|
||||
|
|
@ -2716,7 +2718,7 @@ U f4382918 vert u_node 176 vec3 1 0
|
|||
U f4382918 vert u_morph 192 vec2 1 0
|
||||
U f4382918 vert u_grid 200 float 1 0
|
||||
I f4382918 a_xz 0 vec2
|
||||
B f4382918 frag 1 952
|
||||
B f4382918 frag 1 968
|
||||
U f4382918 frag u_cascade_vp 0 mat4 5 64
|
||||
U f4382918 frag u_cascade_split 320 float 5 16
|
||||
U f4382918 frag u_cascade_range 400 float 5 16
|
||||
|
|
@ -2757,12 +2759,13 @@ U f4382918 frag u_ortho_on 828 float 1 0
|
|||
U f4382918 frag u_carpet_on 832 float 1 0
|
||||
U f4382918 frag u_snow_line 836 float 1 0
|
||||
U f4382918 frag u_lake_level 840 float 1 0
|
||||
U f4382918 frag u_sea_level 844 float 1 0
|
||||
U f4382918 frag u_lake 848 vec4 1 0
|
||||
U f4382918 frag u_origin 864 vec2 1 0
|
||||
U f4382918 frag u_view 880 mat4 1 0
|
||||
U f4382918 frag u_far_split 944 float 1 0
|
||||
U f4382918 frag u_far_band 948 float 1 0
|
||||
U f4382918 frag u_wet 844 float 1 0
|
||||
U f4382918 frag u_sea_level 848 float 1 0
|
||||
U f4382918 frag u_lake 864 vec4 1 0
|
||||
U f4382918 frag u_origin 880 vec2 1 0
|
||||
U f4382918 frag u_view 896 mat4 1 0
|
||||
U f4382918 frag u_far_split 960 float 1 0
|
||||
U f4382918 frag u_far_band 964 float 1 0
|
||||
T f4382918 u_brdf 2
|
||||
T f4382918 u_carpet 3
|
||||
T f4382918 u_grass_a 4
|
||||
|
|
@ -2791,7 +2794,7 @@ U f2952361 vert u_node 176 vec3 1 0
|
|||
U f2952361 vert u_morph 192 vec2 1 0
|
||||
U f2952361 vert u_grid 200 float 1 0
|
||||
I f2952361 a_xz 0 vec2
|
||||
B f2952361 frag 1 952
|
||||
B f2952361 frag 1 968
|
||||
U f2952361 frag u_cascade_vp 0 mat4 5 64
|
||||
U f2952361 frag u_cascade_split 320 float 5 16
|
||||
U f2952361 frag u_cascade_range 400 float 5 16
|
||||
|
|
@ -2832,12 +2835,13 @@ U f2952361 frag u_ortho_on 828 float 1 0
|
|||
U f2952361 frag u_carpet_on 832 float 1 0
|
||||
U f2952361 frag u_snow_line 836 float 1 0
|
||||
U f2952361 frag u_lake_level 840 float 1 0
|
||||
U f2952361 frag u_sea_level 844 float 1 0
|
||||
U f2952361 frag u_lake 848 vec4 1 0
|
||||
U f2952361 frag u_origin 864 vec2 1 0
|
||||
U f2952361 frag u_view 880 mat4 1 0
|
||||
U f2952361 frag u_far_split 944 float 1 0
|
||||
U f2952361 frag u_far_band 948 float 1 0
|
||||
U f2952361 frag u_wet 844 float 1 0
|
||||
U f2952361 frag u_sea_level 848 float 1 0
|
||||
U f2952361 frag u_lake 864 vec4 1 0
|
||||
U f2952361 frag u_origin 880 vec2 1 0
|
||||
U f2952361 frag u_view 896 mat4 1 0
|
||||
U f2952361 frag u_far_split 960 float 1 0
|
||||
U f2952361 frag u_far_band 964 float 1 0
|
||||
T f2952361 u_brdf 2
|
||||
T f2952361 u_carpet 3
|
||||
T f2952361 u_grass_a 4
|
||||
|
|
@ -2866,7 +2870,7 @@ U a0f2dbac vert u_node 176 vec3 1 0
|
|||
U a0f2dbac vert u_morph 192 vec2 1 0
|
||||
U a0f2dbac vert u_grid 200 float 1 0
|
||||
I a0f2dbac a_xz 0 vec2
|
||||
B a0f2dbac frag 1 952
|
||||
B a0f2dbac frag 1 968
|
||||
U a0f2dbac frag u_cascade_vp 0 mat4 5 64
|
||||
U a0f2dbac frag u_cascade_split 320 float 5 16
|
||||
U a0f2dbac frag u_cascade_range 400 float 5 16
|
||||
|
|
@ -2907,12 +2911,13 @@ U a0f2dbac frag u_ortho_on 828 float 1 0
|
|||
U a0f2dbac frag u_carpet_on 832 float 1 0
|
||||
U a0f2dbac frag u_snow_line 836 float 1 0
|
||||
U a0f2dbac frag u_lake_level 840 float 1 0
|
||||
U a0f2dbac frag u_sea_level 844 float 1 0
|
||||
U a0f2dbac frag u_lake 848 vec4 1 0
|
||||
U a0f2dbac frag u_origin 864 vec2 1 0
|
||||
U a0f2dbac frag u_view 880 mat4 1 0
|
||||
U a0f2dbac frag u_far_split 944 float 1 0
|
||||
U a0f2dbac frag u_far_band 948 float 1 0
|
||||
U a0f2dbac frag u_wet 844 float 1 0
|
||||
U a0f2dbac frag u_sea_level 848 float 1 0
|
||||
U a0f2dbac frag u_lake 864 vec4 1 0
|
||||
U a0f2dbac frag u_origin 880 vec2 1 0
|
||||
U a0f2dbac frag u_view 896 mat4 1 0
|
||||
U a0f2dbac frag u_far_split 960 float 1 0
|
||||
U a0f2dbac frag u_far_band 964 float 1 0
|
||||
T a0f2dbac u_brdf 2
|
||||
T a0f2dbac u_carpet 3
|
||||
T a0f2dbac u_grass_a 4
|
||||
|
|
@ -2941,7 +2946,7 @@ U 5e4589a1 vert u_node 176 vec3 1 0
|
|||
U 5e4589a1 vert u_morph 192 vec2 1 0
|
||||
U 5e4589a1 vert u_grid 200 float 1 0
|
||||
I 5e4589a1 a_xz 0 vec2
|
||||
B 5e4589a1 frag 1 952
|
||||
B 5e4589a1 frag 1 968
|
||||
U 5e4589a1 frag u_cascade_vp 0 mat4 5 64
|
||||
U 5e4589a1 frag u_cascade_split 320 float 5 16
|
||||
U 5e4589a1 frag u_cascade_range 400 float 5 16
|
||||
|
|
@ -2982,12 +2987,13 @@ U 5e4589a1 frag u_ortho_on 828 float 1 0
|
|||
U 5e4589a1 frag u_carpet_on 832 float 1 0
|
||||
U 5e4589a1 frag u_snow_line 836 float 1 0
|
||||
U 5e4589a1 frag u_lake_level 840 float 1 0
|
||||
U 5e4589a1 frag u_sea_level 844 float 1 0
|
||||
U 5e4589a1 frag u_lake 848 vec4 1 0
|
||||
U 5e4589a1 frag u_origin 864 vec2 1 0
|
||||
U 5e4589a1 frag u_view 880 mat4 1 0
|
||||
U 5e4589a1 frag u_far_split 944 float 1 0
|
||||
U 5e4589a1 frag u_far_band 948 float 1 0
|
||||
U 5e4589a1 frag u_wet 844 float 1 0
|
||||
U 5e4589a1 frag u_sea_level 848 float 1 0
|
||||
U 5e4589a1 frag u_lake 864 vec4 1 0
|
||||
U 5e4589a1 frag u_origin 880 vec2 1 0
|
||||
U 5e4589a1 frag u_view 896 mat4 1 0
|
||||
U 5e4589a1 frag u_far_split 960 float 1 0
|
||||
U 5e4589a1 frag u_far_band 964 float 1 0
|
||||
T 5e4589a1 u_brdf 2
|
||||
T 5e4589a1 u_carpet 3
|
||||
T 5e4589a1 u_grass_a 4
|
||||
|
|
|
|||
|
|
@ -18,6 +18,13 @@ uniform sampler2D u_snow_d; uniform sampler2D u_carpet; // the clump cards ba
|
|||
uniform float u_carpet_on;
|
||||
uniform float u_snow_line;
|
||||
uniform float u_lake_level; // the ground just above the water is wet and dark
|
||||
// ---- RAIN THAT LEAVES SOMETHING BEHIND -----------------------------------------------------
|
||||
// Rain fell and the ground did not change: the weather was a curtain of particles in front of a
|
||||
// dry valley. This is one scalar, 0 dry to 1 soaked, and it does three things a wet surface
|
||||
// does - darkens the albedo, drops the roughness so the sky glances off it, and pools in the
|
||||
// low places. It dries out over minutes after the rain stops, which is the part that makes a
|
||||
// player notice the weather happened at all.
|
||||
uniform float u_wet;
|
||||
uniform float u_sea_level; // the sea's line: shore, forest and scree gates (terrain_sea)
|
||||
uniform vec4 u_lake; // the carved lake's outline: centre x/z, half extents (zero = none)
|
||||
// The water line that applies here: the sea everywhere, the lake's own inside its outline -
|
||||
|
|
@ -437,7 +444,18 @@ vec3 groundShade(vec3 p, vec3 N, float slope, float dist, float viewDepth, bool
|
|||
float above = p.y - waterLine(p.xz); // >0 on land, metres
|
||||
// wet ground: darker and glossier near the water, fading out over ~1.2 m
|
||||
float wet = smoothstep(1.2, 0.0, above);
|
||||
// the rain's wetness joins the shore's: the same term, from a different cause
|
||||
wet = max(wet, u_wet);
|
||||
alb *= mix(1.0, 0.5, wet * 0.85);
|
||||
// Puddles. A soaked ground does not darken evenly - water finds the low places, and the flat
|
||||
// ground holds it while a slope sheds it. The noise is the same macro field the materials
|
||||
// already use, so a puddle sits where the ground is genuinely dished rather than in a
|
||||
// pattern of its own.
|
||||
float pud = 0.0;
|
||||
if (u_wet > 0.01) {
|
||||
float lowness = smoothstep(0.35, 0.0, slope);
|
||||
pud = smoothstep(0.45, 0.72, fbmC(cheap, p.xz * 0.35 + 17.0, 2) * 0.5 + 0.5) * lowness * u_wet;
|
||||
}
|
||||
// A sheet of water actually runs up the bank ahead of the foam, so the ground inside
|
||||
// the wash is seen through water, not bare. Without this the gaps between the foam
|
||||
// streaks showed dry grass and the wash looked like white paint on a lawn.
|
||||
|
|
@ -477,6 +495,15 @@ vec3 groundShade(vec3 p, vec3 N, float slope, float dist, float viewDepth, bool
|
|||
n = normalize(mix(n, N, smoothstep(150.0, 900.0, dist)));
|
||||
float ao = arm.r;
|
||||
float rough = clamp(arm.g, 0.3, 1.0);
|
||||
// Wet ground is SMOOTH. That is what makes a soaked meadow read as soaked rather than as
|
||||
// dark: the sky glances off it. A puddle is smoother still and flat, so its normal is the
|
||||
// world's up rather than the ground's relief.
|
||||
rough = mix(rough, 0.28, wet * 0.8);
|
||||
if (pud > 0.01) {
|
||||
rough = mix(rough, 0.06, pud);
|
||||
n = normalize(mix(n, vec3(0.0, 1.0, 0.0), pud * 0.9));
|
||||
alb = mix(alb, alb * 0.55, pud);
|
||||
}
|
||||
float metal = 0.0;
|
||||
// the shadow map carries the objects standing on the ground (trees, rocks); the
|
||||
// ground's own relief is in the baked height-field shadow that sunShadow() applies
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ var ter_smooth: bool = false # generate the analytic test ground instead of a
|
|||
var ter_far_split: int = 0 # metres: beyond this the terrain takes its cheap far path (R3D_TFAR)
|
||||
var ter_far_band: int = 0 # half-width of the near/far blend (R3D_TBAND)
|
||||
var ter_snow_line: int = 0
|
||||
# 0 dry .. 1 soaked. The game sets it from the weather and lets it dry out.
|
||||
var ter_wet: int = 0
|
||||
var ter_tex: words = null # 11 material textures (see terrain_bind)
|
||||
var ter_ox: int = 0 # world x/z of the terrain centre (float bits)
|
||||
var ter_oz: int = 0
|
||||
|
|
@ -483,6 +485,7 @@ function terrain_bind_prog(p: int) -> void {
|
|||
u_f(gpu_uniform(p, "u_half"), fi(TERRAIN_HALF))
|
||||
u_f(gpu_uniform(p, "u_texel"), fr(1, TERRAIN_RES))
|
||||
u_f(gpu_uniform(p, "u_snow_line"), ter_snow_line)
|
||||
u_f(gpu_uniform(p, "u_wet"), ter_wet)
|
||||
var lake = fl(-100000.0)
|
||||
if ter_lake_ex != 0 { lake = ter_lake_level }
|
||||
u_f(gpu_uniform(p, "u_lake_level"), lake)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue