@d5techs/3dgs-lib 1.4.54 → 1.4.56

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
@@ -2196,7 +2196,7 @@ function float32ToFloat16(val) {
2196
2196
  const CUBE_WGSL = (
2197
2197
  /* wgsl */
2198
2198
  `
2199
- struct Uniforms { col0: vec4<f32>, col1: vec4<f32>, col2: vec4<f32> };
2199
+ struct Uniforms { col0: vec4<f32>, col1: vec4<f32>, col2: vec4<f32>, extra: vec4<f32> };
2200
2200
  @group(0) @binding(0) var<uniform> u: Uniforms;
2201
2201
  @group(0) @binding(1) var cubeSampler: sampler;
2202
2202
  @group(0) @binding(2) var cubeTexture: texture_cube<f32>;
@@ -2215,12 +2215,17 @@ struct V { @builtin(position) pos: vec4<f32>, @location(0) dir: vec3<f32> };
2215
2215
  const EQUIRECT_WGSL = (
2216
2216
  /* wgsl */
2217
2217
  `
2218
- struct Uniforms { col0: vec4<f32>, col1: vec4<f32>, col2: vec4<f32> };
2218
+ struct Uniforms { col0: vec4<f32>, col1: vec4<f32>, col2: vec4<f32>, extra: vec4<f32> };
2219
2219
  @group(0) @binding(0) var<uniform> u: Uniforms;
2220
2220
  @group(0) @binding(1) var envSampler: sampler;
2221
2221
  @group(0) @binding(2) var envTexture: texture_2d<f32>;
2222
2222
  struct V { @builtin(position) pos: vec4<f32>, @location(0) dir: vec3<f32> };
2223
2223
  const PI: f32 = 3.14159265358979;
2224
+
2225
+ fn dirToUv(d: vec3<f32>) -> vec2<f32> {
2226
+ return vec2(atan2(d.z, d.x) / (2.*PI) + .5, 1. - (asin(clamp(d.y,-1.,1.)) / PI + .5));
2227
+ }
2228
+
2224
2229
  @vertex fn vs(@builtin(vertex_index) vi: u32) -> V {
2225
2230
  let ps = array<vec2<f32>,3>(vec2(-1.,-1.),vec2(3.,-1.),vec2(-1.,3.));
2226
2231
  var o: V; let p = ps[vi]; o.pos = vec4(p, 0., 1.);
@@ -2228,10 +2233,46 @@ const PI: f32 = 3.14159265358979;
2228
2233
  o.dir = vec3(dot(u.col0.xyz,e), dot(u.col1.xyz,e), dot(u.col2.xyz,e));
2229
2234
  return o;
2230
2235
  }
2236
+
2231
2237
  @fragment fn fs(i: V) -> @location(0) vec4<f32> {
2232
2238
  let d = normalize(i.dir);
2233
- let uv = vec2(atan2(d.z, d.x) / (2.*PI) + .5, asin(clamp(d.y,-1.,1.)) / PI + .5);
2234
- let c = textureSample(envTexture, envSampler, vec2(uv.x, 1. - uv.y)).rgb;
2239
+ let camY = u.extra.x;
2240
+ let sphereR = u.extra.y;
2241
+
2242
+ // --- sky UV (always computed) ---
2243
+ let skyUv = dirToUv(d);
2244
+
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
+ let hitX = t * d.x;
2250
+ let hitZ = t * d.z;
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
+ let groundUv = dirToUv(groundDir);
2262
+
2263
+ // --- sample both (unconditional = uniform control flow) ---
2264
+ let skyColor = textureSample(envTexture, envSampler, skyUv).rgb;
2265
+ let groundColor = textureSample(envTexture, envSampler, groundUv).rgb;
2266
+
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);
2274
+
2275
+ // Reinhard tone mapping + gamma
2235
2276
  let mapped = c / (c + vec3(1.));
2236
2277
  let gamma = pow(mapped, vec3(1./2.2));
2237
2278
  return vec4(gamma, 1.);
@@ -2242,7 +2283,7 @@ class SkyboxRenderer {
2242
2283
  __publicField(this, "device");
2243
2284
  __publicField(this, "uniformBuffer");
2244
2285
  __publicField(this, "sampler");
2245
- __publicField(this, "uniformData", new Float32Array(12));
2286
+ __publicField(this, "uniformData", new Float32Array(16));
2246
2287
  __publicField(this, "cubePipeline");
2247
2288
  __publicField(this, "cubeBindGroupLayout");
2248
2289
  __publicField(this, "equirectPipeline");
@@ -2251,6 +2292,8 @@ class SkyboxRenderer {
2251
2292
  __publicField(this, "bindGroup", null);
2252
2293
  __publicField(this, "frameReady", false);
2253
2294
  __publicField(this, "mode", "none");
2295
+ /** Ground projection sphere radius (world units). Larger = ground extends further, flatter. */
2296
+ __publicField(this, "groundRadius", 500);
2254
2297
  this.device = device;
2255
2298
  const depthStencil = {
2256
2299
  format: depthFormat,
@@ -2259,7 +2302,7 @@ class SkyboxRenderer {
2259
2302
  };
2260
2303
  this.cubeBindGroupLayout = device.createBindGroupLayout({
2261
2304
  entries: [
2262
- { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } },
2305
+ { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
2263
2306
  { binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } },
2264
2307
  { binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float", viewDimension: "cube" } }
2265
2308
  ]
@@ -2273,7 +2316,7 @@ class SkyboxRenderer {
2273
2316
  });
2274
2317
  this.equirectBindGroupLayout = device.createBindGroupLayout({
2275
2318
  entries: [
2276
- { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } },
2319
+ { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
2277
2320
  { binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } },
2278
2321
  { binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float", viewDimension: "2d" } }
2279
2322
  ]
@@ -2286,7 +2329,7 @@ class SkyboxRenderer {
2286
2329
  depthStencil
2287
2330
  });
2288
2331
  this.uniformBuffer = device.createBuffer({
2289
- size: 48,
2332
+ size: 64,
2290
2333
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
2291
2334
  });
2292
2335
  this.sampler = device.createSampler({ magFilter: "linear", minFilter: "linear" });
@@ -2369,7 +2412,7 @@ class SkyboxRenderer {
2369
2412
  this.mode = "equirect";
2370
2413
  }
2371
2414
  // ---- common ----
2372
- prepareFrame(viewMatrix, projectionMatrix) {
2415
+ prepareFrame(viewMatrix, projectionMatrix, cameraPosition) {
2373
2416
  if (!this.isActive) {
2374
2417
  this.frameReady = false;
2375
2418
  return;
@@ -2387,6 +2430,10 @@ class SkyboxRenderer {
2387
2430
  ud[9] = viewMatrix[9];
2388
2431
  ud[10] = viewMatrix[10];
2389
2432
  ud[11] = 0;
2433
+ ud[12] = cameraPosition ? cameraPosition[1] : 0;
2434
+ ud[13] = this.groundRadius;
2435
+ ud[14] = 0;
2436
+ ud[15] = 0;
2390
2437
  this.device.queue.writeBuffer(this.uniformBuffer, 0, ud);
2391
2438
  this.frameReady = true;
2392
2439
  }
@@ -19023,9 +19070,11 @@ class App {
19023
19070
  this.updateAdaptivePerformance();
19024
19071
  this.hotspotManager.updateBillboards();
19025
19072
  if ((_a2 = this.skyboxRenderer) == null ? void 0 : _a2.isActive) {
19073
+ const cam = this.camera.position;
19026
19074
  this.skyboxRenderer.prepareFrame(
19027
19075
  this.camera.viewMatrix,
19028
- this.camera.projectionMatrix
19076
+ this.camera.projectionMatrix,
19077
+ [cam[0], cam[1], cam[2]]
19029
19078
  );
19030
19079
  }
19031
19080
  const pass = this.renderer.beginFrame();
@@ -19220,6 +19269,11 @@ class App {
19220
19269
  }
19221
19270
  await this.skyboxRenderer.loadEquirectangular(url);
19222
19271
  }
19272
+ setHdrGroundRadius(radius) {
19273
+ if (this.skyboxRenderer) {
19274
+ this.skyboxRenderer.groundRadius = radius;
19275
+ }
19276
+ }
19223
19277
  clearSkybox() {
19224
19278
  var _a2;
19225
19279
  (_a2 = this.skyboxRenderer) == null ? void 0 : _a2.clear();