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