feat(render3d): terrain_lake_carve - a height map may carry its own lake bed

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-16 15:27:21 +03:00
parent 6dfdee75e2
commit fa6c422f9b
5 changed files with 16 additions and 2 deletions

View file

@ -6,3 +6,6 @@ its lake no longer floods every hollow in the survey with that lake's level; and
terrain's wet shore, forest and scree gates read the carved lake's line inside its outline 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 (`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. 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.

View file

@ -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 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 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_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 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 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) 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; 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 // 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)); 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 // 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 // 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; vec2 q = (xz - u_lake.xy) / u_lake.zw;

View file

@ -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_origin 784 vec2 1 0
U 4be7acd9 frag u_lake 800 vec4 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_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 832 vec4 1 0
U 4be7acd9 frag u_isle_mode 848 float 1 0 U 4be7acd9 frag u_isle_mode 848 float 1 0
U 4be7acd9 frag u_dem_blur 852 float 1 0 U 4be7acd9 frag u_dem_blur 852 float 1 0

View file

@ -69,6 +69,12 @@ var ter_lake_ez: int = 0
function terrain_lake(level: int, cx: int, cz: int, ex: int, ez: int) -> void { 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 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 # 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 # 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, # 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_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_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) 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_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_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)) u_f(gpu_uniform(p, "u_isle_mode"), fi(ter_isle_mode))