@d5techs/3dgs-lib 1.4.55 → 1.4.57

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/3dgs-lib.cjs CHANGED
@@ -2244,33 +2244,35 @@ fn dirToUv(d: vec3<f32>) -> vec2<f32> {
2244
2244
  // --- sky UV (always computed) ---
2245
2245
  let skyUv = dirToUv(d);
2246
2246
 
2247
- // --- ground projection UV (always computed to satisfy uniform control flow) ---
2248
- // ray-plane intersection: camera at height camY, plane y=0
2249
- let dySafe = select(d.y, -0.0001, d.y > -0.0001);
2250
- let t = -camY / dySafe;
2247
+ // --- ground projection (always computed for uniform control flow) ---
2248
+ // Ray from camera (0, camY, 0) in direction d hits plane y=0 at t
2249
+ let dyClamped = min(d.y, -0.0001);
2250
+ let t = -camY / dyClamped;
2251
2251
  let hitX = t * d.x;
2252
2252
  let hitZ = t * d.z;
2253
- let hitDist2 = hitX * hitX + hitZ * hitZ;
2254
- let R2 = sphereR * sphereR;
2255
- // clamp hit to sphere radius to avoid extreme stretching at edges
2256
- let needClamp = hitDist2 > R2;
2257
- let clampScale = select(1.0, sphereR / sqrt(max(hitDist2, 0.0001)), needClamp);
2258
- let pX = hitX * clampScale;
2259
- let pZ = hitZ * clampScale;
2260
- // project back onto sphere: y = -sqrt(R^2 - x^2 - z^2)
2261
- let projY = -sqrt(max(R2 - pX * pX - pZ * pZ, 0.0));
2262
- let groundDir = normalize(vec3(pX, projY, pZ));
2253
+ let hitDist = sqrt(hitX * hitX + hitZ * hitZ);
2254
+
2255
+ // Project the ground hit point back onto a sphere of radius R
2256
+ // centered at the camera projection on y=0 (i.e. center = origin).
2257
+ // For points beyond R, fade to horizon sampling.
2258
+ let ratio = min(hitDist, sphereR) / max(hitDist, 0.001);
2259
+ let pX = hitX * ratio;
2260
+ let pZ = hitZ * ratio;
2261
+ let pY = -sqrt(max(sphereR * sphereR - pX * pX - pZ * pZ, 0.0));
2262
+ let groundDir = normalize(vec3(pX, pY, pZ));
2263
2263
  let groundUv = dirToUv(groundDir);
2264
2264
 
2265
2265
  // --- sample both (unconditional = uniform control flow) ---
2266
2266
  let skyColor = textureSample(envTexture, envSampler, skyUv).rgb;
2267
2267
  let groundColor = textureSample(envTexture, envSampler, groundUv).rgb;
2268
2268
 
2269
- // blend near horizon for smooth transition
2270
- let blend = smoothstep(0.0, -0.08, d.y);
2271
- let mixed = mix(skyColor, groundColor, blend);
2272
- let useGround = d.y < 0.0 && camY > 0.01;
2273
- let c = select(skyColor, mixed, useGround);
2269
+ // Blend: smooth transition near horizon
2270
+ // step(0.01, camY) disables ground projection when camera is at/below ground
2271
+ let groundFactor = smoothstep(0.01, -0.15, d.y) * step(0.01, camY);
2272
+ // Fade out ground color at the sphere edge to avoid hard seam
2273
+ let edgeFade = 1.0 - smoothstep(sphereR * 0.7, sphereR * 0.99, hitDist);
2274
+ let finalBlend = groundFactor * edgeFade;
2275
+ let c = mix(skyColor, groundColor, finalBlend);
2274
2276
 
2275
2277
  // Reinhard tone mapping + gamma
2276
2278
  let mapped = c / (c + vec3(1.));
@@ -2292,8 +2294,8 @@ class SkyboxRenderer {
2292
2294
  __publicField(this, "bindGroup", null);
2293
2295
  __publicField(this, "frameReady", false);
2294
2296
  __publicField(this, "mode", "none");
2295
- /** Ground projection sphere radius (world units). Larger = ground extends further. */
2296
- __publicField(this, "groundRadius", 32);
2297
+ /** Ground projection sphere radius (world units). Larger = ground extends further, flatter. */
2298
+ __publicField(this, "groundRadius", 500);
2297
2299
  this.device = device;
2298
2300
  const depthStencil = {
2299
2301
  format: depthFormat,
@@ -2412,7 +2414,7 @@ class SkyboxRenderer {
2412
2414
  this.mode = "equirect";
2413
2415
  }
2414
2416
  // ---- common ----
2415
- prepareFrame(viewMatrix, projectionMatrix, cameraPosition) {
2417
+ prepareFrame(viewMatrix, projectionMatrix, cameraPosition, groundY) {
2416
2418
  if (!this.isActive) {
2417
2419
  this.frameReady = false;
2418
2420
  return;
@@ -2430,7 +2432,9 @@ class SkyboxRenderer {
2430
2432
  ud[9] = viewMatrix[9];
2431
2433
  ud[10] = viewMatrix[10];
2432
2434
  ud[11] = 0;
2433
- ud[12] = cameraPosition ? cameraPosition[1] : 0;
2435
+ const camWorldY = cameraPosition ? cameraPosition[1] : 0;
2436
+ const gndY = groundY ?? 0;
2437
+ ud[12] = camWorldY - gndY;
2434
2438
  ud[13] = this.groundRadius;
2435
2439
  ud[14] = 0;
2436
2440
  ud[15] = 0;
@@ -19071,10 +19075,22 @@ class App {
19071
19075
  this.hotspotManager.updateBillboards();
19072
19076
  if ((_a2 = this.skyboxRenderer) == null ? void 0 : _a2.isActive) {
19073
19077
  const cam = this.camera.position;
19078
+ let groundY = 0;
19079
+ const gsRenderer2 = this.sceneManager.getGSRenderer();
19080
+ if (gsRenderer2) {
19081
+ const bbox = gsRenderer2.getBoundingBox();
19082
+ if (bbox) {
19083
+ const m = gsRenderer2.getModelMatrix();
19084
+ const minLocalY = bbox.center[1] - bbox.radius;
19085
+ groundY = minLocalY * m[5] + bbox.center[1] * (m[5] - m[5]) + m[13];
19086
+ groundY = (bbox.center[1] - bbox.radius) * m[5] + m[13];
19087
+ }
19088
+ }
19074
19089
  this.skyboxRenderer.prepareFrame(
19075
19090
  this.camera.viewMatrix,
19076
19091
  this.camera.projectionMatrix,
19077
- [cam[0], cam[1], cam[2]]
19092
+ [cam[0], cam[1], cam[2]],
19093
+ groundY
19078
19094
  );
19079
19095
  }
19080
19096
  const pass = this.renderer.beginFrame();