incanto 0.15.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/3d.d.ts +19 -0
- package/dist/3d.js +3 -3
- package/dist/{create-game-BS-K-GY1.js → create-game-DW1te5ve.js} +2 -109
- package/dist/index.js +1 -1
- package/dist/{physics-3d-TmOuCy7J.js → physics-3d-BiqGnxg_.js} +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-Bh_3Z39N.js → register-CNvGGK2B.js} +388 -88
- package/dist/test.js +3 -3
- package/editor/assets/{agent8-DqQ2CQ5A.js → agent8-DF_fw2wK.js} +1 -1
- package/editor/assets/{index-CofH0yGY.js → index-B0zes_tz.js} +196 -162
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +9 -0
- package/skills/incanto-environment.md +14 -8
- package/skills/incanto-node-reference.md +2 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
|
@@ -10269,6 +10269,120 @@ void main() {
|
|
|
10269
10269
|
}
|
|
10270
10270
|
`;
|
|
10271
10271
|
//#endregion
|
|
10272
|
+
//#region src/3d/water/caustics.ts
|
|
10273
|
+
/**
|
|
10274
|
+
* Underwater caustics — the dancing refracted-light pattern the water surface
|
|
10275
|
+
* throws onto everything below it. The engine has no post-processing pipeline,
|
|
10276
|
+
* so the renderer does this as ONE depth-aware composite pass, and ONLY while
|
|
10277
|
+
* the camera is genuinely underwater (so normal above-water rendering — even
|
|
10278
|
+
* standing at the water's edge — is completely untouched):
|
|
10279
|
+
*
|
|
10280
|
+
* 1. render the scene to an offscreen target (color + depth)
|
|
10281
|
+
* 2. draw this fullscreen material, which reconstructs each pixel's WORLD
|
|
10282
|
+
* position from the depth buffer and adds an animated caustic highlight
|
|
10283
|
+
* wherever that world point sits below the water surface
|
|
10284
|
+
*
|
|
10285
|
+
* Because the pattern is keyed to reconstructed world XZ, it STICKS to the
|
|
10286
|
+
* floor/walls/props (it isn't a flat screen overlay) and fades with depth +
|
|
10287
|
+
* view distance so it melts into the underwater fog.
|
|
10288
|
+
*/
|
|
10289
|
+
/** Fullscreen triangle/quad — the vertex stage ignores the camera entirely. */
|
|
10290
|
+
const CAUSTICS_VERT = `
|
|
10291
|
+
varying vec2 vUv;
|
|
10292
|
+
void main() {
|
|
10293
|
+
vUv = uv;
|
|
10294
|
+
gl_Position = vec4(position.xy, 0.0, 1.0);
|
|
10295
|
+
}
|
|
10296
|
+
`;
|
|
10297
|
+
/**
|
|
10298
|
+
* The classic animated caustic pattern (layered moving cells), 0..1 — SHARED
|
|
10299
|
+
* between the underwater composite and Water3D's above-water caustics (the
|
|
10300
|
+
* refracted bottom shimmer), so both views of the same water agree.
|
|
10301
|
+
*/
|
|
10302
|
+
const CAUSTIC_GLSL = `
|
|
10303
|
+
float caustic(vec2 uv, float t) {
|
|
10304
|
+
vec2 p = mod(uv * 6.28318, 6.28318) - 250.0;
|
|
10305
|
+
vec2 i = p;
|
|
10306
|
+
float c = 1.0;
|
|
10307
|
+
float inten = 0.005;
|
|
10308
|
+
for (int n = 0; n < 5; n++) {
|
|
10309
|
+
float ti = t * (1.0 - (3.5 / float(n + 1)));
|
|
10310
|
+
i = p + vec2(cos(ti - i.x) + sin(ti + i.y), sin(ti - i.y) + cos(ti + i.x));
|
|
10311
|
+
c += 1.0 / length(vec2(p.x / (sin(i.x + ti) / inten), p.y / (cos(i.y + ti) / inten)));
|
|
10312
|
+
}
|
|
10313
|
+
c /= 5.0;
|
|
10314
|
+
c = 1.17 - pow(c, 1.4);
|
|
10315
|
+
return clamp(pow(abs(c), 8.0), 0.0, 1.0);
|
|
10316
|
+
}
|
|
10317
|
+
`;
|
|
10318
|
+
const CAUSTICS_FRAG = `
|
|
10319
|
+
precision highp float;
|
|
10320
|
+
varying vec2 vUv;
|
|
10321
|
+
uniform sampler2D tColor;
|
|
10322
|
+
uniform sampler2D tDepth;
|
|
10323
|
+
uniform mat4 uInvViewProj;
|
|
10324
|
+
uniform vec3 uCameraPos;
|
|
10325
|
+
uniform float uWaterLevel;
|
|
10326
|
+
uniform float uTime;
|
|
10327
|
+
uniform vec3 uCausticColor;
|
|
10328
|
+
uniform float uCausticIntensity;
|
|
10329
|
+
uniform float uCausticScale;
|
|
10330
|
+
uniform float uMaxDist;
|
|
10331
|
+
|
|
10332
|
+
${CAUSTIC_GLSL}
|
|
10333
|
+
|
|
10334
|
+
void main() {
|
|
10335
|
+
vec4 color = texture2D(tColor, vUv);
|
|
10336
|
+
float depth = texture2D(tDepth, vUv).x;
|
|
10337
|
+
// depth == 1 is the far plane (sky/background) — nothing to light there
|
|
10338
|
+
if (depth < 1.0) {
|
|
10339
|
+
vec4 ndc = vec4(vUv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
|
10340
|
+
vec4 world = uInvViewProj * ndc;
|
|
10341
|
+
world.xyz /= world.w;
|
|
10342
|
+
float below = uWaterLevel - world.y;
|
|
10343
|
+
if (below > 0.0) {
|
|
10344
|
+
float dist = distance(world.xyz, uCameraPos);
|
|
10345
|
+
// caustics — fade with distance (melt into the fog) + a touch with depth
|
|
10346
|
+
float distFade = 1.0 - clamp(dist / uMaxDist, 0.0, 1.0);
|
|
10347
|
+
float depthFade = 1.0 - clamp(below / (uMaxDist * 0.5), 0.0, 0.6);
|
|
10348
|
+
// two octaves at offset speeds = the shimmering interference of real caustics
|
|
10349
|
+
float c =
|
|
10350
|
+
caustic(world.xz * uCausticScale, uTime) * 0.65 +
|
|
10351
|
+
caustic(world.xz * uCausticScale * 1.7 + 30.0, uTime * 0.8) * 0.35;
|
|
10352
|
+
color.rgb += uCausticColor * (c * uCausticIntensity * distFade * distFade * depthFade);
|
|
10353
|
+
}
|
|
10354
|
+
}
|
|
10355
|
+
gl_FragColor = color;
|
|
10356
|
+
}
|
|
10357
|
+
`;
|
|
10358
|
+
/** Build the fullscreen composite mesh (a 2×2 clip-space quad). */
|
|
10359
|
+
function createCausticsQuad() {
|
|
10360
|
+
const material = new ShaderMaterial({
|
|
10361
|
+
vertexShader: CAUSTICS_VERT,
|
|
10362
|
+
fragmentShader: CAUSTICS_FRAG,
|
|
10363
|
+
depthTest: false,
|
|
10364
|
+
depthWrite: false,
|
|
10365
|
+
uniforms: {
|
|
10366
|
+
tColor: { value: null },
|
|
10367
|
+
tDepth: { value: null },
|
|
10368
|
+
uInvViewProj: { value: new Matrix4() },
|
|
10369
|
+
uCameraPos: { value: new Vector3() },
|
|
10370
|
+
uWaterLevel: { value: 0 },
|
|
10371
|
+
uTime: { value: 0 },
|
|
10372
|
+
uCausticColor: { value: new Color("#cdeeff") },
|
|
10373
|
+
uCausticIntensity: { value: .55 },
|
|
10374
|
+
uCausticScale: { value: .32 },
|
|
10375
|
+
uMaxDist: { value: 22 }
|
|
10376
|
+
}
|
|
10377
|
+
});
|
|
10378
|
+
const mesh = new Mesh(new PlaneGeometry(2, 2), material);
|
|
10379
|
+
mesh.frustumCulled = false;
|
|
10380
|
+
return {
|
|
10381
|
+
mesh,
|
|
10382
|
+
uniforms: material.uniforms
|
|
10383
|
+
};
|
|
10384
|
+
}
|
|
10385
|
+
//#endregion
|
|
10272
10386
|
//#region src/3d/water/shaders.ts
|
|
10273
10387
|
/**
|
|
10274
10388
|
* The Water3D 'fancy' shaders — ported VERBATIM from
|
|
@@ -10576,6 +10690,16 @@ uniform float uWhitecaps;
|
|
|
10576
10690
|
uniform float uWaveEnvelope;
|
|
10577
10691
|
uniform float uSwellAmplitude;
|
|
10578
10692
|
|
|
10693
|
+
// incanto presets: above-water CAUSTICS — the dancing light web on the
|
|
10694
|
+
// submerged bottom, seen THROUGH the surface (the pool/shallow-sea look).
|
|
10695
|
+
// Intensity 0 = off. The pattern fn is shared with the underwater composite.
|
|
10696
|
+
uniform float uCausticsAbove;
|
|
10697
|
+
// incanto presets: per-preset reflection ceiling (the old hard 0.6) — lakes
|
|
10698
|
+
// push toward mirror, pools stay glassy-clear.
|
|
10699
|
+
uniform float uReflectivityMax;
|
|
10700
|
+
|
|
10701
|
+
${CAUSTIC_GLSL}
|
|
10702
|
+
|
|
10579
10703
|
// 🎨 Contact surface color customization uniforms
|
|
10580
10704
|
uniform vec3 uEdgeColor;
|
|
10581
10705
|
uniform float uEdgeIntensity;
|
|
@@ -10668,59 +10792,67 @@ vec2 noiseGrad(vec2 p) {
|
|
|
10668
10792
|
// layers sit close in weight so no single direction dominates. One coarse
|
|
10669
10793
|
// smooth layer keeps long-swell coherence underneath. The line this walks:
|
|
10670
10794
|
// PR-J's isotropic goop ←→ the crease field this replaces.
|
|
10795
|
+
// ============ the WATER-FEEL rewrite (the syrup fix) ============
|
|
10796
|
+
// The old detail layers had two viscosity bugs that made every surface read
|
|
10797
|
+
// as 꿀렁꿀렁한 gel instead of water:
|
|
10798
|
+
// 1. WRONG SPEED: each ripple layer drifted ~10× slower than a real wave
|
|
10799
|
+
// of its wavelength. Deep-water dispersion says a λ-meter wave travels
|
|
10800
|
+
// at c = sqrt(gλ/2π) — a 40 cm ripple crosses ITSELF ~2.7× per second.
|
|
10801
|
+
// Slow fine ripples are exactly what honey looks like.
|
|
10802
|
+
// 2. PATTERN SLIDING: a translated noise field reads as one sticker being
|
|
10803
|
+
// dragged (cellophane). Real ripple CHURNS — crests appear, interfere
|
|
10804
|
+
// and die. The fine octaves are therefore INTERFERENCE PAIRS: the same
|
|
10805
|
+
// wavelength read twice in slightly split directions and speeds; their
|
|
10806
|
+
// sum morphs continuously instead of sliding.
|
|
10807
|
+
// Four octaves, each advected at its REAL phase speed (in noise-space,
|
|
10808
|
+
// phase = c/λ per second — short waves flicker fast, the tell of thin
|
|
10809
|
+
// mobile water): λ 6.0 m → 0.51/s · 2.2 m → 0.84/s · 0.9 m → 1.31/s ·
|
|
10810
|
+
// 0.38 m → 2.02/s.
|
|
10671
10811
|
const vec2 WIND_DIR = vec2(0.8192, 0.5735);
|
|
10672
|
-
const float WIND_STRETCH = 1.7;
|
|
10673
10812
|
|
|
10674
|
-
vec2
|
|
10675
|
-
|
|
10813
|
+
vec2 octaveSlope(vec2 p, vec2 dir, float lambda, float t) {
|
|
10814
|
+
// advect ALONG the octave's travel direction at the dispersion speed
|
|
10815
|
+
float phase = sqrt(1.56 / lambda) * t; // c/λ = sqrt(g/(2πλ)) · … ≈ sqrt(1.56/λ)
|
|
10816
|
+
return noiseGrad(p / lambda + dir * phase);
|
|
10676
10817
|
}
|
|
10677
|
-
//
|
|
10678
|
-
|
|
10679
|
-
|
|
10818
|
+
// interference pair: same wavelength, directions split ±14°, speeds split
|
|
10819
|
+
// ±12% — the sum churns (crests are born and die) instead of sliding.
|
|
10820
|
+
vec2 octavePair(vec2 p, vec2 dir, float lambda, float t) {
|
|
10821
|
+
vec2 dA = normalize(dir + 0.25 * vec2(-dir.y, dir.x));
|
|
10822
|
+
vec2 dB = normalize(dir - 0.25 * vec2(-dir.y, dir.x));
|
|
10823
|
+
float phase = sqrt(1.56 / lambda) * t;
|
|
10824
|
+
return noiseGrad(p / lambda + dA * (phase * 1.12))
|
|
10825
|
+
+ noiseGrad(p / lambda * 1.07 + dB * (phase * 0.88) + 17.0);
|
|
10680
10826
|
}
|
|
10681
|
-
|
|
10682
|
-
vec2 ridgeGrad(vec2 p) {
|
|
10683
|
-
const float e = 0.05;
|
|
10684
|
-
float h = ridge(p);
|
|
10685
|
-
return vec2(ridge(p + vec2(e, 0.0)) - h, ridge(p + vec2(0.0, e)) - h) / e;
|
|
10686
|
-
}
|
|
10687
|
-
// dapple pass: the softened crest — ridge folds diluted ~half toward plain
|
|
10688
|
-
// simplex so crests read as short glints, never continuous crease lines.
|
|
10689
|
-
vec2 dappleGrad(vec2 p) { return mix(noiseGrad(p), ridgeGrad(p), 0.55); }
|
|
10827
|
+
|
|
10690
10828
|
vec3 detailNormal(vec3 n, vec2 worldXZ, float strength, float camDist) {
|
|
10691
10829
|
float fadeCoarse = 1.0 - smoothstep(90.0, 420.0, camDist);
|
|
10692
|
-
float fadeMid = 1.0 - smoothstep(40.0,
|
|
10693
|
-
float fadeFine = 1.0 - smoothstep(
|
|
10694
|
-
|
|
10695
|
-
vec2
|
|
10830
|
+
float fadeMid = 1.0 - smoothstep(40.0, 170.0, camDist);
|
|
10831
|
+
float fadeFine = 1.0 - smoothstep(18.0, 80.0, camDist);
|
|
10832
|
+
float fadeMicro = 1.0 - smoothstep(8.0, 34.0, camDist);
|
|
10833
|
+
vec2 dMid = normalize(vec2(0.62, 0.78));
|
|
10696
10834
|
vec2 slope =
|
|
10697
|
-
|
|
10698
|
-
|
|
10699
|
-
+
|
|
10700
|
-
|
|
10701
|
-
|
|
10702
|
-
* (0.25 * fadeFine);
|
|
10703
|
-
slope *= strength;
|
|
10835
|
+
octaveSlope(worldXZ, WIND_DIR, 6.0, uTime) * (0.085 * fadeCoarse)
|
|
10836
|
+
+ octaveSlope(worldXZ, dMid, 2.2, uTime) * (0.10 * fadeMid)
|
|
10837
|
+
+ octavePair(worldXZ, WIND_DIR, 0.9, uTime) * (0.055 * fadeFine)
|
|
10838
|
+
+ octavePair(worldXZ, dMid, 0.38, uTime) * (0.042 * fadeMicro);
|
|
10839
|
+
slope *= strength * 3.0; // spectrum norm: default strength 0.26 ≈ calm-lively
|
|
10704
10840
|
return normalize(vec3(n.x - slope.x, n.y, n.z - slope.y));
|
|
10705
10841
|
}
|
|
10706
10842
|
|
|
10707
|
-
//
|
|
10708
|
-
//
|
|
10709
|
-
//
|
|
10710
|
-
//
|
|
10711
|
-
// the
|
|
10712
|
-
// must read only the SMOOTH long-wavelength layers — the crisp ripple still
|
|
10713
|
-
// shows through the refraction offset and the sparse glints.
|
|
10843
|
+
// The GLOSS normal — what fresnel, the reflection and the refraction offset
|
|
10844
|
+
// read. Only the two long octaves: a mirror the size of a pixel integrates
|
|
10845
|
+
// micro-ripple away, so reflections stay smooth and ROUNDED (the glassy
|
|
10846
|
+
// pool-reference surface); the fast fine churn lives in the sun glitter and
|
|
10847
|
+
// the body shading, never as reflection speckle.
|
|
10714
10848
|
vec3 glossNormal(vec3 n, vec2 worldXZ, float strength, float camDist) {
|
|
10715
10849
|
float fadeCoarse = 1.0 - smoothstep(90.0, 420.0, camDist);
|
|
10716
|
-
float fadeMid = 1.0 - smoothstep(40.0,
|
|
10850
|
+
float fadeMid = 1.0 - smoothstep(40.0, 170.0, camDist);
|
|
10717
10851
|
vec2 dMid = normalize(vec2(0.62, 0.78));
|
|
10718
10852
|
vec2 slope =
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
* (0.16 * fadeMid);
|
|
10723
|
-
slope *= strength;
|
|
10853
|
+
octaveSlope(worldXZ, WIND_DIR, 6.0, uTime) * (0.085 * fadeCoarse)
|
|
10854
|
+
+ octaveSlope(worldXZ, dMid, 2.2, uTime) * (0.075 * fadeMid);
|
|
10855
|
+
slope *= strength * 3.0;
|
|
10724
10856
|
return normalize(vec3(n.x - slope.x, n.y, n.z - slope.y));
|
|
10725
10857
|
}
|
|
10726
10858
|
|
|
@@ -11031,6 +11163,22 @@ void main() {
|
|
|
11031
11163
|
// underwater scene. Real water blurs what it refracts; the crisp
|
|
11032
11164
|
// half-res grab pixel-speckled at every silhouette and ripple edge.
|
|
11033
11165
|
vec3 sceneColor = texture2D(uSceneColor, refractedUV, 1.75).rgb;
|
|
11166
|
+
// incanto presets: above-water caustics — reconstruct the sampled
|
|
11167
|
+
// bottom's world position along the view ray and light it with the
|
|
11168
|
+
// shared caustic web. Strongest through the first meters of water
|
|
11169
|
+
// (a pool floor dances, the deep sea does not), distance-faded so far
|
|
11170
|
+
// shallows never shimmer-alias.
|
|
11171
|
+
if (uCausticsAbove > 0.0) {
|
|
11172
|
+
vec3 bottomWorld = cameraPosition + viewDirection * refrT;
|
|
11173
|
+
float below = uWaterCenter.y - bottomWorld.y;
|
|
11174
|
+
if (below > 0.05) {
|
|
11175
|
+
float reach = 1.0 - smoothstep(0.2, 9.0, below);
|
|
11176
|
+
float causticFade = 1.0 - smoothstep(60.0, 200.0, camDist);
|
|
11177
|
+
float cw = caustic(bottomWorld.xz * 0.42, uTime * 0.7) * 0.65
|
|
11178
|
+
+ caustic(bottomWorld.xz * 0.72 + 30.0, uTime * 0.55) * 0.35;
|
|
11179
|
+
sceneColor += vec3(0.87, 0.96, 1.0) * (cw * uCausticsAbove * reach * causticFade);
|
|
11180
|
+
}
|
|
11181
|
+
}
|
|
11034
11182
|
// opacity keeps its dial under in-shader compositing: it scales how
|
|
11035
11183
|
// strongly the water body hides the Beer-attenuated scene behind it —
|
|
11036
11184
|
// per channel, so the shallows tint instead of fading uniformly
|
|
@@ -11071,7 +11219,7 @@ void main() {
|
|
|
11071
11219
|
// mirror (dark scenes otherwise paint the near edge black). refinement
|
|
11072
11220
|
// pass: 0.75 → 0.6 — the reference sea stays teal even at range; an HDR
|
|
11073
11221
|
// sky at 3/4 mirror washed the whole far field toward white.
|
|
11074
|
-
float reflectivity = clamp(fresnel, 0.0,
|
|
11222
|
+
float reflectivity = clamp(fresnel, 0.0, uReflectivityMax) * uUseEnvironmentMap;
|
|
11075
11223
|
vec3 finalColor = mix(bodyColor, reflectionColor.rgb, reflectivity);
|
|
11076
11224
|
|
|
11077
11225
|
// incanto v2: sun specular off the detail-perturbed normal.
|
|
@@ -11098,14 +11246,13 @@ void main() {
|
|
|
11098
11246
|
// grazing angles. Weight by a Schlick-like grazing term so steep views
|
|
11099
11247
|
// stay calm, clear water instead of speckling.
|
|
11100
11248
|
float grazing = pow(1.0 - clamp(dot(-viewDirection, vec3(0.0, 1.0, 0.0)), 0.0, 1.0), 2.0);
|
|
11101
|
-
//
|
|
11102
|
-
//
|
|
11103
|
-
//
|
|
11104
|
-
//
|
|
11105
|
-
float
|
|
11106
|
-
float
|
|
11107
|
-
|
|
11108
|
-
* (0.1 + 0.9 * grazing) * glintGate;
|
|
11249
|
+
// water-feel rewrite: NO artificial gate — the micro-ripple spectrum's
|
|
11250
|
+
// fast churn makes each facet align with the sun for only a flash, so the
|
|
11251
|
+
// glitter is naturally granular AND flickers at ripple speed (the old
|
|
11252
|
+
// slow-noise gate was another piece of the syrup feel).
|
|
11253
|
+
float glintFade = 1.0 - smoothstep(60.0, 240.0, camDist);
|
|
11254
|
+
float glint = pow(specAngle, 900.0) * (0.15 + 0.85 * sunPath) * glintFade
|
|
11255
|
+
* (0.1 + 0.9 * grazing);
|
|
11109
11256
|
float farAngle = max(dot(fresnelNormal, halfway), 0.0);
|
|
11110
11257
|
float streak = pow(farAngle, 240.0) * 0.45 * sunPath * (1.0 - glintFade);
|
|
11111
11258
|
float sheen = pow(specAngle, 64.0) * 0.05 * sunPath;
|
|
@@ -11394,6 +11541,108 @@ const COLOR_KEYS = [
|
|
|
11394
11541
|
"surface",
|
|
11395
11542
|
"peak"
|
|
11396
11543
|
];
|
|
11544
|
+
const WATER_PRESET_NAMES = [
|
|
11545
|
+
"custom",
|
|
11546
|
+
"ocean",
|
|
11547
|
+
"pool",
|
|
11548
|
+
"lake",
|
|
11549
|
+
"pond"
|
|
11550
|
+
];
|
|
11551
|
+
/**
|
|
11552
|
+
* The four curated water types — `preset: 'ocean' | 'pool' | 'lake' | 'pond'`
|
|
11553
|
+
* is THE one-choice dial: each bundle sets every wave/color/clarity/caustics
|
|
11554
|
+
* knob to a hand-tuned sea state. A preset value applies ONLY while the prop
|
|
11555
|
+
* still sits at its schema default (same convention as the env-sun handoff),
|
|
11556
|
+
* so any explicitly authored prop wins — pick the type, then override details
|
|
11557
|
+
* to taste.
|
|
11558
|
+
*
|
|
11559
|
+
* - ocean: traveling swell + whitecaps, wide turquoise→deep-blue absorption
|
|
11560
|
+
* - pool: near-flat crystal water, strong above-water caustics on the floor
|
|
11561
|
+
* - lake: calm mirror — high reflectivity, murkier green-teal depths
|
|
11562
|
+
* - pond: still, mossy, opaque quickly — the garden pond
|
|
11563
|
+
*/
|
|
11564
|
+
const WATER_PRESETS = {
|
|
11565
|
+
ocean: {
|
|
11566
|
+
waveHeight: .045,
|
|
11567
|
+
swell: .38,
|
|
11568
|
+
swellWavelength: 52,
|
|
11569
|
+
whitecaps: .4,
|
|
11570
|
+
absorption: .2,
|
|
11571
|
+
opacity: .85,
|
|
11572
|
+
detailStrength: .3,
|
|
11573
|
+
colors: {
|
|
11574
|
+
trough: "#0c3d58",
|
|
11575
|
+
surface: "#1a7d9c",
|
|
11576
|
+
peak: "#9adfe0"
|
|
11577
|
+
},
|
|
11578
|
+
color: "#1a7d9c",
|
|
11579
|
+
causticsAbove: .35,
|
|
11580
|
+
reflectionInterval: 400
|
|
11581
|
+
},
|
|
11582
|
+
pool: {
|
|
11583
|
+
waveHeight: .006,
|
|
11584
|
+
swell: 0,
|
|
11585
|
+
whitecaps: 0,
|
|
11586
|
+
absorption: .3,
|
|
11587
|
+
opacity: .5,
|
|
11588
|
+
detailStrength: .16,
|
|
11589
|
+
sunIntensity: 1.25,
|
|
11590
|
+
colors: {
|
|
11591
|
+
trough: "#1e8dbe",
|
|
11592
|
+
surface: "#3fb6dc",
|
|
11593
|
+
peak: "#bdeef7"
|
|
11594
|
+
},
|
|
11595
|
+
color: "#3fb6dc",
|
|
11596
|
+
causticsAbove: 1,
|
|
11597
|
+
reflectionInterval: 600,
|
|
11598
|
+
_look: {
|
|
11599
|
+
fresnelScale: .85,
|
|
11600
|
+
reflectivityMax: .5
|
|
11601
|
+
}
|
|
11602
|
+
},
|
|
11603
|
+
lake: {
|
|
11604
|
+
waveHeight: .028,
|
|
11605
|
+
swell: .14,
|
|
11606
|
+
swellWavelength: 24,
|
|
11607
|
+
whitecaps: 0,
|
|
11608
|
+
absorption: .5,
|
|
11609
|
+
opacity: .88,
|
|
11610
|
+
detailStrength: .3,
|
|
11611
|
+
colors: {
|
|
11612
|
+
trough: "#12343a",
|
|
11613
|
+
surface: "#25565c",
|
|
11614
|
+
peak: "#7fb2ab"
|
|
11615
|
+
},
|
|
11616
|
+
color: "#25565c",
|
|
11617
|
+
causticsAbove: .15,
|
|
11618
|
+
reflectionInterval: 300,
|
|
11619
|
+
_look: {
|
|
11620
|
+
fresnelScale: 1.25,
|
|
11621
|
+
reflectivityMax: .78
|
|
11622
|
+
}
|
|
11623
|
+
},
|
|
11624
|
+
pond: {
|
|
11625
|
+
waveHeight: .012,
|
|
11626
|
+
swell: 0,
|
|
11627
|
+
whitecaps: 0,
|
|
11628
|
+
absorption: .55,
|
|
11629
|
+
opacity: .88,
|
|
11630
|
+
detailStrength: .2,
|
|
11631
|
+
sunIntensity: .9,
|
|
11632
|
+
colors: {
|
|
11633
|
+
trough: "#24402a",
|
|
11634
|
+
surface: "#436b4d",
|
|
11635
|
+
peak: "#8fae8e"
|
|
11636
|
+
},
|
|
11637
|
+
color: "#436b4d",
|
|
11638
|
+
causticsAbove: .2,
|
|
11639
|
+
reflectionInterval: 800,
|
|
11640
|
+
_look: {
|
|
11641
|
+
fresnelScale: 1.1,
|
|
11642
|
+
reflectivityMax: .68
|
|
11643
|
+
}
|
|
11644
|
+
}
|
|
11645
|
+
};
|
|
11397
11646
|
/** Refinement-pass palette — teal-leaning sea blues sampled off the reference
|
|
11398
11647
|
* calm sea (deep open water ≈ #2b7993, mid teal ≈ #16878a). The old ported
|
|
11399
11648
|
* palette (#1f5b8a/#52a0d0/#aee3ff) read as saturated pool blue. */
|
|
@@ -11545,7 +11794,12 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11545
11794
|
swell: { default: 0 },
|
|
11546
11795
|
swellDirectionDeg: { default: 0 },
|
|
11547
11796
|
swellWavelength: { default: 30 },
|
|
11548
|
-
whitecaps: { default: 0 }
|
|
11797
|
+
whitecaps: { default: 0 },
|
|
11798
|
+
preset: {
|
|
11799
|
+
default: "custom",
|
|
11800
|
+
options: WATER_PRESET_NAMES
|
|
11801
|
+
},
|
|
11802
|
+
causticsAbove: { default: 0 }
|
|
11549
11803
|
};
|
|
11550
11804
|
/** [width, depth] in meters (the surface lies on XZ). */
|
|
11551
11805
|
size = [40, 40];
|
|
@@ -11615,6 +11869,40 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11615
11869
|
/** Open-water whitecap foam on the tallest crests, 0–1 (fancy only). Works
|
|
11616
11870
|
* best with `swell` — the caps ride the swell's crest lines. */
|
|
11617
11871
|
whitecaps = 0;
|
|
11872
|
+
/**
|
|
11873
|
+
* THE one-choice water type: 'ocean' | 'pool' | 'lake' | 'pond' bundles
|
|
11874
|
+
* every wave/color/clarity/caustics knob into a hand-tuned sea state
|
|
11875
|
+
* ('custom', the default, changes nothing). A preset value applies ONLY
|
|
11876
|
+
* where a prop still sits at its schema default — set the type first, then
|
|
11877
|
+
* override any detail prop to taste and your value wins.
|
|
11878
|
+
*/
|
|
11879
|
+
preset = "custom";
|
|
11880
|
+
/**
|
|
11881
|
+
* Above-water CAUSTICS intensity (0 = off): the dancing light web on the
|
|
11882
|
+
* submerged bottom, seen THROUGH the surface — the pool / tropical-shallows
|
|
11883
|
+
* look. Needs `refraction` (fancy quality). Presets set it; override freely.
|
|
11884
|
+
*/
|
|
11885
|
+
causticsAbove = 0;
|
|
11886
|
+
/** Preset-layered prop read (see {@link WATER_PRESETS}): the preset value
|
|
11887
|
+
* applies only while the prop sits at its schema default. */
|
|
11888
|
+
rp(key) {
|
|
11889
|
+
const bundle = WATER_PRESETS[this.preset];
|
|
11890
|
+
const self = this;
|
|
11891
|
+
if (bundle && key in bundle) {
|
|
11892
|
+
const def = Water3D.props[key]?.default;
|
|
11893
|
+
const cur = self[key];
|
|
11894
|
+
if (typeof cur === "object" && cur !== null ? JSON.stringify(cur) === JSON.stringify(def) : cur === def) return bundle[key];
|
|
11895
|
+
}
|
|
11896
|
+
return self[key];
|
|
11897
|
+
}
|
|
11898
|
+
/** Per-preset internal look constants (fresnel curve, reflection ceiling). */
|
|
11899
|
+
presetLook() {
|
|
11900
|
+
const look = WATER_PRESETS[this.preset]?._look;
|
|
11901
|
+
return {
|
|
11902
|
+
fresnelScale: look?.fresnelScale ?? FANCY_LOOK.fresnelScale,
|
|
11903
|
+
reflectivityMax: look?.reflectivityMax ?? .6
|
|
11904
|
+
};
|
|
11905
|
+
}
|
|
11618
11906
|
/** Loader hook: degenerate planes and bad enums fail at LOAD, not at render. */
|
|
11619
11907
|
static validateJson(node) {
|
|
11620
11908
|
const w = node;
|
|
@@ -11639,6 +11927,11 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11639
11927
|
if (!(w.swell >= 0) || !Number.isFinite(w.swell)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' swell must be >= 0 meters (0 = off), got ${JSON.stringify(w.swell)}.`, { prop: "swell" });
|
|
11640
11928
|
if (!(w.swellWavelength >= 2)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' swellWavelength must be >= 2 meters, got ${JSON.stringify(w.swellWavelength)}.`, { prop: "swellWavelength" });
|
|
11641
11929
|
if (!(w.whitecaps >= 0) || !(w.whitecaps <= 1)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' whitecaps must be in [0, 1], got ${JSON.stringify(w.whitecaps)}.`, { prop: "whitecaps" });
|
|
11930
|
+
if (!WATER_PRESET_NAMES.includes(w.preset)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' preset must be one of [${WATER_PRESET_NAMES.join(", ")}], got '${w.preset}'.`, {
|
|
11931
|
+
prop: "preset",
|
|
11932
|
+
validOptions: WATER_PRESET_NAMES
|
|
11933
|
+
});
|
|
11934
|
+
if (!(w.causticsAbove >= 0) || !(w.causticsAbove <= 3)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' causticsAbove must be in [0, 3] (0 = off), got ${JSON.stringify(w.causticsAbove)}.`, { prop: "causticsAbove" });
|
|
11642
11935
|
const uw = w.underwater;
|
|
11643
11936
|
if (typeof uw !== "boolean") {
|
|
11644
11937
|
if (typeof uw !== "object" || uw === null || Array.isArray(uw)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' underwater must be true, false or an object ({ color?, visibility? }), got ${JSON.stringify(uw)}.`, { prop: "underwater" });
|
|
@@ -11718,7 +12011,7 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11718
12011
|
this.cubeCamera = new CubeCamera(near, 1e3, this.cubeTarget);
|
|
11719
12012
|
this.lastReflectionAt = 0;
|
|
11720
12013
|
}
|
|
11721
|
-
if (this.lastReflectionAt === 0 || now - this.lastReflectionAt >= this.reflectionInterval) {
|
|
12014
|
+
if (this.lastReflectionAt === 0 || now - this.lastReflectionAt >= this.rp("reflectionInterval")) {
|
|
11722
12015
|
this.lastReflectionAt = now;
|
|
11723
12016
|
const center = worldTranslationOf(this);
|
|
11724
12017
|
const cam = this.cubeCamera;
|
|
@@ -11805,7 +12098,7 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11805
12098
|
halfW: (this.size[0] ?? 1) / 2,
|
|
11806
12099
|
halfD: (this.size[1] ?? 1) / 2
|
|
11807
12100
|
}, UNDERWATER_MARGIN)) return null;
|
|
11808
|
-
const cfg = resolveUnderwater(this.underwater, this.color);
|
|
12101
|
+
const cfg = resolveUnderwater(this.underwater, this.rp("color"));
|
|
11809
12102
|
return cfg.enabled ? {
|
|
11810
12103
|
...cfg,
|
|
11811
12104
|
surfaceY: center.y
|
|
@@ -11851,10 +12144,10 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11851
12144
|
fogFar: { value: 1e3 },
|
|
11852
12145
|
fogDensity: { value: 25e-5 },
|
|
11853
12146
|
uTime: { value: 0 },
|
|
11854
|
-
uOpacity: { value: this.opacity },
|
|
12147
|
+
uOpacity: { value: this.rp("opacity") },
|
|
11855
12148
|
uEnvironmentMap: { value: null },
|
|
11856
12149
|
uUseEnvironmentMap: { value: 0 },
|
|
11857
|
-
uWavesAmplitude: { value: this.waveHeight * AMPLITUDE_PER_WAVE_HEIGHT },
|
|
12150
|
+
uWavesAmplitude: { value: this.rp("waveHeight") * AMPLITUDE_PER_WAVE_HEIGHT },
|
|
11858
12151
|
uWavesSpeed: { value: FANCY_WAVE.speed },
|
|
11859
12152
|
uWavesFrequency: { value: FANCY_WAVE.frequency },
|
|
11860
12153
|
uWavesPersistence: { value: FANCY_WAVE.persistence },
|
|
@@ -11876,9 +12169,9 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11876
12169
|
uSplashFoam: { value: this.splash ? 1 : 0 },
|
|
11877
12170
|
uSunDirection: { value: new Vector3(.5, .8, .3) },
|
|
11878
12171
|
uSunColor: { value: new Color(this.sunColor) },
|
|
11879
|
-
uSunIntensity: { value: this.sunIntensity },
|
|
11880
|
-
uDetailStrength: { value: this.detailStrength },
|
|
11881
|
-
uAbsorption: { value: this.absorption },
|
|
12172
|
+
uSunIntensity: { value: this.rp("sunIntensity") },
|
|
12173
|
+
uDetailStrength: { value: this.rp("detailStrength") },
|
|
12174
|
+
uAbsorption: { value: this.rp("absorption") },
|
|
11882
12175
|
uUseSceneDepth: { value: 0 },
|
|
11883
12176
|
uUseRefraction: { value: 0 },
|
|
11884
12177
|
uSceneColor: { value: null },
|
|
@@ -11893,11 +12186,13 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11893
12186
|
uEdgeColor: { value: new Color(FOAM_LOOK.edgeColor) },
|
|
11894
12187
|
uEdgeIntensity: { value: FOAM_LOOK.edgeIntensity },
|
|
11895
12188
|
uEdgeWidth: { value: FOAM_LOOK.edgeWidth },
|
|
11896
|
-
uSwellAmplitude: { value: this.swell },
|
|
12189
|
+
uSwellAmplitude: { value: this.rp("swell") },
|
|
11897
12190
|
uSwellDir: { value: new Vector2(0, 1) },
|
|
11898
|
-
uSwellWavelength: { value: this.swellWavelength },
|
|
11899
|
-
uWhitecaps: { value: this.whitecaps },
|
|
11900
|
-
uWaveEnvelope: { value: 0 }
|
|
12191
|
+
uSwellWavelength: { value: this.rp("swellWavelength") },
|
|
12192
|
+
uWhitecaps: { value: this.rp("whitecaps") },
|
|
12193
|
+
uWaveEnvelope: { value: 0 },
|
|
12194
|
+
uCausticsAbove: { value: this.rp("causticsAbove") },
|
|
12195
|
+
uReflectivityMax: { value: .6 }
|
|
11901
12196
|
},
|
|
11902
12197
|
transparent: true,
|
|
11903
12198
|
depthTest: true,
|
|
@@ -11918,14 +12213,14 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11918
12213
|
fogFar: { value: 1e3 },
|
|
11919
12214
|
fogDensity: { value: 25e-5 },
|
|
11920
12215
|
uTime: { value: 0 },
|
|
11921
|
-
uOpacity: { value: this.opacity },
|
|
11922
|
-
uColor: { value: new Color(this.color) },
|
|
11923
|
-
uSurfaceColor: { value: new Color(this.color) },
|
|
11924
|
-
uSkyColor: { value: new Color(this.color) },
|
|
12216
|
+
uOpacity: { value: this.rp("opacity") },
|
|
12217
|
+
uColor: { value: new Color(this.rp("color")) },
|
|
12218
|
+
uSurfaceColor: { value: new Color(this.rp("color")) },
|
|
12219
|
+
uSkyColor: { value: new Color(this.rp("color")) },
|
|
11925
12220
|
uSunDirection: { value: new Vector3(.5, .8, .3).normalize() },
|
|
11926
12221
|
uSunColor: { value: new Color(this.sunColor) },
|
|
11927
|
-
uSunIntensity: { value: this.sunIntensity },
|
|
11928
|
-
uDetailStrength: { value: this.detailStrength },
|
|
12222
|
+
uSunIntensity: { value: this.rp("sunIntensity") },
|
|
12223
|
+
uDetailStrength: { value: this.rp("detailStrength") },
|
|
11929
12224
|
uFresnelPower: { value: FANCY_LOOK.fresnelPower },
|
|
11930
12225
|
uScale: { value: new Vector3(1, 1, 1) },
|
|
11931
12226
|
uWaterCenter: { value: new Vector3() },
|
|
@@ -11946,8 +12241,8 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11946
12241
|
const d = this.size[1] ?? 1;
|
|
11947
12242
|
const center = worldTranslationOf(this);
|
|
11948
12243
|
if (u.uTime) u.uTime.value = this.time;
|
|
11949
|
-
if (u.uOpacity) u.uOpacity.value = this.opacity;
|
|
11950
|
-
if (u.uWavesAmplitude) u.uWavesAmplitude.value = this.waveHeight * AMPLITUDE_PER_WAVE_HEIGHT;
|
|
12244
|
+
if (u.uOpacity) u.uOpacity.value = this.rp("opacity");
|
|
12245
|
+
if (u.uWavesAmplitude) u.uWavesAmplitude.value = this.rp("waveHeight") * AMPLITUDE_PER_WAVE_HEIGHT;
|
|
11951
12246
|
(u.uScale?.value)?.set(w / 2, d / 2, d / 2);
|
|
11952
12247
|
(u.uWaterCenter?.value)?.set(center.x, center.y, center.z);
|
|
11953
12248
|
const palette = this.resolvePalette();
|
|
@@ -11956,15 +12251,19 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11956
12251
|
(u.uPeakColor?.value)?.copy(palette.peak);
|
|
11957
12252
|
(u.uSunDirection?.value)?.set(this.sunDirection[0] ?? 0, this.sunDirection[1] ?? 1, this.sunDirection[2] ?? 0).normalize();
|
|
11958
12253
|
(u.uSunColor?.value)?.set(this.sunColor);
|
|
11959
|
-
if (u.uSunIntensity) u.uSunIntensity.value = this.sunIntensity;
|
|
11960
|
-
if (u.uDetailStrength) u.uDetailStrength.value = this.detailStrength;
|
|
11961
|
-
if (u.uAbsorption) u.uAbsorption.value = this.absorption;
|
|
11962
|
-
if (u.uSwellAmplitude) u.uSwellAmplitude.value = this.swell;
|
|
11963
|
-
if (u.uSwellWavelength) u.uSwellWavelength.value = this.swellWavelength;
|
|
11964
|
-
if (u.uWhitecaps) u.uWhitecaps.value = this.whitecaps;
|
|
12254
|
+
if (u.uSunIntensity) u.uSunIntensity.value = this.rp("sunIntensity");
|
|
12255
|
+
if (u.uDetailStrength) u.uDetailStrength.value = this.rp("detailStrength");
|
|
12256
|
+
if (u.uAbsorption) u.uAbsorption.value = this.rp("absorption");
|
|
12257
|
+
if (u.uSwellAmplitude) u.uSwellAmplitude.value = this.rp("swell");
|
|
12258
|
+
if (u.uSwellWavelength) u.uSwellWavelength.value = this.rp("swellWavelength");
|
|
12259
|
+
if (u.uWhitecaps) u.uWhitecaps.value = this.rp("whitecaps");
|
|
12260
|
+
if (u.uCausticsAbove) u.uCausticsAbove.value = this.rp("causticsAbove");
|
|
12261
|
+
const look = this.presetLook();
|
|
12262
|
+
if (u.uFresnelScale) u.uFresnelScale.value = look.fresnelScale;
|
|
12263
|
+
if (u.uReflectivityMax) u.uReflectivityMax.value = look.reflectivityMax;
|
|
11965
12264
|
const swellRad = this.swellDirectionDeg * Math.PI / 180;
|
|
11966
12265
|
(u.uSwellDir?.value)?.set(Math.sin(swellRad), Math.cos(swellRad));
|
|
11967
|
-
if (u.uWaveEnvelope) u.uWaveEnvelope.value = this.waveHeight * AMPLITUDE_PER_WAVE_HEIGHT * 1.5 + this.swell * 1.03;
|
|
12266
|
+
if (u.uWaveEnvelope) u.uWaveEnvelope.value = this.rp("waveHeight") * AMPLITUDE_PER_WAVE_HEIGHT * 1.5 + this.rp("swell") * 1.03;
|
|
11968
12267
|
if (!this.reflection && u.uUseEnvironmentMap) u.uUseEnvironmentMap.value = 0;
|
|
11969
12268
|
if (!this.foam && u.uEnableFoam) u.uEnableFoam.value = 0;
|
|
11970
12269
|
if (!this.refraction && u.uUseRefraction) u.uUseRefraction.value = 0;
|
|
@@ -11992,8 +12291,9 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11992
12291
|
}
|
|
11993
12292
|
/** The fancy three-color ramp; a customized legacy `color` tints it. */
|
|
11994
12293
|
resolvePalette() {
|
|
11995
|
-
const overrides = this.colors;
|
|
11996
|
-
const
|
|
12294
|
+
const overrides = this.rp("colors");
|
|
12295
|
+
const tint = this.rp("color");
|
|
12296
|
+
const legacyTint = tint !== Water3D.props.color?.default ? tint : null;
|
|
11997
12297
|
const surface = overrides.surface ?? legacyTint ?? FANCY_COLORS.surface;
|
|
11998
12298
|
paletteScratch.surface.set(surface);
|
|
11999
12299
|
if (overrides.trough) paletteScratch.trough.set(overrides.trough);
|
|
@@ -12006,22 +12306,22 @@ var Water3D = class Water3D extends Node3D {
|
|
|
12006
12306
|
}
|
|
12007
12307
|
syncSimple(mesh) {
|
|
12008
12308
|
const mat = mesh.material;
|
|
12009
|
-
mat.opacity = this.opacity;
|
|
12309
|
+
mat.opacity = this.rp("opacity");
|
|
12010
12310
|
const u = mat.uniforms;
|
|
12011
12311
|
const w = this.size[0] ?? 1;
|
|
12012
12312
|
const d = this.size[1] ?? 1;
|
|
12013
12313
|
const center = worldTranslationOf(this, this._scratchA);
|
|
12014
12314
|
if (u.uTime) u.uTime.value = this.time;
|
|
12015
|
-
if (u.uOpacity) u.uOpacity.value = this.opacity;
|
|
12016
|
-
(u.uSurfaceColor?.value)?.set(this.color).lerp(WHITE, .12);
|
|
12017
|
-
(u.uColor?.value)?.set(this.color).lerp(BLACK, .4);
|
|
12018
|
-
(u.uSkyColor?.value)?.set(this.color).lerp(SKY_PALE, .82);
|
|
12315
|
+
if (u.uOpacity) u.uOpacity.value = this.rp("opacity");
|
|
12316
|
+
(u.uSurfaceColor?.value)?.set(this.rp("color")).lerp(WHITE, .12);
|
|
12317
|
+
(u.uColor?.value)?.set(this.rp("color")).lerp(BLACK, .4);
|
|
12318
|
+
(u.uSkyColor?.value)?.set(this.rp("color")).lerp(SKY_PALE, .82);
|
|
12019
12319
|
(u.uScale?.value)?.set(w / 2, d / 2, d / 2);
|
|
12020
12320
|
(u.uWaterCenter?.value)?.set(center.x, center.y, center.z);
|
|
12021
12321
|
(u.uSunDirection?.value)?.set(this.sunDirection[0] ?? 0, this.sunDirection[1] ?? 1, this.sunDirection[2] ?? 0).normalize();
|
|
12022
12322
|
(u.uSunColor?.value)?.set(this.sunColor);
|
|
12023
|
-
if (u.uSunIntensity) u.uSunIntensity.value = this.sunIntensity;
|
|
12024
|
-
if (u.uDetailStrength) u.uDetailStrength.value = this.detailStrength;
|
|
12323
|
+
if (u.uSunIntensity) u.uSunIntensity.value = this.rp("sunIntensity");
|
|
12324
|
+
if (u.uDetailStrength) u.uDetailStrength.value = this.rp("detailStrength");
|
|
12025
12325
|
if (u.uSplashFoam) u.uSplashFoam.value = this.splash ? 1 : 0;
|
|
12026
12326
|
const uRip = u.uRipples?.value;
|
|
12027
12327
|
const uFoam = u.uRippleFoam?.value;
|
|
@@ -12035,7 +12335,7 @@ var Water3D = class Water3D extends Node3D {
|
|
|
12035
12335
|
const pos = geo.getAttribute("position");
|
|
12036
12336
|
const norm = geo.getAttribute("normal");
|
|
12037
12337
|
const t = this.time;
|
|
12038
|
-
const wh = this.waveHeight;
|
|
12338
|
+
const wh = this.rp("waveHeight");
|
|
12039
12339
|
const cx = center.x;
|
|
12040
12340
|
const cz = center.z;
|
|
12041
12341
|
const ripples = this._ripples;
|
|
@@ -12119,9 +12419,9 @@ var Water3D = class Water3D extends Node3D {
|
|
|
12119
12419
|
/** Base wave height at world (x, z) — the CPU twin of the active shader.
|
|
12120
12420
|
* Ripples are excluded on purpose: a splash must not re-trigger itself. */
|
|
12121
12421
|
waveOffsetAt(x, z, center) {
|
|
12122
|
-
if (this.quality === "simple") return simpleWaveHeight(x - center.x, z - center.z, this.time, this.waveHeight);
|
|
12422
|
+
if (this.quality === "simple") return simpleWaveHeight(x - center.x, z - center.z, this.time, this.rp("waveHeight"));
|
|
12123
12423
|
return waveElevation(x, z, this.time, {
|
|
12124
|
-
amplitude: this.waveHeight * AMPLITUDE_PER_WAVE_HEIGHT,
|
|
12424
|
+
amplitude: this.rp("waveHeight") * AMPLITUDE_PER_WAVE_HEIGHT,
|
|
12125
12425
|
frequency: FANCY_WAVE.frequency,
|
|
12126
12426
|
persistence: FANCY_WAVE.persistence,
|
|
12127
12427
|
lacunarity: FANCY_WAVE.lacunarity,
|
|
@@ -12241,4 +12541,4 @@ function registerNodes3D() {
|
|
|
12241
12541
|
registerNode(CharacterBody3D);
|
|
12242
12542
|
}
|
|
12243
12543
|
//#endregion
|
|
12244
|
-
export {
|
|
12544
|
+
export { Joint3D as A, keyboardIntensity as B, BoneLookAt3D as C, DEFAULT_TERRAIN_TEXTURE_BASE as D, Terrain3D as E, StaticBody3D as F, rigPose as H, Node3D as I, validateCollider3D as L, CharacterBody3D as M, PhysicsBody3D as N, TERRAIN_THEMES as O, RigidBody3D as P, QUARTER_PITCH as R, Camera3D as S, Billboard3D as T, movementState as V, DENSITY_PRESETS as _, VOXEL_PALETTE as a, FLOWER_VARIETIES as b, Trail3D as c, LoftMesh3D as d, DirectionalLight3D as f, Foliage3D as g, MeshInstance3D as h, WATER_MAX_RIPPLES as i, Area3D as j, terrainThemeLayers as k, Particles3D as l, InstancedMesh3D as m, Water3D as n, VoxelGrid3D as o, OmniLight3D as p, createCausticsQuad as r, Tree3D as s, registerNodes3D as t, ModelInstance3D as u, Flowers3D as v, BoneAttachment3D as w, CharacterController3D as x, resolveFlowerDensity as y, cameraRelative as z };
|