Merge feat/lake-water: a mirrored lake clipped to its ellipse, its own wet shore, terrain_lake_carve
This commit is contained in:
commit
c0884705c7
13 changed files with 78 additions and 37 deletions
11
changes/lake-water.md
Normal file
11
changes/lake-water.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
bump: patch
|
||||
type: fix
|
||||
**A lake can be the water that mirrors the world** — a reflecting body is clipped to its
|
||||
ellipse like any other unless it is an unbounded sea, so a map whose reflection belongs to
|
||||
its lake no longer floods every hollow in the survey with that lake's level; and the
|
||||
terrain's wet shore, forest and scree gates read the carved lake's line inside its outline
|
||||
(`u_lake`), the rule the grass already used, so a lake above the sea keeps its wet bank and
|
||||
no forest is painted down its bed.
|
||||
|
||||
`terrain_lake_carve(false)` keeps a lake's line, outline and shore but skips carving its
|
||||
bed, for a height map that already carries a shaped one.
|
||||
|
|
@ -10,6 +10,7 @@ uniform float u_dem_base; // the elevation that becomes y = 0
|
|||
uniform vec2 u_origin; // world x/z of the map's centre
|
||||
uniform vec4 u_lake; // a lake: centre x/z, half extents (zero = none)
|
||||
uniform float u_lake_level; // its surface height; the model records the surface, the bed is carved below it
|
||||
uniform float u_lake_carve; // 0: the height map carries its own bed (terrain_lake_carve)
|
||||
uniform float u_sea_level; // the sea the coast falls into (terrain_sea); the lake's level unless set
|
||||
uniform vec4 u_isle; // an island: centre x/z, radius (or rim margin), falloff width
|
||||
uniform float u_isle_mode; // 0 none, 1 radial (terrain_island), 2 inward from the survey's edge (terrain_coast)
|
||||
|
|
@ -50,7 +51,7 @@ void main() {
|
|||
float raw = demRaw(v_uv) * (u_dem_max - u_dem_min) + u_dem_min - u_dem_base;
|
||||
// the survey carries its own relief at this resolution; only the foot track is added
|
||||
h -= 0.25 * smoothstep(6.0, 1.5, pathDist(xz));
|
||||
if (u_lake.z > 0.0) {
|
||||
if (u_lake.z > 0.0 && u_lake_carve > 0.5) {
|
||||
// the elevation model samples the water surface as flat ground: inside the lake's
|
||||
// outline sink it into a bed, deepest in the middle, with a gentle gravel ramp at the shore
|
||||
vec2 q = (xz - u_lake.xy) / u_lake.zw;
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -157,7 +157,8 @@ U 4be7acd9 frag u_dem_base 776 float 1 0
|
|||
U 4be7acd9 frag u_origin 784 vec2 1 0
|
||||
U 4be7acd9 frag u_lake 800 vec4 1 0
|
||||
U 4be7acd9 frag u_lake_level 816 float 1 0
|
||||
U 4be7acd9 frag u_sea_level 820 float 1 0
|
||||
U 4be7acd9 frag u_lake_carve 820 float 1 0
|
||||
U 4be7acd9 frag u_sea_level 824 float 1 0
|
||||
U 4be7acd9 frag u_isle 832 vec4 1 0
|
||||
U 4be7acd9 frag u_isle_mode 848 float 1 0
|
||||
U 4be7acd9 frag u_dem_blur 852 float 1 0
|
||||
|
|
@ -2297,7 +2298,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 872
|
||||
B 2e2908c8 frag 1 904
|
||||
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
|
||||
|
|
@ -2333,10 +2334,11 @@ U 2e2908c8 frag u_carpet_on 776 float 1 0
|
|||
U 2e2908c8 frag u_snow_line 780 float 1 0
|
||||
U 2e2908c8 frag u_lake_level 784 float 1 0
|
||||
U 2e2908c8 frag u_sea_level 788 float 1 0
|
||||
U 2e2908c8 frag u_origin 792 vec2 1 0
|
||||
U 2e2908c8 frag u_view 800 mat4 1 0
|
||||
U 2e2908c8 frag u_far_split 864 float 1 0
|
||||
U 2e2908c8 frag u_far_band 868 float 1 0
|
||||
U 2e2908c8 frag u_lake 800 vec4 1 0
|
||||
U 2e2908c8 frag u_origin 816 vec2 1 0
|
||||
U 2e2908c8 frag u_view 832 mat4 1 0
|
||||
U 2e2908c8 frag u_far_split 896 float 1 0
|
||||
U 2e2908c8 frag u_far_band 900 float 1 0
|
||||
T 2e2908c8 u_brdf 2
|
||||
T 2e2908c8 u_carpet 3
|
||||
T 2e2908c8 u_grass_a 4
|
||||
|
|
@ -2365,7 +2367,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 872
|
||||
B 1f95f31b frag 1 904
|
||||
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
|
||||
|
|
@ -2401,10 +2403,11 @@ U 1f95f31b frag u_carpet_on 776 float 1 0
|
|||
U 1f95f31b frag u_snow_line 780 float 1 0
|
||||
U 1f95f31b frag u_lake_level 784 float 1 0
|
||||
U 1f95f31b frag u_sea_level 788 float 1 0
|
||||
U 1f95f31b frag u_origin 792 vec2 1 0
|
||||
U 1f95f31b frag u_view 800 mat4 1 0
|
||||
U 1f95f31b frag u_far_split 864 float 1 0
|
||||
U 1f95f31b frag u_far_band 868 float 1 0
|
||||
U 1f95f31b frag u_lake 800 vec4 1 0
|
||||
U 1f95f31b frag u_origin 816 vec2 1 0
|
||||
U 1f95f31b frag u_view 832 mat4 1 0
|
||||
U 1f95f31b frag u_far_split 896 float 1 0
|
||||
U 1f95f31b frag u_far_band 900 float 1 0
|
||||
T 1f95f31b u_brdf 2
|
||||
T 1f95f31b u_carpet 3
|
||||
T 1f95f31b u_grass_a 4
|
||||
|
|
@ -2433,7 +2436,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 872
|
||||
B f4382918 frag 1 904
|
||||
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
|
||||
|
|
@ -2469,10 +2472,11 @@ U f4382918 frag u_carpet_on 776 float 1 0
|
|||
U f4382918 frag u_snow_line 780 float 1 0
|
||||
U f4382918 frag u_lake_level 784 float 1 0
|
||||
U f4382918 frag u_sea_level 788 float 1 0
|
||||
U f4382918 frag u_origin 792 vec2 1 0
|
||||
U f4382918 frag u_view 800 mat4 1 0
|
||||
U f4382918 frag u_far_split 864 float 1 0
|
||||
U f4382918 frag u_far_band 868 float 1 0
|
||||
U f4382918 frag u_lake 800 vec4 1 0
|
||||
U f4382918 frag u_origin 816 vec2 1 0
|
||||
U f4382918 frag u_view 832 mat4 1 0
|
||||
U f4382918 frag u_far_split 896 float 1 0
|
||||
U f4382918 frag u_far_band 900 float 1 0
|
||||
T f4382918 u_brdf 2
|
||||
T f4382918 u_carpet 3
|
||||
T f4382918 u_grass_a 4
|
||||
|
|
@ -2501,7 +2505,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 872
|
||||
B f2952361 frag 1 904
|
||||
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
|
||||
|
|
@ -2537,10 +2541,11 @@ U f2952361 frag u_carpet_on 776 float 1 0
|
|||
U f2952361 frag u_snow_line 780 float 1 0
|
||||
U f2952361 frag u_lake_level 784 float 1 0
|
||||
U f2952361 frag u_sea_level 788 float 1 0
|
||||
U f2952361 frag u_origin 792 vec2 1 0
|
||||
U f2952361 frag u_view 800 mat4 1 0
|
||||
U f2952361 frag u_far_split 864 float 1 0
|
||||
U f2952361 frag u_far_band 868 float 1 0
|
||||
U f2952361 frag u_lake 800 vec4 1 0
|
||||
U f2952361 frag u_origin 816 vec2 1 0
|
||||
U f2952361 frag u_view 832 mat4 1 0
|
||||
U f2952361 frag u_far_split 896 float 1 0
|
||||
U f2952361 frag u_far_band 900 float 1 0
|
||||
T f2952361 u_brdf 2
|
||||
T f2952361 u_carpet 3
|
||||
T f2952361 u_grass_a 4
|
||||
|
|
@ -2569,7 +2574,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 872
|
||||
B a0f2dbac frag 1 904
|
||||
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
|
||||
|
|
@ -2605,10 +2610,11 @@ U a0f2dbac frag u_carpet_on 776 float 1 0
|
|||
U a0f2dbac frag u_snow_line 780 float 1 0
|
||||
U a0f2dbac frag u_lake_level 784 float 1 0
|
||||
U a0f2dbac frag u_sea_level 788 float 1 0
|
||||
U a0f2dbac frag u_origin 792 vec2 1 0
|
||||
U a0f2dbac frag u_view 800 mat4 1 0
|
||||
U a0f2dbac frag u_far_split 864 float 1 0
|
||||
U a0f2dbac frag u_far_band 868 float 1 0
|
||||
U a0f2dbac frag u_lake 800 vec4 1 0
|
||||
U a0f2dbac frag u_origin 816 vec2 1 0
|
||||
U a0f2dbac frag u_view 832 mat4 1 0
|
||||
U a0f2dbac frag u_far_split 896 float 1 0
|
||||
U a0f2dbac frag u_far_band 900 float 1 0
|
||||
T a0f2dbac u_brdf 2
|
||||
T a0f2dbac u_carpet 3
|
||||
T a0f2dbac u_grass_a 4
|
||||
|
|
@ -2637,7 +2643,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 872
|
||||
B 5e4589a1 frag 1 904
|
||||
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
|
||||
|
|
@ -2673,10 +2679,11 @@ U 5e4589a1 frag u_carpet_on 776 float 1 0
|
|||
U 5e4589a1 frag u_snow_line 780 float 1 0
|
||||
U 5e4589a1 frag u_lake_level 784 float 1 0
|
||||
U 5e4589a1 frag u_sea_level 788 float 1 0
|
||||
U 5e4589a1 frag u_origin 792 vec2 1 0
|
||||
U 5e4589a1 frag u_view 800 mat4 1 0
|
||||
U 5e4589a1 frag u_far_split 864 float 1 0
|
||||
U 5e4589a1 frag u_far_band 868 float 1 0
|
||||
U 5e4589a1 frag u_lake 800 vec4 1 0
|
||||
U 5e4589a1 frag u_origin 816 vec2 1 0
|
||||
U 5e4589a1 frag u_view 832 mat4 1 0
|
||||
U 5e4589a1 frag u_far_split 896 float 1 0
|
||||
U 5e4589a1 frag u_far_band 900 float 1 0
|
||||
T 5e4589a1 u_brdf 2
|
||||
T 5e4589a1 u_carpet 3
|
||||
T 5e4589a1 u_grass_a 4
|
||||
|
|
|
|||
|
|
@ -19,6 +19,15 @@ 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
|
||||
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 -
|
||||
// the rule the grass and the game's water test use. One line for both put a lake above the
|
||||
// sea with no wet shore and forest painted down its bed.
|
||||
float waterLine(vec2 xz) {
|
||||
float wl = u_sea_level;
|
||||
if (u_lake.z > 0.0) { vec2 q = (xz - u_lake.xy) / u_lake.zw; if (dot(q, q) < 1.0) wl = max(wl, u_lake_level); }
|
||||
return wl;
|
||||
}
|
||||
uniform vec2 u_origin; // world offset of the terrain grid
|
||||
|
||||
// The ground's own sun shadow comes from the baked height-field map (tershadow.frag),
|
||||
|
|
@ -251,14 +260,14 @@ vec3 groundShade(vec3 p, vec3 N, float slope, float dist, float viewDepth, bool
|
|||
vec3 ocf = textureLod(u_ortho, v_huv, 2.0).rgb;
|
||||
float gx = ocf.g - max(ocf.r, ocf.b);
|
||||
// (the photograph is sampled linear: sRGB 72 is 0.06, 92 is 0.11)
|
||||
forestW = smoothstep(0.12, 0.06, max(ocf.r, max(ocf.g, ocf.b))) * smoothstep(0.004, 0.012, gx) * smoothstep(u_sea_level + 0.8, u_sea_level + 1.8, p.y);
|
||||
forestW = smoothstep(0.12, 0.06, max(ocf.r, max(ocf.g, ocf.b))) * smoothstep(0.004, 0.012, gx) * smoothstep(waterLine(p.xz) + 0.8, waterLine(p.xz) + 1.8, p.y);
|
||||
// Classify from a ~60 m blur, never from the pixels: the survey's 10 m pixels carry
|
||||
// a foot trail as a broken line of bare ground, and thresholding them painted it
|
||||
// across the meadow as tan dashes (and, on the CPU, lined boulders up along it).
|
||||
vec3 ocl = textureLod(u_ortho, v_huv, 2.5).rgb;
|
||||
float mxc = max(ocl.r, max(ocl.g, ocl.b)), mnc = min(ocl.r, min(ocl.g, ocl.b));
|
||||
float greenEx = ocl.g - max(ocl.r, ocl.b);
|
||||
screeC = smoothstep(0.008, -0.002, greenEx) * smoothstep(0.06, 0.12, mxc) * (1.0 - smoothstep(0.55, 0.75, mxc)) * smoothstep(u_sea_level + 0.2, u_sea_level + 1.2, p.y);
|
||||
screeC = smoothstep(0.008, -0.002, greenEx) * smoothstep(0.06, 0.12, mxc) * (1.0 - smoothstep(0.55, 0.75, mxc)) * smoothstep(waterLine(p.xz) + 0.2, waterLine(p.xz) + 1.2, p.y);
|
||||
snowC = smoothstep(0.08, 0.04, mxc - mnc) * smoothstep(0.55, 0.8, mxc);
|
||||
}
|
||||
// snow lingering in the high gullies is drawn further down, but whether it can be
|
||||
|
|
@ -377,7 +386,7 @@ vec3 groundShade(vec3 p, vec3 N, float slope, float dist, float viewDepth, bool
|
|||
// the bank here: identical noise fields, identical time, identical phase, keyed off
|
||||
// height above the lake instead of depth below it. Across the seam the two agree, so
|
||||
// there is nothing there to read as an edge.
|
||||
float above = p.y - u_sea_level; // >0 on land, metres
|
||||
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);
|
||||
alb *= mix(1.0, 0.5, wet * 0.85);
|
||||
|
|
|
|||
|
|
@ -69,6 +69,12 @@ var ter_lake_ez: int = 0
|
|||
function terrain_lake(level: int, cx: int, cz: int, ex: int, ez: int) -> void {
|
||||
ter_lake_level = level; ter_lake_cx = cx; ter_lake_cz = cz; ter_lake_ex = ex; ter_lake_ez = ez
|
||||
}
|
||||
# Whether the generator carves that bed. A height map that already carries a shaped bed
|
||||
# turns it off and keeps the lake for everything else (its line, its outline, its shore):
|
||||
# the carve drops the bed metres within the survey's last 0.9 m of shore, which reads as a
|
||||
# cut edge on a lake whose own bank was shaped to come down gently.
|
||||
var ter_lake_carve: bool = true
|
||||
function terrain_lake_carve(on: bool) -> void { ter_lake_carve = on }
|
||||
# The SEA's level, for the coast, the strand and the shoreline shading, when it is not the
|
||||
# carved lake's. They were one number, which holds only while the lake is at sea level: a
|
||||
# lake eighty metres up the valley drowned the whole coast toward its own surface. Unset,
|
||||
|
|
@ -238,6 +244,9 @@ function terrain_generate() -> void {
|
|||
u_f2(gpu_uniform(p, "u_origin"), ter_ox, ter_oz)
|
||||
u_f4(gpu_uniform(p, "u_lake"), ter_lake_cx, ter_lake_cz, ter_lake_ex, ter_lake_ez)
|
||||
u_f(gpu_uniform(p, "u_lake_level"), ter_lake_level)
|
||||
var carve = F_ONE
|
||||
if not ter_lake_carve { carve = F_ZERO }
|
||||
u_f(gpu_uniform(p, "u_lake_carve"), carve)
|
||||
u_f(gpu_uniform(p, "u_sea_level"), ter_sea_gen())
|
||||
u_f4(gpu_uniform(p, "u_isle"), ter_isle_cx, ter_isle_cz, ter_isle_r, ter_isle_fall)
|
||||
u_f(gpu_uniform(p, "u_isle_mode"), fi(ter_isle_mode))
|
||||
|
|
@ -480,6 +489,7 @@ function terrain_bind_prog(p: int) -> void {
|
|||
var sea = lake
|
||||
if ter_sea_set { sea = ter_sea_level }
|
||||
u_f(gpu_uniform(p, "u_sea_level"), sea)
|
||||
u_f4(gpu_uniform(p, "u_lake"), ter_lake_cx, ter_lake_cz, ter_lake_ex, ter_lake_ez)
|
||||
u_mat4(gpu_uniform(p, "u_view"), cam_view)
|
||||
u_mat4(gpu_uniform(p, "u_proj"), cam_proj)
|
||||
u_f2(gpu_uniform(p, "u_origin"), ter_ox, ter_oz)
|
||||
|
|
|
|||
|
|
@ -361,9 +361,12 @@ function water_draw(depth_tex: int) -> void {
|
|||
var r = F_ZERO
|
||||
if i == wb_primary { r = ron }
|
||||
u_f(gpu_uniform(p, "u_refl_on"), r)
|
||||
# every body but the mirrored sea is clipped to the ellipse inside its bounds
|
||||
# Every body is clipped to the ellipse inside its bounds but an unbounded mirrored sea,
|
||||
# whose rectangle is the point. A mirrored LAKE is clipped like any other: a map whose
|
||||
# reflection belongs to its lake (the Bells in Maroon Lake) would otherwise draw that
|
||||
# lake's level over every hollow in the survey.
|
||||
var clip = F_ONE
|
||||
if i == wb_primary { clip = F_ZERO }
|
||||
if i == wb_primary and f_gt(f_max(wb_ex[i], wb_ez[i]), fi(10000)) { clip = F_ZERO }
|
||||
u_f(gpu_uniform(p, "u_clip_ellipse"), clip)
|
||||
mesh_draw(water_mesh)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue