feat(render3d): terrain_island, a coastline out of the survey
`terrain_island(cx, cz, r, fall)` keeps land out to `r` and then scales the terrain down into the water over `fall` metres and on to a shelf. Scaling rather than blending to a fixed bed is what makes the coastline come out of the terrain that is already there: low ground turns into beach and shallows, high ground into cliff. `r = 0` leaves the survey alone, so nothing that does not ask for an island is touched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
6043a67631
commit
9c00cd3e44
2 changed files with 24 additions and 0 deletions
|
|
@ -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 vec4 u_isle; // an island: centre x/z, radius, falloff width (radius 0 = none)
|
||||
// The DEM is Copernicus GLO-30 — 30 m data resampled onto this 4 m grid — so the stored
|
||||
// field is piecewise linear with a slope discontinuity every ~7 texels. Differencing it
|
||||
// for a shading normal turns each kink into a ridge, and on steep ground, where the same
|
||||
|
|
@ -58,6 +59,17 @@ void main() {
|
|||
float bed = u_lake_level - 0.4 - (5.0 + 3.0 * (1.0 - dot(q, q)) + 1.5 * fbm(xz * 0.02, 3)) * basin * basin; // a gentle gravel ramp, then the drop
|
||||
h = mix(h, bed, basin);
|
||||
}
|
||||
// The island. Outside the radius the terrain is scaled toward the water line and then
|
||||
// taken below it, so the shoreline is not drawn on: it is wherever the survey's own
|
||||
// relief, shrunk, happens to cross the water. Low ground becomes beach and shallows,
|
||||
// high ground becomes cliff, and a bay stays a bay.
|
||||
if (u_isle.z > 0.0) {
|
||||
float d = distance(xz, u_isle.xy);
|
||||
float t = smoothstep(u_isle.z, u_isle.z + u_isle.w, d); // 0 inland, 1 past the fall
|
||||
float shelf = 26.0 + 34.0 * smoothstep(0.0, 1.0, (d - u_isle.z - u_isle.w) / max(u_isle.w, 1.0));
|
||||
float above = h - u_lake_level;
|
||||
h = u_lake_level + above * (1.0 - t) - t * shelf;
|
||||
}
|
||||
o = vec4(h, 0.0, 0.0, 1.0);
|
||||
#elif defined(SMOOTH)
|
||||
// A purpose-built test ground: 2 km square, analytically smooth everywhere. No survey
|
||||
|
|
|
|||
|
|
@ -68,6 +68,17 @@ 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
|
||||
}
|
||||
# An island: land out to `r` from (cx, cz), then the terrain scaled down into the water
|
||||
# over `fall` metres and on down to a shelf. Scaling rather than blending to a fixed bed is
|
||||
# what makes the coastline come out of the terrain that is already there — low ground turns
|
||||
# into beach and shallows, high ground into cliff. `r = 0` leaves the survey alone.
|
||||
var ter_isle_cx: int = 0
|
||||
var ter_isle_cz: int = 0
|
||||
var ter_isle_r: int = 0
|
||||
var ter_isle_fall: int = 0
|
||||
function terrain_island(cx: int, cz: int, r: int, fall: int) -> void {
|
||||
ter_isle_cx = cx; ter_isle_cz = cz; ter_isle_r = r; ter_isle_fall = fall
|
||||
}
|
||||
|
||||
# Use a real place: a 16-bit PNG height map plus its elevation range (metres). The
|
||||
# elevation `base` becomes y = 0; `ox`/`oz` put the map's centre in the world.
|
||||
|
|
@ -194,6 +205,7 @@ function terrain_generate() -> void {
|
|||
u_f2(gl_uniform(p, "u_origin"), ter_ox, ter_oz)
|
||||
u_f4(gl_uniform(p, "u_lake"), ter_lake_cx, ter_lake_cz, ter_lake_ex, ter_lake_ez)
|
||||
u_f(gl_uniform(p, "u_lake_level"), ter_lake_level)
|
||||
u_f4(gl_uniform(p, "u_isle"), ter_isle_cx, ter_isle_cz, ter_isle_r, ter_isle_fall)
|
||||
u_f(gl_uniform(p, "u_dem_blur"), ter_dem_blur)
|
||||
}
|
||||
mesh_draw(sky_fullscreen)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue