@d5techs/3dgs-lib 1.4.38 → 1.4.40

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
@@ -2076,6 +2076,228 @@ class SceneAidsRenderer {
2076
2076
  this.axesBindGroup = null;
2077
2077
  }
2078
2078
  }
2079
+ const WGSL = (
2080
+ /* wgsl */
2081
+ `
2082
+ struct Uniforms {
2083
+ invViewProjNoTrans: mat4x4<f32>,
2084
+ };
2085
+
2086
+ @group(0) @binding(0) var<uniform> uniforms: Uniforms;
2087
+ @group(0) @binding(1) var cubeSampler: sampler;
2088
+ @group(0) @binding(2) var cubeTexture: texture_cube<f32>;
2089
+
2090
+ struct VSOut {
2091
+ @builtin(position) position: vec4<f32>,
2092
+ @location(0) dir: vec3<f32>,
2093
+ };
2094
+
2095
+ @vertex
2096
+ fn vs(@builtin(vertex_index) vi: u32) -> VSOut {
2097
+ let positions = array<vec2<f32>, 3>(
2098
+ vec2<f32>(-1.0, -1.0),
2099
+ vec2<f32>(3.0, -1.0),
2100
+ vec2<f32>(-1.0, 3.0),
2101
+ );
2102
+ var out: VSOut;
2103
+ let p = positions[vi];
2104
+ 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
+ return out;
2108
+ }
2109
+
2110
+ @fragment
2111
+ fn fs(input: VSOut) -> @location(0) vec4<f32> {
2112
+ return textureSample(cubeTexture, cubeSampler, normalize(input.dir));
2113
+ }
2114
+ `
2115
+ );
2116
+ class SkyboxRenderer {
2117
+ constructor(device, format, depthFormat) {
2118
+ __publicField(this, "device");
2119
+ __publicField(this, "format");
2120
+ __publicField(this, "depthFormat");
2121
+ __publicField(this, "shaderModule");
2122
+ __publicField(this, "bindGroupLayout");
2123
+ __publicField(this, "pipelineLayout");
2124
+ __publicField(this, "pipeline");
2125
+ __publicField(this, "uniformBuffer");
2126
+ __publicField(this, "sampler");
2127
+ __publicField(this, "scratchViewNoTrans", new Float32Array(16));
2128
+ __publicField(this, "scratchVp", new Float32Array(16));
2129
+ __publicField(this, "scratchInv", new Float32Array(16));
2130
+ __publicField(this, "cubeTexture", null);
2131
+ __publicField(this, "cubeBindGroup", null);
2132
+ this.device = device;
2133
+ this.format = format;
2134
+ this.depthFormat = depthFormat;
2135
+ this.shaderModule = device.createShaderModule({ code: WGSL });
2136
+ this.bindGroupLayout = device.createBindGroupLayout({
2137
+ 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
+ }
2153
+ ]
2154
+ });
2155
+ this.pipelineLayout = device.createPipelineLayout({
2156
+ bindGroupLayouts: [this.bindGroupLayout]
2157
+ });
2158
+ 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
+ }
2178
+ });
2179
+ this.uniformBuffer = device.createBuffer({
2180
+ size: 64,
2181
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
2182
+ });
2183
+ this.sampler = device.createSampler({
2184
+ magFilter: "linear",
2185
+ minFilter: "linear"
2186
+ });
2187
+ }
2188
+ get isActive() {
2189
+ return this.cubeTexture !== null && this.cubeBindGroup !== null;
2190
+ }
2191
+ async loadCubemap(faceUrls) {
2192
+ this.clear();
2193
+ const bitmaps = await Promise.all(
2194
+ faceUrls.map(async (url) => {
2195
+ 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);
2201
+ })
2202
+ );
2203
+ const width = bitmaps[0].width;
2204
+ const height = bitmaps[0].height;
2205
+ for (let i = 1; i < 6; i++) {
2206
+ if (bitmaps[i].width !== width || bitmaps[i].height !== height) {
2207
+ bitmaps.forEach((b) => b.close());
2208
+ throw new Error("SkyboxRenderer: all cubemap faces must share the same dimensions");
2209
+ }
2210
+ }
2211
+ const tex = this.device.createTexture({
2212
+ dimension: "2d",
2213
+ size: [width, height, 6],
2214
+ format: "rgba8unorm",
2215
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
2216
+ });
2217
+ for (let layer = 0; layer < 6; layer++) {
2218
+ this.device.queue.copyExternalImageToTexture(
2219
+ { source: bitmaps[layer] },
2220
+ { texture: tex, mipLevel: 0, origin: { x: 0, y: 0, z: layer } },
2221
+ { width, height, depthOrArrayLayers: 1 }
2222
+ );
2223
+ }
2224
+ bitmaps.forEach((b) => b.close());
2225
+ const cubeView = tex.createView({ dimension: "cube" });
2226
+ const bindGroup = this.device.createBindGroup({
2227
+ layout: this.bindGroupLayout,
2228
+ entries: [
2229
+ { binding: 0, resource: { buffer: this.uniformBuffer } },
2230
+ { binding: 1, resource: this.sampler },
2231
+ { binding: 2, resource: cubeView }
2232
+ ]
2233
+ });
2234
+ this.cubeTexture = tex;
2235
+ this.cubeBindGroup = bindGroup;
2236
+ }
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)) {
2247
+ return;
2248
+ }
2249
+ this.device.queue.writeBuffer(this.uniformBuffer, 0, this.scratchInv);
2250
+ pass.setPipeline(this.pipeline);
2251
+ pass.setBindGroup(0, this.cubeBindGroup);
2252
+ pass.draw(3);
2253
+ }
2254
+ clear() {
2255
+ if (this.cubeTexture) {
2256
+ this.cubeTexture.destroy();
2257
+ this.cubeTexture = null;
2258
+ }
2259
+ this.cubeBindGroup = null;
2260
+ }
2261
+ destroy() {
2262
+ this.clear();
2263
+ this.uniformBuffer.destroy();
2264
+ }
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
+ }
2079
2301
  class Mesh {
2080
2302
  constructor(vertexBuffer, vertexCount, indexBuffer = null, indexCount = 0, boundingBox) {
2081
2303
  __publicField(this, "vertexBuffer");
@@ -18242,6 +18464,7 @@ class App {
18242
18464
  __publicField(this, "gizmoManager");
18243
18465
  __publicField(this, "hotspotManager");
18244
18466
  __publicField(this, "sceneAids");
18467
+ __publicField(this, "skyboxRenderer", null);
18245
18468
  __publicField(this, "isRunning", false);
18246
18469
  __publicField(this, "animationId", 0);
18247
18470
  // 是否使用移动端渲染器
@@ -18681,11 +18904,15 @@ class App {
18681
18904
  }
18682
18905
  }
18683
18906
  render() {
18907
+ var _a2;
18684
18908
  this.camera.setAspect(this.renderer.getAspectRatio());
18685
18909
  this.controls.update();
18686
18910
  this.updateAdaptivePerformance();
18687
18911
  this.hotspotManager.updateBillboards();
18688
18912
  const pass = this.renderer.beginFrame();
18913
+ if ((_a2 = this.skyboxRenderer) == null ? void 0 : _a2.isActive) {
18914
+ this.skyboxRenderer.render(pass, this.camera.viewMatrix, this.camera.projectionMatrix);
18915
+ }
18689
18916
  const gsRenderer = this.sceneManager.getGSRenderer();
18690
18917
  if (gsRenderer) {
18691
18918
  gsRenderer.render(pass);
@@ -18845,6 +19072,34 @@ class App {
18845
19072
  return false;
18846
19073
  }
18847
19074
  // ============================================
19075
+ // Skybox
19076
+ // ============================================
19077
+ async setSkybox(faceUrls) {
19078
+ if (!this.skyboxRenderer) {
19079
+ this.skyboxRenderer = new SkyboxRenderer(
19080
+ this.renderer.device,
19081
+ this.renderer.format,
19082
+ "depth24plus"
19083
+ );
19084
+ }
19085
+ await this.skyboxRenderer.loadCubemap([
19086
+ faceUrls.posX,
19087
+ faceUrls.negX,
19088
+ faceUrls.posY,
19089
+ faceUrls.negY,
19090
+ faceUrls.posZ,
19091
+ faceUrls.negZ
19092
+ ]);
19093
+ }
19094
+ clearSkybox() {
19095
+ var _a2;
19096
+ (_a2 = this.skyboxRenderer) == null ? void 0 : _a2.clear();
19097
+ }
19098
+ isSkyboxActive() {
19099
+ var _a2;
19100
+ return ((_a2 = this.skyboxRenderer) == null ? void 0 : _a2.isActive) ?? false;
19101
+ }
19102
+ // ============================================
18848
19103
  // Gizmo(委托给 GizmoManager)
18849
19104
  // ============================================
18850
19105
  getTransformGizmo() {
@@ -19305,6 +19560,7 @@ export {
19305
19560
  SHMode,
19306
19561
  SceneAidsRenderer,
19307
19562
  SceneManager,
19563
+ SkyboxRenderer,
19308
19564
  SplatBoundingBoxProvider,
19309
19565
  SplatEditor,
19310
19566
  SplatState,