@d5techs/3dgs-lib 1.4.54 → 1.4.55

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,44 @@ 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 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;
2251
+ let hitX = t * d.x;
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));
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 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);
2274
+
2275
+ // Reinhard tone mapping + gamma
2237
2276
  let mapped = c / (c + vec3(1.));
2238
2277
  let gamma = pow(mapped, vec3(1./2.2));
2239
2278
  return vec4(gamma, 1.);
@@ -2244,7 +2283,7 @@ class SkyboxRenderer {
2244
2283
  __publicField(this, "device");
2245
2284
  __publicField(this, "uniformBuffer");
2246
2285
  __publicField(this, "sampler");
2247
- __publicField(this, "uniformData", new Float32Array(12));
2286
+ __publicField(this, "uniformData", new Float32Array(16));
2248
2287
  __publicField(this, "cubePipeline");
2249
2288
  __publicField(this, "cubeBindGroupLayout");
2250
2289
  __publicField(this, "equirectPipeline");
@@ -2253,6 +2292,8 @@ class SkyboxRenderer {
2253
2292
  __publicField(this, "bindGroup", null);
2254
2293
  __publicField(this, "frameReady", false);
2255
2294
  __publicField(this, "mode", "none");
2295
+ /** Ground projection sphere radius (world units). Larger = ground extends further. */
2296
+ __publicField(this, "groundRadius", 32);
2256
2297
  this.device = device;
2257
2298
  const depthStencil = {
2258
2299
  format: depthFormat,
@@ -2261,7 +2302,7 @@ class SkyboxRenderer {
2261
2302
  };
2262
2303
  this.cubeBindGroupLayout = device.createBindGroupLayout({
2263
2304
  entries: [
2264
- { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } },
2305
+ { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
2265
2306
  { binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } },
2266
2307
  { binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float", viewDimension: "cube" } }
2267
2308
  ]
@@ -2275,7 +2316,7 @@ class SkyboxRenderer {
2275
2316
  });
2276
2317
  this.equirectBindGroupLayout = device.createBindGroupLayout({
2277
2318
  entries: [
2278
- { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } },
2319
+ { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
2279
2320
  { binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } },
2280
2321
  { binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float", viewDimension: "2d" } }
2281
2322
  ]
@@ -2288,7 +2329,7 @@ class SkyboxRenderer {
2288
2329
  depthStencil
2289
2330
  });
2290
2331
  this.uniformBuffer = device.createBuffer({
2291
- size: 48,
2332
+ size: 64,
2292
2333
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
2293
2334
  });
2294
2335
  this.sampler = device.createSampler({ magFilter: "linear", minFilter: "linear" });
@@ -2371,7 +2412,7 @@ class SkyboxRenderer {
2371
2412
  this.mode = "equirect";
2372
2413
  }
2373
2414
  // ---- common ----
2374
- prepareFrame(viewMatrix, projectionMatrix) {
2415
+ prepareFrame(viewMatrix, projectionMatrix, cameraPosition) {
2375
2416
  if (!this.isActive) {
2376
2417
  this.frameReady = false;
2377
2418
  return;
@@ -2389,6 +2430,10 @@ class SkyboxRenderer {
2389
2430
  ud[9] = viewMatrix[9];
2390
2431
  ud[10] = viewMatrix[10];
2391
2432
  ud[11] = 0;
2433
+ ud[12] = cameraPosition ? cameraPosition[1] : 0;
2434
+ ud[13] = this.groundRadius;
2435
+ ud[14] = 0;
2436
+ ud[15] = 0;
2392
2437
  this.device.queue.writeBuffer(this.uniformBuffer, 0, ud);
2393
2438
  this.frameReady = true;
2394
2439
  }
@@ -19025,9 +19070,11 @@ class App {
19025
19070
  this.updateAdaptivePerformance();
19026
19071
  this.hotspotManager.updateBillboards();
19027
19072
  if ((_a2 = this.skyboxRenderer) == null ? void 0 : _a2.isActive) {
19073
+ const cam = this.camera.position;
19028
19074
  this.skyboxRenderer.prepareFrame(
19029
19075
  this.camera.viewMatrix,
19030
- this.camera.projectionMatrix
19076
+ this.camera.projectionMatrix,
19077
+ [cam[0], cam[1], cam[2]]
19031
19078
  );
19032
19079
  }
19033
19080
  const pass = this.renderer.beginFrame();
@@ -19222,6 +19269,11 @@ class App {
19222
19269
  }
19223
19270
  await this.skyboxRenderer.loadEquirectangular(url);
19224
19271
  }
19272
+ setHdrGroundRadius(radius) {
19273
+ if (this.skyboxRenderer) {
19274
+ this.skyboxRenderer.groundRadius = radius;
19275
+ }
19276
+ }
19225
19277
  clearSkybox() {
19226
19278
  var _a2;
19227
19279
  (_a2 = this.skyboxRenderer) == null ? void 0 : _a2.clear();