diff --git a/changes/rain-that-leaves-something.md b/changes/rain-that-leaves-something.md new file mode 100644 index 00000000..d301a658 --- /dev/null +++ b/changes/rain-that-leaves-something.md @@ -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. diff --git a/packages/ludic.render3d/shaders/spv/1f95f31b.frag.spv b/packages/ludic.render3d/shaders/spv/1f95f31b.frag.spv index 5fa89fee..748e5278 100644 Binary files a/packages/ludic.render3d/shaders/spv/1f95f31b.frag.spv and b/packages/ludic.render3d/shaders/spv/1f95f31b.frag.spv differ diff --git a/packages/ludic.render3d/shaders/spv/2e2908c8.frag.spv b/packages/ludic.render3d/shaders/spv/2e2908c8.frag.spv index 5b723d75..5ffa9a1f 100644 Binary files a/packages/ludic.render3d/shaders/spv/2e2908c8.frag.spv and b/packages/ludic.render3d/shaders/spv/2e2908c8.frag.spv differ diff --git a/packages/ludic.render3d/shaders/spv/5e4589a1.frag.spv b/packages/ludic.render3d/shaders/spv/5e4589a1.frag.spv index 6e67a36a..e164e783 100644 Binary files a/packages/ludic.render3d/shaders/spv/5e4589a1.frag.spv and b/packages/ludic.render3d/shaders/spv/5e4589a1.frag.spv differ diff --git a/packages/ludic.render3d/shaders/spv/a0f2dbac.frag.spv b/packages/ludic.render3d/shaders/spv/a0f2dbac.frag.spv index 951bd89b..20f97ef8 100644 Binary files a/packages/ludic.render3d/shaders/spv/a0f2dbac.frag.spv and b/packages/ludic.render3d/shaders/spv/a0f2dbac.frag.spv differ diff --git a/packages/ludic.render3d/shaders/spv/f2952361.frag.spv b/packages/ludic.render3d/shaders/spv/f2952361.frag.spv index 7b3fa2c5..123e5a1d 100644 Binary files a/packages/ludic.render3d/shaders/spv/f2952361.frag.spv and b/packages/ludic.render3d/shaders/spv/f2952361.frag.spv differ diff --git a/packages/ludic.render3d/shaders/spv/f4382918.frag.spv b/packages/ludic.render3d/shaders/spv/f4382918.frag.spv index c226f79f..b3f353d0 100644 Binary files a/packages/ludic.render3d/shaders/spv/f4382918.frag.spv and b/packages/ludic.render3d/shaders/spv/f4382918.frag.spv differ diff --git a/packages/ludic.render3d/shaders/spv/manifest.txt b/packages/ludic.render3d/shaders/spv/manifest.txt index bf688c9a..6f46fe0e 100644 --- a/packages/ludic.render3d/shaders/spv/manifest.txt +++ b/packages/ludic.render3d/shaders/spv/manifest.txt @@ -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 diff --git a/packages/ludic.render3d/shaders/terrain.frag b/packages/ludic.render3d/shaders/terrain.frag index b2081fde..a2d2cb2a 100644 --- a/packages/ludic.render3d/shaders/terrain.frag +++ b/packages/ludic.render3d/shaders/terrain.frag @@ -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 diff --git a/packages/ludic.render3d/terrain.ludic b/packages/ludic.render3d/terrain.ludic index cac569ee..b1446f4b 100644 --- a/packages/ludic.render3d/terrain.ludic +++ b/packages/ludic.render3d/terrain.ludic @@ -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)