Upload index.html
Browse files- index.html +26 -5
index.html
CHANGED
|
@@ -170,6 +170,8 @@ function decode(code){
|
|
| 170 |
return { peak, shape, rough: F32(F32(rg)/F32(15)), type, ramp, pk, sh, rg };
|
| 171 |
}
|
| 172 |
|
|
|
|
|
|
|
| 173 |
function landH(x, z){
|
| 174 |
const cx = Math.floor(x/ICELL), cz = Math.floor(z/ICELL);
|
| 175 |
// starting below sea level is what makes the depth readable: outside an island there is no
|
|
@@ -198,7 +200,13 @@ function landH(x, z){
|
|
| 198 |
if(d > rr) continue;
|
| 199 |
const k = F32(F32(1.0) - F32(F32(d)/F32(rr)));
|
| 200 |
const nz = F32(F32(0.55) + F32(F32(0.45)*F32(p.rough)*lnoise(F32(F32(dx*f2) + F32((p.pk+p.sh+1)%16)), F32(F32(dz*f2) + F32((p.pk+p.sh+7)%16)))));
|
| 201 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
h = Math.max(h, p.peak*terr - LAND.shelf); // the shelf is the shallow ring around an island
|
| 203 |
}
|
| 204 |
return h;
|
|
@@ -281,11 +289,21 @@ float landH(vec2 p){
|
|
| 281 |
float rough = rg/15.0;
|
| 282 |
float k = 1.0 - d/rr;
|
| 283 |
float nz = 0.55 + 0.45*rough*lnoise(r*f2 + vec2(mod(pk+sh+1.0, 16.0), mod(pk+sh+7.0, 16.0)));
|
| 284 |
-
float terr = (ramp > 0.0) ?
|
| 285 |
h = max(h, peak*terr - 1.2);
|
| 286 |
}
|
| 287 |
return h;
|
| 288 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
`;
|
| 290 |
|
| 291 |
/* ================= hull =================
|
|
@@ -481,7 +499,7 @@ void main(){
|
|
| 481 |
vLand = land;
|
| 482 |
vDepth = water - land; // depth of water over the seabed
|
| 483 |
vEdge = edge;
|
| 484 |
-
vNormal = waveN(w, uTime);
|
| 485 |
vFoam = clamp((wake + hullFoam + popFoam) * (isLand ? 0.0 : 1.0), 0.0, 1.0);
|
| 486 |
gl_Position = uProj * uView * vec4(wp, 1.0);
|
| 487 |
}`, `#version 300 es
|
|
@@ -538,9 +556,12 @@ void main(){
|
|
| 538 |
// mesh - a staircase on a 1 m grid. It is now an interpolated value, so the crossing is a line across
|
| 539 |
// each facet that joins with its neighbours, and the narrow band between the two is blended instead of
|
| 540 |
// switched.
|
|
|
|
|
|
|
|
|
|
| 541 |
float t = clamp(smoothstep(-0.12, 0.12, vEdge), 0.0, 1.0);
|
| 542 |
-
if(fn.y < 0.12) t = 1.0;
|
| 543 |
-
vec3 n = mix(wn,
|
| 544 |
if(n.y < 0.0) n = -n;
|
| 545 |
vec3 col = mix(waterCol(wn), landCol(fn, max(vLand, 0.0)), t);
|
| 546 |
float ndl = max(dot(n, LDIR), 0.0);
|
|
|
|
| 170 |
return { peak, shape, rough: F32(F32(rg)/F32(15)), type, ramp, pk, sh, rg };
|
| 171 |
}
|
| 172 |
|
| 173 |
+
// smoothstep on [0,1], every step rounded to float32 so the shader and the boat get the same number
|
| 174 |
+
function smooth01(u){ return F32(F32(F32(u)*F32(u))*F32(F32(3.0)-F32(F32(2.0)*u))); }
|
| 175 |
function landH(x, z){
|
| 176 |
const cx = Math.floor(x/ICELL), cz = Math.floor(z/ICELL);
|
| 177 |
// starting below sea level is what makes the depth readable: outside an island there is no
|
|
|
|
| 200 |
if(d > rr) continue;
|
| 201 |
const k = F32(F32(1.0) - F32(F32(d)/F32(rr)));
|
| 202 |
const nz = F32(F32(0.55) + F32(F32(0.45)*F32(p.rough)*lnoise(F32(F32(dx*f2) + F32((p.pk+p.sh+1)%16)), F32(F32(dz*f2) + F32((p.pk+p.sh+7)%16)))));
|
| 203 |
+
// A hard min at k = ramp is a crease, and where that crease meets the shoreline it reads as a
|
| 204 |
+
// corner. Easing it keeps the flat top - u is clamped to 1 over most of the radius - but rounds the
|
| 205 |
+
// shoulder. The shader does the same thing, so the boat still sits on the ground it is drawn on.
|
| 206 |
+
const u = F32(F32(k)/F32(p.ramp));
|
| 207 |
+
let s = 1.0;
|
| 208 |
+
if(u <= 0.0) s = 0.0; else if(u >= 1.0) s = 1.0; else s = smooth01(u);
|
| 209 |
+
const terr = F32(F32(p.ramp > 0 ? s : Math.pow(k, p.shape)) * F32(nz));
|
| 210 |
h = Math.max(h, p.peak*terr - LAND.shelf); // the shelf is the shallow ring around an island
|
| 211 |
}
|
| 212 |
return h;
|
|
|
|
| 289 |
float rough = rg/15.0;
|
| 290 |
float k = 1.0 - d/rr;
|
| 291 |
float nz = 0.55 + 0.45*rough*lnoise(r*f2 + vec2(mod(pk+sh+1.0, 16.0), mod(pk+sh+7.0, 16.0)));
|
| 292 |
+
float terr = (ramp > 0.0) ? smoothstep(0.0, 1.0, k/ramp) * nz : pow(k, shape) * nz; // eased shoulder, mirrored in the JS copy
|
| 293 |
h = max(h, peak*terr - 1.2);
|
| 294 |
}
|
| 295 |
return h;
|
| 296 |
}
|
| 297 |
+
// Land normal from the height field itself rather than from the facet drawn. Bilinear interpolation
|
| 298 |
+
// between lattice points is planar, so each cell is a flat sheet and the facet normal makes every quad
|
| 299 |
+
// read as its own tile. Sampling the field either side of the point gives a normal that varies
|
| 300 |
+
// continuously, which is what stops the islands looking like polygons.
|
| 301 |
+
vec3 landN(vec2 p){
|
| 302 |
+
float e = 0.25;
|
| 303 |
+
float hx = (landH(p + vec2(e, 0.0)) - landH(p - vec2(e, 0.0))) / (2.0*e);
|
| 304 |
+
float hz = (landH(p + vec2(0.0, e)) - landH(p - vec2(0.0, e))) / (2.0*e);
|
| 305 |
+
return normalize(vec3(-hx, 1.0, -hz));
|
| 306 |
+
}
|
| 307 |
`;
|
| 308 |
|
| 309 |
/* ================= hull =================
|
|
|
|
| 499 |
vLand = land;
|
| 500 |
vDepth = water - land; // depth of water over the seabed
|
| 501 |
vEdge = edge;
|
| 502 |
+
vNormal = isLand ? landN(w) : waveN(w, uTime); // only land vertices pay for the extra samples
|
| 503 |
vFoam = clamp((wake + hullFoam + popFoam) * (isLand ? 0.0 : 1.0), 0.0, 1.0);
|
| 504 |
gl_Position = uProj * uView * vec4(wp, 1.0);
|
| 505 |
}`, `#version 300 es
|
|
|
|
| 556 |
// mesh - a staircase on a 1 m grid. It is now an interpolated value, so the crossing is a line across
|
| 557 |
// each facet that joins with its neighbours, and the narrow band between the two is blended instead of
|
| 558 |
// switched.
|
| 559 |
+
// The normal comes from the height field, not from the facet, so land shades continuously across the
|
| 560 |
+
// mesh instead of one flat tile per quad. fn is still used, but only to decide which material a facet
|
| 561 |
+
// is - a facet this steep can only be a cliff face, and the sea surface never gets that steep.
|
| 562 |
float t = clamp(smoothstep(-0.12, 0.12, vEdge), 0.0, 1.0);
|
| 563 |
+
if(fn.y < 0.12) t = 1.0;
|
| 564 |
+
vec3 n = mix(wn, normalize(vNormal), t);
|
| 565 |
if(n.y < 0.0) n = -n;
|
| 566 |
vec3 col = mix(waterCol(wn), landCol(fn, max(vLand, 0.0)), t);
|
| 567 |
float ndl = max(dot(n, LDIR), 0.0);
|