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