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