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