@d5techs/3dgs-lib 1.4.52 → 1.4.54
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 +229 -96
- package/dist/3dgs-lib.cjs.map +1 -1
- package/dist/3dgs-lib.js +229 -96
- package/dist/3dgs-lib.js.map +1 -1
- package/dist/App.d.ts +1 -0
- package/dist/core/SkyboxRenderer.d.ts +8 -4
- package/dist/index.d.ts +2 -0
- package/dist/loaders/HdrLoader.d.ts +6 -0
- package/package.json +1 -1
package/dist/3dgs-lib.js
CHANGED
|
@@ -2096,122 +2096,211 @@ class SceneAidsRenderer {
|
|
|
2096
2096
|
this.axesBindGroup = null;
|
|
2097
2097
|
}
|
|
2098
2098
|
}
|
|
2099
|
-
|
|
2099
|
+
async function loadHdr(url) {
|
|
2100
|
+
const res = await fetch(url);
|
|
2101
|
+
if (!res.ok) throw new Error(`HdrLoader: fetch failed ${url} (${res.status})`);
|
|
2102
|
+
const buf = await res.arrayBuffer();
|
|
2103
|
+
return parseHdr(new Uint8Array(buf));
|
|
2104
|
+
}
|
|
2105
|
+
function parseHdr(bytes) {
|
|
2106
|
+
let pos = 0;
|
|
2107
|
+
const readLine = () => {
|
|
2108
|
+
let line = "";
|
|
2109
|
+
while (pos < bytes.length) {
|
|
2110
|
+
const c = bytes[pos++];
|
|
2111
|
+
if (c === 10) return line;
|
|
2112
|
+
line += String.fromCharCode(c);
|
|
2113
|
+
}
|
|
2114
|
+
return line;
|
|
2115
|
+
};
|
|
2116
|
+
const magic = readLine();
|
|
2117
|
+
if (!magic.startsWith("#?")) throw new Error("HdrLoader: not a Radiance HDR file");
|
|
2118
|
+
while (pos < bytes.length) {
|
|
2119
|
+
const line = readLine();
|
|
2120
|
+
if (line.length === 0) break;
|
|
2121
|
+
}
|
|
2122
|
+
const resLine = readLine();
|
|
2123
|
+
const m = resLine.match(/-Y\s+(\d+)\s+\+X\s+(\d+)/);
|
|
2124
|
+
if (!m) throw new Error("HdrLoader: unsupported resolution format: " + resLine);
|
|
2125
|
+
const height = parseInt(m[1], 10);
|
|
2126
|
+
const width = parseInt(m[2], 10);
|
|
2127
|
+
const rgbe = new Uint8Array(width * height * 4);
|
|
2128
|
+
for (let y = 0; y < height; y++) {
|
|
2129
|
+
const scanline = decodeScanline(bytes, pos, width);
|
|
2130
|
+
pos = scanline.newPos;
|
|
2131
|
+
rgbe.set(scanline.pixels, y * width * 4);
|
|
2132
|
+
}
|
|
2133
|
+
const data = new Float32Array(width * height * 4);
|
|
2134
|
+
for (let i = 0; i < width * height; i++) {
|
|
2135
|
+
const r = rgbe[i * 4];
|
|
2136
|
+
const g = rgbe[i * 4 + 1];
|
|
2137
|
+
const b = rgbe[i * 4 + 2];
|
|
2138
|
+
const e = rgbe[i * 4 + 3];
|
|
2139
|
+
if (e === 0) {
|
|
2140
|
+
data[i * 4] = 0;
|
|
2141
|
+
data[i * 4 + 1] = 0;
|
|
2142
|
+
data[i * 4 + 2] = 0;
|
|
2143
|
+
} else {
|
|
2144
|
+
const scale = Math.pow(2, e - 128 - 8);
|
|
2145
|
+
data[i * 4] = r * scale;
|
|
2146
|
+
data[i * 4 + 1] = g * scale;
|
|
2147
|
+
data[i * 4 + 2] = b * scale;
|
|
2148
|
+
}
|
|
2149
|
+
data[i * 4 + 3] = 1;
|
|
2150
|
+
}
|
|
2151
|
+
return { width, height, data };
|
|
2152
|
+
}
|
|
2153
|
+
function decodeScanline(bytes, pos, width) {
|
|
2154
|
+
const pixels = new Uint8Array(width * 4);
|
|
2155
|
+
if (width < 8 || width > 32767) {
|
|
2156
|
+
for (let i = 0; i < width * 4; i++) pixels[i] = bytes[pos++];
|
|
2157
|
+
return { pixels, newPos: pos };
|
|
2158
|
+
}
|
|
2159
|
+
const b0 = bytes[pos], b1 = bytes[pos + 1], b22 = bytes[pos + 2], b3 = bytes[pos + 3];
|
|
2160
|
+
if (b0 !== 2 || b1 !== 2 || (b22 & 128) !== 0) {
|
|
2161
|
+
for (let i = 0; i < width * 4; i++) pixels[i] = bytes[pos++];
|
|
2162
|
+
return { pixels, newPos: pos };
|
|
2163
|
+
}
|
|
2164
|
+
const lineWidth = b22 << 8 | b3;
|
|
2165
|
+
if (lineWidth !== width) throw new Error("HdrLoader: scanline width mismatch");
|
|
2166
|
+
pos += 4;
|
|
2167
|
+
for (let ch = 0; ch < 4; ch++) {
|
|
2168
|
+
let x = 0;
|
|
2169
|
+
while (x < width) {
|
|
2170
|
+
const code = bytes[pos++];
|
|
2171
|
+
if (code > 128) {
|
|
2172
|
+
const count = code - 128;
|
|
2173
|
+
const val = bytes[pos++];
|
|
2174
|
+
for (let i = 0; i < count; i++) pixels[(x + i) * 4 + ch] = val;
|
|
2175
|
+
x += count;
|
|
2176
|
+
} else {
|
|
2177
|
+
for (let i = 0; i < code; i++) pixels[(x + i) * 4 + ch] = bytes[pos++];
|
|
2178
|
+
x += code;
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
return { pixels, newPos: pos };
|
|
2183
|
+
}
|
|
2184
|
+
const f32Buf = new Float32Array(1);
|
|
2185
|
+
const u32Buf = new Uint32Array(f32Buf.buffer);
|
|
2186
|
+
function float32ToFloat16(val) {
|
|
2187
|
+
f32Buf[0] = val;
|
|
2188
|
+
const f = u32Buf[0];
|
|
2189
|
+
const sign = f >> 16 & 32768;
|
|
2190
|
+
const exp = (f >> 23 & 255) - 127 + 15;
|
|
2191
|
+
const frac = f >> 13 & 1023;
|
|
2192
|
+
if (exp <= 0) return sign;
|
|
2193
|
+
if (exp >= 31) return sign | 31744;
|
|
2194
|
+
return sign | exp << 10 | frac;
|
|
2195
|
+
}
|
|
2196
|
+
const CUBE_WGSL = (
|
|
2100
2197
|
/* wgsl */
|
|
2101
2198
|
`
|
|
2102
|
-
struct Uniforms {
|
|
2103
|
-
col0: vec4<f32>,
|
|
2104
|
-
col1: vec4<f32>,
|
|
2105
|
-
col2: vec4<f32>,
|
|
2106
|
-
};
|
|
2107
|
-
|
|
2199
|
+
struct Uniforms { col0: vec4<f32>, col1: vec4<f32>, col2: vec4<f32> };
|
|
2108
2200
|
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
2109
2201
|
@group(0) @binding(1) var cubeSampler: sampler;
|
|
2110
2202
|
@group(0) @binding(2) var cubeTexture: texture_cube<f32>;
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
fn vs(@builtin(vertex_index) vi: u32) -> VSOut {
|
|
2119
|
-
let positions = array<vec2<f32>, 3>(
|
|
2120
|
-
vec2<f32>(-1.0, -1.0),
|
|
2121
|
-
vec2<f32>(3.0, -1.0),
|
|
2122
|
-
vec2<f32>(-1.0, 3.0),
|
|
2123
|
-
);
|
|
2124
|
-
var out: VSOut;
|
|
2125
|
-
let p = positions[vi];
|
|
2126
|
-
out.position = vec4<f32>(p, 0.0, 1.0);
|
|
2127
|
-
|
|
2128
|
-
let eyeDir = vec3<f32>(p.x * u.col0.w, p.y * u.col1.w, -1.0);
|
|
2129
|
-
|
|
2130
|
-
out.dir = vec3<f32>(
|
|
2131
|
-
dot(u.col0.xyz, eyeDir),
|
|
2132
|
-
dot(u.col1.xyz, eyeDir),
|
|
2133
|
-
dot(u.col2.xyz, eyeDir),
|
|
2134
|
-
);
|
|
2135
|
-
return out;
|
|
2203
|
+
struct V { @builtin(position) pos: vec4<f32>, @location(0) dir: vec3<f32> };
|
|
2204
|
+
@vertex fn vs(@builtin(vertex_index) vi: u32) -> V {
|
|
2205
|
+
let ps = array<vec2<f32>,3>(vec2(-1.,-1.),vec2(3.,-1.),vec2(-1.,3.));
|
|
2206
|
+
var o: V; let p = ps[vi]; o.pos = vec4(p, 0., 1.);
|
|
2207
|
+
let e = vec3(p.x*u.col0.w, p.y*u.col1.w, -1.);
|
|
2208
|
+
o.dir = vec3(dot(u.col0.xyz,e), dot(u.col1.xyz,e), dot(u.col2.xyz,e));
|
|
2209
|
+
return o;
|
|
2136
2210
|
}
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2211
|
+
@fragment fn fs(i: V) -> @location(0) vec4<f32> {
|
|
2212
|
+
return vec4(textureSample(cubeTexture, cubeSampler, normalize(i.dir)).rgb, 1.);
|
|
2213
|
+
}`
|
|
2214
|
+
);
|
|
2215
|
+
const EQUIRECT_WGSL = (
|
|
2216
|
+
/* wgsl */
|
|
2217
|
+
`
|
|
2218
|
+
struct Uniforms { col0: vec4<f32>, col1: vec4<f32>, col2: vec4<f32> };
|
|
2219
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
2220
|
+
@group(0) @binding(1) var envSampler: sampler;
|
|
2221
|
+
@group(0) @binding(2) var envTexture: texture_2d<f32>;
|
|
2222
|
+
struct V { @builtin(position) pos: vec4<f32>, @location(0) dir: vec3<f32> };
|
|
2223
|
+
const PI: f32 = 3.14159265358979;
|
|
2224
|
+
@vertex fn vs(@builtin(vertex_index) vi: u32) -> V {
|
|
2225
|
+
let ps = array<vec2<f32>,3>(vec2(-1.,-1.),vec2(3.,-1.),vec2(-1.,3.));
|
|
2226
|
+
var o: V; let p = ps[vi]; o.pos = vec4(p, 0., 1.);
|
|
2227
|
+
let e = vec3(p.x*u.col0.w, p.y*u.col1.w, -1.);
|
|
2228
|
+
o.dir = vec3(dot(u.col0.xyz,e), dot(u.col1.xyz,e), dot(u.col2.xyz,e));
|
|
2229
|
+
return o;
|
|
2142
2230
|
}
|
|
2143
|
-
|
|
2231
|
+
@fragment fn fs(i: V) -> @location(0) vec4<f32> {
|
|
2232
|
+
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;
|
|
2235
|
+
let mapped = c / (c + vec3(1.));
|
|
2236
|
+
let gamma = pow(mapped, vec3(1./2.2));
|
|
2237
|
+
return vec4(gamma, 1.);
|
|
2238
|
+
}`
|
|
2144
2239
|
);
|
|
2145
2240
|
class SkyboxRenderer {
|
|
2146
2241
|
constructor(device, format, depthFormat) {
|
|
2147
2242
|
__publicField(this, "device");
|
|
2148
|
-
__publicField(this, "pipeline");
|
|
2149
2243
|
__publicField(this, "uniformBuffer");
|
|
2150
2244
|
__publicField(this, "sampler");
|
|
2151
|
-
__publicField(this, "bindGroupLayout");
|
|
2152
2245
|
__publicField(this, "uniformData", new Float32Array(12));
|
|
2153
|
-
__publicField(this, "
|
|
2154
|
-
__publicField(this, "
|
|
2246
|
+
__publicField(this, "cubePipeline");
|
|
2247
|
+
__publicField(this, "cubeBindGroupLayout");
|
|
2248
|
+
__publicField(this, "equirectPipeline");
|
|
2249
|
+
__publicField(this, "equirectBindGroupLayout");
|
|
2250
|
+
__publicField(this, "texture", null);
|
|
2251
|
+
__publicField(this, "bindGroup", null);
|
|
2155
2252
|
__publicField(this, "frameReady", false);
|
|
2253
|
+
__publicField(this, "mode", "none");
|
|
2156
2254
|
this.device = device;
|
|
2157
|
-
const
|
|
2158
|
-
|
|
2255
|
+
const depthStencil = {
|
|
2256
|
+
format: depthFormat,
|
|
2257
|
+
depthWriteEnabled: false,
|
|
2258
|
+
depthCompare: "always"
|
|
2259
|
+
};
|
|
2260
|
+
this.cubeBindGroupLayout = device.createBindGroupLayout({
|
|
2159
2261
|
entries: [
|
|
2160
|
-
{
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
buffer: { type: "uniform" }
|
|
2164
|
-
},
|
|
2165
|
-
{
|
|
2166
|
-
binding: 1,
|
|
2167
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
2168
|
-
sampler: { type: "filtering" }
|
|
2169
|
-
},
|
|
2170
|
-
{
|
|
2171
|
-
binding: 2,
|
|
2172
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
2173
|
-
texture: { sampleType: "float", viewDimension: "cube" }
|
|
2174
|
-
}
|
|
2262
|
+
{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } },
|
|
2263
|
+
{ binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } },
|
|
2264
|
+
{ binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float", viewDimension: "cube" } }
|
|
2175
2265
|
]
|
|
2176
2266
|
});
|
|
2177
|
-
this.
|
|
2178
|
-
layout: device.createPipelineLayout({
|
|
2179
|
-
|
|
2180
|
-
}),
|
|
2181
|
-
vertex: { module: shaderModule, entryPoint: "vs" },
|
|
2182
|
-
fragment: {
|
|
2183
|
-
module: shaderModule,
|
|
2184
|
-
entryPoint: "fs",
|
|
2185
|
-
targets: [{ format }]
|
|
2186
|
-
},
|
|
2267
|
+
this.cubePipeline = device.createRenderPipeline({
|
|
2268
|
+
layout: device.createPipelineLayout({ bindGroupLayouts: [this.cubeBindGroupLayout] }),
|
|
2269
|
+
vertex: { module: device.createShaderModule({ code: CUBE_WGSL }), entryPoint: "vs" },
|
|
2270
|
+
fragment: { module: device.createShaderModule({ code: CUBE_WGSL }), entryPoint: "fs", targets: [{ format }] },
|
|
2187
2271
|
primitive: { topology: "triangle-list", cullMode: "none" },
|
|
2188
|
-
depthStencil
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2272
|
+
depthStencil
|
|
2273
|
+
});
|
|
2274
|
+
this.equirectBindGroupLayout = device.createBindGroupLayout({
|
|
2275
|
+
entries: [
|
|
2276
|
+
{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } },
|
|
2277
|
+
{ binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } },
|
|
2278
|
+
{ binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float", viewDimension: "2d" } }
|
|
2279
|
+
]
|
|
2280
|
+
});
|
|
2281
|
+
this.equirectPipeline = device.createRenderPipeline({
|
|
2282
|
+
layout: device.createPipelineLayout({ bindGroupLayouts: [this.equirectBindGroupLayout] }),
|
|
2283
|
+
vertex: { module: device.createShaderModule({ code: EQUIRECT_WGSL }), entryPoint: "vs" },
|
|
2284
|
+
fragment: { module: device.createShaderModule({ code: EQUIRECT_WGSL }), entryPoint: "fs", targets: [{ format }] },
|
|
2285
|
+
primitive: { topology: "triangle-list", cullMode: "none" },
|
|
2286
|
+
depthStencil
|
|
2193
2287
|
});
|
|
2194
2288
|
this.uniformBuffer = device.createBuffer({
|
|
2195
2289
|
size: 48,
|
|
2196
2290
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
2197
2291
|
});
|
|
2198
|
-
this.sampler = device.createSampler({
|
|
2199
|
-
magFilter: "linear",
|
|
2200
|
-
minFilter: "linear"
|
|
2201
|
-
});
|
|
2292
|
+
this.sampler = device.createSampler({ magFilter: "linear", minFilter: "linear" });
|
|
2202
2293
|
}
|
|
2203
2294
|
get isActive() {
|
|
2204
|
-
return this.
|
|
2295
|
+
return this.mode !== "none" && this.texture !== null && this.bindGroup !== null;
|
|
2205
2296
|
}
|
|
2297
|
+
// ---- cubemap ----
|
|
2206
2298
|
async loadCubemap(faceUrls) {
|
|
2207
2299
|
this.clear();
|
|
2208
2300
|
const bitmaps = await Promise.all(
|
|
2209
2301
|
faceUrls.map(async (url) => {
|
|
2210
2302
|
const res = await fetch(url);
|
|
2211
|
-
if (!res.ok)
|
|
2212
|
-
throw new Error(
|
|
2213
|
-
`SkyboxRenderer: failed to fetch ${url} (${res.status})`
|
|
2214
|
-
);
|
|
2303
|
+
if (!res.ok) throw new Error(`SkyboxRenderer: failed to fetch ${url} (${res.status})`);
|
|
2215
2304
|
return createImageBitmap(await res.blob());
|
|
2216
2305
|
})
|
|
2217
2306
|
);
|
|
@@ -2220,9 +2309,7 @@ class SkyboxRenderer {
|
|
|
2220
2309
|
for (let i = 1; i < 6; i++) {
|
|
2221
2310
|
if (bitmaps[i].width !== width || bitmaps[i].height !== height) {
|
|
2222
2311
|
bitmaps.forEach((b) => b.close());
|
|
2223
|
-
throw new Error(
|
|
2224
|
-
"SkyboxRenderer: all cubemap faces must share the same dimensions"
|
|
2225
|
-
);
|
|
2312
|
+
throw new Error("SkyboxRenderer: all cubemap faces must share the same dimensions");
|
|
2226
2313
|
}
|
|
2227
2314
|
}
|
|
2228
2315
|
const tex = this.device.createTexture({
|
|
@@ -2239,16 +2326,49 @@ class SkyboxRenderer {
|
|
|
2239
2326
|
);
|
|
2240
2327
|
}
|
|
2241
2328
|
bitmaps.forEach((b) => b.close());
|
|
2242
|
-
this.
|
|
2243
|
-
layout: this.
|
|
2329
|
+
this.bindGroup = this.device.createBindGroup({
|
|
2330
|
+
layout: this.cubeBindGroupLayout,
|
|
2244
2331
|
entries: [
|
|
2245
2332
|
{ binding: 0, resource: { buffer: this.uniformBuffer } },
|
|
2246
2333
|
{ binding: 1, resource: this.sampler },
|
|
2247
2334
|
{ binding: 2, resource: tex.createView({ dimension: "cube" }) }
|
|
2248
2335
|
]
|
|
2249
2336
|
});
|
|
2250
|
-
this.
|
|
2337
|
+
this.texture = tex;
|
|
2338
|
+
this.mode = "cubemap";
|
|
2251
2339
|
}
|
|
2340
|
+
// ---- equirectangular HDR ----
|
|
2341
|
+
async loadEquirectangular(url) {
|
|
2342
|
+
this.clear();
|
|
2343
|
+
const hdr = await loadHdr(url);
|
|
2344
|
+
const pixelCount = hdr.width * hdr.height * 4;
|
|
2345
|
+
const f16 = new Uint16Array(pixelCount);
|
|
2346
|
+
for (let i = 0; i < pixelCount; i++) {
|
|
2347
|
+
f16[i] = float32ToFloat16(hdr.data[i]);
|
|
2348
|
+
}
|
|
2349
|
+
const tex = this.device.createTexture({
|
|
2350
|
+
size: [hdr.width, hdr.height],
|
|
2351
|
+
format: "rgba16float",
|
|
2352
|
+
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST
|
|
2353
|
+
});
|
|
2354
|
+
this.device.queue.writeTexture(
|
|
2355
|
+
{ texture: tex },
|
|
2356
|
+
f16.buffer,
|
|
2357
|
+
{ bytesPerRow: hdr.width * 8, rowsPerImage: hdr.height },
|
|
2358
|
+
{ width: hdr.width, height: hdr.height }
|
|
2359
|
+
);
|
|
2360
|
+
this.bindGroup = this.device.createBindGroup({
|
|
2361
|
+
layout: this.equirectBindGroupLayout,
|
|
2362
|
+
entries: [
|
|
2363
|
+
{ binding: 0, resource: { buffer: this.uniformBuffer } },
|
|
2364
|
+
{ binding: 1, resource: this.sampler },
|
|
2365
|
+
{ binding: 2, resource: tex.createView() }
|
|
2366
|
+
]
|
|
2367
|
+
});
|
|
2368
|
+
this.texture = tex;
|
|
2369
|
+
this.mode = "equirect";
|
|
2370
|
+
}
|
|
2371
|
+
// ---- common ----
|
|
2252
2372
|
prepareFrame(viewMatrix, projectionMatrix) {
|
|
2253
2373
|
if (!this.isActive) {
|
|
2254
2374
|
this.frameReady = false;
|
|
@@ -2271,18 +2391,20 @@ class SkyboxRenderer {
|
|
|
2271
2391
|
this.frameReady = true;
|
|
2272
2392
|
}
|
|
2273
2393
|
draw(pass) {
|
|
2274
|
-
if (!this.frameReady || !this.
|
|
2275
|
-
|
|
2276
|
-
pass.
|
|
2394
|
+
if (!this.frameReady || !this.bindGroup) return;
|
|
2395
|
+
const pipeline = this.mode === "cubemap" ? this.cubePipeline : this.equirectPipeline;
|
|
2396
|
+
pass.setPipeline(pipeline);
|
|
2397
|
+
pass.setBindGroup(0, this.bindGroup);
|
|
2277
2398
|
pass.draw(3);
|
|
2278
2399
|
}
|
|
2279
2400
|
clear() {
|
|
2280
|
-
if (this.
|
|
2281
|
-
this.
|
|
2282
|
-
this.
|
|
2401
|
+
if (this.texture) {
|
|
2402
|
+
this.texture.destroy();
|
|
2403
|
+
this.texture = null;
|
|
2283
2404
|
}
|
|
2284
|
-
this.
|
|
2405
|
+
this.bindGroup = null;
|
|
2285
2406
|
this.frameReady = false;
|
|
2407
|
+
this.mode = "none";
|
|
2286
2408
|
}
|
|
2287
2409
|
destroy() {
|
|
2288
2410
|
this.clear();
|
|
@@ -19088,6 +19210,16 @@ class App {
|
|
|
19088
19210
|
faceUrls.negZ
|
|
19089
19211
|
]);
|
|
19090
19212
|
}
|
|
19213
|
+
async setHdrBackground(url) {
|
|
19214
|
+
if (!this.skyboxRenderer) {
|
|
19215
|
+
this.skyboxRenderer = new SkyboxRenderer(
|
|
19216
|
+
this.renderer.device,
|
|
19217
|
+
this.renderer.format,
|
|
19218
|
+
"depth24plus"
|
|
19219
|
+
);
|
|
19220
|
+
}
|
|
19221
|
+
await this.skyboxRenderer.loadEquirectangular(url);
|
|
19222
|
+
}
|
|
19091
19223
|
clearSkybox() {
|
|
19092
19224
|
var _a2;
|
|
19093
19225
|
(_a2 = this.skyboxRenderer) == null ? void 0 : _a2.clear();
|
|
@@ -19580,6 +19712,7 @@ export {
|
|
|
19580
19712
|
getRecommendedDPR,
|
|
19581
19713
|
isMobileDevice,
|
|
19582
19714
|
isWebGPUSupported,
|
|
19715
|
+
loadHdr,
|
|
19583
19716
|
loadPLY,
|
|
19584
19717
|
loadPLYMobile,
|
|
19585
19718
|
loadSOG,
|