@d5techs/3dgs-lib 1.4.40 → 1.4.42

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
@@ -2082,10 +2082,12 @@ const WGSL = (
2082
2082
  /* wgsl */
2083
2083
  `
2084
2084
  struct Uniforms {
2085
- invViewProjNoTrans: mat4x4<f32>,
2085
+ col0: vec4<f32>,
2086
+ col1: vec4<f32>,
2087
+ col2: vec4<f32>,
2086
2088
  };
2087
2089
 
2088
- @group(0) @binding(0) var<uniform> uniforms: Uniforms;
2090
+ @group(0) @binding(0) var<uniform> u: Uniforms;
2089
2091
  @group(0) @binding(1) var cubeSampler: sampler;
2090
2092
  @group(0) @binding(2) var cubeTexture: texture_cube<f32>;
2091
2093
 
@@ -2104,88 +2106,58 @@ fn vs(@builtin(vertex_index) vi: u32) -> VSOut {
2104
2106
  var out: VSOut;
2105
2107
  let p = positions[vi];
2106
2108
  out.position = vec4<f32>(p, 0.0, 1.0);
2107
- let unprojected = uniforms.invViewProjNoTrans * vec4<f32>(p, 1.0, 1.0);
2108
- out.dir = unprojected.xyz / unprojected.w;
2109
+
2110
+ // col0.w = 1/proj[0] (aspect*tan(fov/2)), col1.w = 1/proj[5] (tan(fov/2))
2111
+ let eyeDir = vec3<f32>(p.x * u.col0.w, p.y * u.col1.w, -1.0);
2112
+
2113
+ // col0..2.xyz = rows of inverse view rotation (= transpose of view rotation)
2114
+ out.dir = vec3<f32>(
2115
+ dot(u.col0.xyz, eyeDir),
2116
+ dot(u.col1.xyz, eyeDir),
2117
+ dot(u.col2.xyz, eyeDir),
2118
+ );
2109
2119
  return out;
2110
2120
  }
2111
2121
 
2112
2122
  @fragment
2113
2123
  fn fs(input: VSOut) -> @location(0) vec4<f32> {
2114
- return textureSample(cubeTexture, cubeSampler, normalize(input.dir));
2124
+ let color = textureSample(cubeTexture, cubeSampler, normalize(input.dir));
2125
+ return vec4<f32>(color.rgb, 1.0);
2115
2126
  }
2116
2127
  `
2117
2128
  );
2118
2129
  class SkyboxRenderer {
2119
2130
  constructor(device, format, depthFormat) {
2120
2131
  __publicField(this, "device");
2121
- __publicField(this, "format");
2122
- __publicField(this, "depthFormat");
2123
- __publicField(this, "shaderModule");
2124
- __publicField(this, "bindGroupLayout");
2125
- __publicField(this, "pipelineLayout");
2126
2132
  __publicField(this, "pipeline");
2127
2133
  __publicField(this, "uniformBuffer");
2128
2134
  __publicField(this, "sampler");
2129
- __publicField(this, "scratchViewNoTrans", new Float32Array(16));
2130
- __publicField(this, "scratchVp", new Float32Array(16));
2131
- __publicField(this, "scratchInv", new Float32Array(16));
2135
+ __publicField(this, "bindGroupLayout");
2136
+ __publicField(this, "uniformData", new Float32Array(12));
2132
2137
  __publicField(this, "cubeTexture", null);
2133
2138
  __publicField(this, "cubeBindGroup", null);
2139
+ __publicField(this, "frameReady", false);
2134
2140
  this.device = device;
2135
- this.format = format;
2136
- this.depthFormat = depthFormat;
2137
- this.shaderModule = device.createShaderModule({ code: WGSL });
2141
+ const shaderModule = device.createShaderModule({ code: WGSL });
2138
2142
  this.bindGroupLayout = device.createBindGroupLayout({
2139
2143
  entries: [
2140
- {
2141
- binding: 0,
2142
- visibility: GPUShaderStage.VERTEX,
2143
- buffer: { type: "uniform", minBindingSize: 64 }
2144
- },
2145
- {
2146
- binding: 1,
2147
- visibility: GPUShaderStage.FRAGMENT,
2148
- sampler: { type: "filtering" }
2149
- },
2150
- {
2151
- binding: 2,
2152
- visibility: GPUShaderStage.FRAGMENT,
2153
- texture: { sampleType: "float", viewDimension: "cube" }
2154
- }
2144
+ { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } },
2145
+ { binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } },
2146
+ { binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float", viewDimension: "cube" } }
2155
2147
  ]
2156
2148
  });
2157
- this.pipelineLayout = device.createPipelineLayout({
2158
- bindGroupLayouts: [this.bindGroupLayout]
2159
- });
2160
2149
  this.pipeline = device.createRenderPipeline({
2161
- layout: this.pipelineLayout,
2162
- vertex: {
2163
- module: this.shaderModule,
2164
- entryPoint: "vs"
2165
- },
2166
- fragment: {
2167
- module: this.shaderModule,
2168
- entryPoint: "fs",
2169
- targets: [{ format: this.format }]
2170
- },
2171
- primitive: {
2172
- topology: "triangle-list",
2173
- cullMode: "none"
2174
- },
2175
- depthStencil: {
2176
- format: this.depthFormat,
2177
- depthWriteEnabled: false,
2178
- depthCompare: "always"
2179
- }
2150
+ layout: device.createPipelineLayout({ bindGroupLayouts: [this.bindGroupLayout] }),
2151
+ vertex: { module: shaderModule, entryPoint: "vs" },
2152
+ fragment: { module: shaderModule, entryPoint: "fs", targets: [{ format }] },
2153
+ primitive: { topology: "triangle-list", cullMode: "none" },
2154
+ depthStencil: { format: depthFormat, depthWriteEnabled: false, depthCompare: "always" }
2180
2155
  });
2181
2156
  this.uniformBuffer = device.createBuffer({
2182
- size: 64,
2157
+ size: 48,
2183
2158
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
2184
2159
  });
2185
- this.sampler = device.createSampler({
2186
- magFilter: "linear",
2187
- minFilter: "linear"
2188
- });
2160
+ this.sampler = device.createSampler({ magFilter: "linear", minFilter: "linear" });
2189
2161
  }
2190
2162
  get isActive() {
2191
2163
  return this.cubeTexture !== null && this.cubeBindGroup !== null;
@@ -2195,11 +2167,8 @@ class SkyboxRenderer {
2195
2167
  const bitmaps = await Promise.all(
2196
2168
  faceUrls.map(async (url) => {
2197
2169
  const res = await fetch(url);
2198
- if (!res.ok) {
2199
- throw new Error(`SkyboxRenderer: failed to fetch ${url} (${res.status})`);
2200
- }
2201
- const blob = await res.blob();
2202
- return createImageBitmap(blob);
2170
+ if (!res.ok) throw new Error(`SkyboxRenderer: failed to fetch ${url} (${res.status})`);
2171
+ return createImageBitmap(await res.blob());
2203
2172
  })
2204
2173
  );
2205
2174
  const width = bitmaps[0].width;
@@ -2224,31 +2193,43 @@ class SkyboxRenderer {
2224
2193
  );
2225
2194
  }
2226
2195
  bitmaps.forEach((b) => b.close());
2227
- const cubeView = tex.createView({ dimension: "cube" });
2228
- const bindGroup = this.device.createBindGroup({
2196
+ this.cubeBindGroup = this.device.createBindGroup({
2229
2197
  layout: this.bindGroupLayout,
2230
2198
  entries: [
2231
2199
  { binding: 0, resource: { buffer: this.uniformBuffer } },
2232
2200
  { binding: 1, resource: this.sampler },
2233
- { binding: 2, resource: cubeView }
2201
+ { binding: 2, resource: tex.createView({ dimension: "cube" }) }
2234
2202
  ]
2235
2203
  });
2236
2204
  this.cubeTexture = tex;
2237
- this.cubeBindGroup = bindGroup;
2238
2205
  }
2239
- render(pass, viewMatrix, projectionMatrix) {
2240
- if (!this.isActive || !this.cubeBindGroup) {
2241
- return;
2242
- }
2243
- this.scratchViewNoTrans.set(viewMatrix);
2244
- this.scratchViewNoTrans[12] = 0;
2245
- this.scratchViewNoTrans[13] = 0;
2246
- this.scratchViewNoTrans[14] = 0;
2247
- SkyboxRenderer.multiplyMat4(this.scratchVp, projectionMatrix, this.scratchViewNoTrans);
2248
- if (!SkyboxRenderer.invertMat4(this.scratchInv, this.scratchVp)) {
2206
+ /**
2207
+ * Write uniforms BEFORE beginFrame(). No matrix inversion needed —
2208
+ * we extract the view rotation transpose and inverse projection scalars directly.
2209
+ */
2210
+ prepareFrame(viewMatrix, projectionMatrix) {
2211
+ if (!this.isActive) {
2212
+ this.frameReady = false;
2249
2213
  return;
2250
2214
  }
2251
- this.device.queue.writeBuffer(this.uniformBuffer, 0, this.scratchInv);
2215
+ const ud = this.uniformData;
2216
+ ud[0] = viewMatrix[0];
2217
+ ud[1] = viewMatrix[1];
2218
+ ud[2] = viewMatrix[2];
2219
+ ud[3] = 1 / projectionMatrix[0];
2220
+ ud[4] = viewMatrix[4];
2221
+ ud[5] = viewMatrix[5];
2222
+ ud[6] = viewMatrix[6];
2223
+ ud[7] = 1 / projectionMatrix[5];
2224
+ ud[8] = viewMatrix[8];
2225
+ ud[9] = viewMatrix[9];
2226
+ ud[10] = viewMatrix[10];
2227
+ ud[11] = 0;
2228
+ this.device.queue.writeBuffer(this.uniformBuffer, 0, ud);
2229
+ this.frameReady = true;
2230
+ }
2231
+ draw(pass) {
2232
+ if (!this.frameReady || !this.cubeBindGroup) return;
2252
2233
  pass.setPipeline(this.pipeline);
2253
2234
  pass.setBindGroup(0, this.cubeBindGroup);
2254
2235
  pass.draw(3);
@@ -2259,46 +2240,12 @@ class SkyboxRenderer {
2259
2240
  this.cubeTexture = null;
2260
2241
  }
2261
2242
  this.cubeBindGroup = null;
2243
+ this.frameReady = false;
2262
2244
  }
2263
2245
  destroy() {
2264
2246
  this.clear();
2265
2247
  this.uniformBuffer.destroy();
2266
2248
  }
2267
- static invertMat4(out, e) {
2268
- const inv = new Float32Array(16);
2269
- inv[0] = e[5] * e[10] * e[15] - e[5] * e[11] * e[14] - e[9] * e[6] * e[15] + e[9] * e[7] * e[14] + e[13] * e[6] * e[11] - e[13] * e[7] * e[10];
2270
- inv[4] = -e[4] * e[10] * e[15] + e[4] * e[11] * e[14] + e[8] * e[6] * e[15] - e[8] * e[7] * e[14] - e[12] * e[6] * e[11] + e[12] * e[7] * e[10];
2271
- inv[8] = e[4] * e[9] * e[15] - e[4] * e[11] * e[13] - e[8] * e[5] * e[15] + e[8] * e[7] * e[13] + e[12] * e[5] * e[11] - e[12] * e[7] * e[9];
2272
- inv[12] = -e[4] * e[9] * e[14] + e[4] * e[10] * e[13] + e[8] * e[5] * e[14] - e[8] * e[6] * e[13] - e[12] * e[5] * e[10] + e[12] * e[6] * e[9];
2273
- inv[1] = -e[1] * e[10] * e[15] + e[1] * e[11] * e[14] + e[9] * e[2] * e[15] - e[9] * e[3] * e[14] - e[13] * e[2] * e[11] + e[13] * e[3] * e[10];
2274
- inv[5] = e[0] * e[10] * e[15] - e[0] * e[11] * e[14] - e[8] * e[2] * e[15] + e[8] * e[3] * e[14] + e[12] * e[2] * e[11] - e[12] * e[3] * e[10];
2275
- inv[9] = -e[0] * e[9] * e[15] + e[0] * e[11] * e[13] + e[8] * e[1] * e[15] - e[8] * e[3] * e[13] - e[12] * e[1] * e[11] + e[12] * e[3] * e[9];
2276
- inv[13] = e[0] * e[9] * e[14] - e[0] * e[10] * e[13] - e[8] * e[1] * e[14] + e[8] * e[2] * e[13] + e[12] * e[1] * e[10] - e[12] * e[2] * e[9];
2277
- inv[2] = e[1] * e[6] * e[15] - e[1] * e[7] * e[14] - e[5] * e[2] * e[15] + e[5] * e[3] * e[14] + e[13] * e[2] * e[7] - e[13] * e[3] * e[6];
2278
- inv[6] = -e[0] * e[6] * e[15] + e[0] * e[7] * e[14] + e[4] * e[2] * e[15] - e[4] * e[3] * e[14] - e[12] * e[2] * e[7] + e[12] * e[3] * e[6];
2279
- inv[10] = e[0] * e[5] * e[15] - e[0] * e[7] * e[13] - e[4] * e[1] * e[15] + e[4] * e[3] * e[13] + e[12] * e[1] * e[7] - e[12] * e[3] * e[5];
2280
- inv[14] = -e[0] * e[5] * e[14] + e[0] * e[6] * e[13] + e[4] * e[1] * e[14] - e[4] * e[2] * e[13] - e[12] * e[1] * e[6] + e[12] * e[2] * e[5];
2281
- inv[3] = -e[1] * e[6] * e[11] + e[1] * e[7] * e[10] + e[5] * e[2] * e[11] - e[5] * e[3] * e[10] - e[9] * e[2] * e[7] + e[9] * e[3] * e[6];
2282
- inv[7] = e[0] * e[6] * e[11] - e[0] * e[7] * e[10] - e[4] * e[2] * e[11] + e[4] * e[3] * e[10] + e[8] * e[2] * e[7] - e[8] * e[3] * e[6];
2283
- inv[11] = -e[0] * e[5] * e[11] + e[0] * e[7] * e[9] + e[4] * e[1] * e[11] - e[4] * e[3] * e[9] - e[8] * e[1] * e[7] + e[8] * e[3] * e[5];
2284
- inv[15] = e[0] * e[5] * e[10] - e[0] * e[6] * e[9] - e[4] * e[1] * e[10] + e[4] * e[2] * e[9] + e[8] * e[1] * e[6] - e[8] * e[2] * e[5];
2285
- const det = e[0] * inv[0] + e[1] * inv[4] + e[2] * inv[8] + e[3] * inv[12];
2286
- if (Math.abs(det) < 1e-10) {
2287
- return false;
2288
- }
2289
- const invDet = 1 / det;
2290
- for (let i = 0; i < 16; i++) {
2291
- out[i] = inv[i] * invDet;
2292
- }
2293
- return true;
2294
- }
2295
- static multiplyMat4(out, a, b) {
2296
- for (let c = 0; c < 4; c++) {
2297
- for (let r = 0; r < 4; r++) {
2298
- out[c * 4 + r] = a[0 * 4 + r] * b[c * 4 + 0] + a[1 * 4 + r] * b[c * 4 + 1] + a[2 * 4 + r] * b[c * 4 + 2] + a[3 * 4 + r] * b[c * 4 + 3];
2299
- }
2300
- }
2301
- }
2302
2249
  }
2303
2250
  class Mesh {
2304
2251
  constructor(vertexBuffer, vertexCount, indexBuffer = null, indexCount = 0, boundingBox) {
@@ -18906,14 +18853,17 @@ class App {
18906
18853
  }
18907
18854
  }
18908
18855
  render() {
18909
- var _a2;
18856
+ var _a2, _b2;
18910
18857
  this.camera.setAspect(this.renderer.getAspectRatio());
18911
18858
  this.controls.update();
18912
18859
  this.updateAdaptivePerformance();
18913
18860
  this.hotspotManager.updateBillboards();
18914
- const pass = this.renderer.beginFrame();
18915
18861
  if ((_a2 = this.skyboxRenderer) == null ? void 0 : _a2.isActive) {
18916
- this.skyboxRenderer.render(pass, this.camera.viewMatrix, this.camera.projectionMatrix);
18862
+ this.skyboxRenderer.prepareFrame(this.camera.viewMatrix, this.camera.projectionMatrix);
18863
+ }
18864
+ const pass = this.renderer.beginFrame();
18865
+ if ((_b2 = this.skyboxRenderer) == null ? void 0 : _b2.isActive) {
18866
+ this.skyboxRenderer.draw(pass);
18917
18867
  }
18918
18868
  const gsRenderer = this.sceneManager.getGSRenderer();
18919
18869
  if (gsRenderer) {