@d5techs/3dgs-lib 1.4.54 → 1.4.56
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 +64 -10
- package/dist/3dgs-lib.cjs.map +1 -1
- package/dist/3dgs-lib.js +64 -10
- package/dist/3dgs-lib.js.map +1 -1
- package/dist/App.d.ts +1 -0
- package/dist/core/SkyboxRenderer.d.ts +3 -1
- package/package.json +1 -1
package/dist/3dgs-lib.cjs
CHANGED
|
@@ -2198,7 +2198,7 @@ function float32ToFloat16(val) {
|
|
|
2198
2198
|
const CUBE_WGSL = (
|
|
2199
2199
|
/* wgsl */
|
|
2200
2200
|
`
|
|
2201
|
-
struct Uniforms { col0: vec4<f32>, col1: vec4<f32>, col2: vec4<f32> };
|
|
2201
|
+
struct Uniforms { col0: vec4<f32>, col1: vec4<f32>, col2: vec4<f32>, extra: vec4<f32> };
|
|
2202
2202
|
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
2203
2203
|
@group(0) @binding(1) var cubeSampler: sampler;
|
|
2204
2204
|
@group(0) @binding(2) var cubeTexture: texture_cube<f32>;
|
|
@@ -2217,12 +2217,17 @@ struct V { @builtin(position) pos: vec4<f32>, @location(0) dir: vec3<f32> };
|
|
|
2217
2217
|
const EQUIRECT_WGSL = (
|
|
2218
2218
|
/* wgsl */
|
|
2219
2219
|
`
|
|
2220
|
-
struct Uniforms { col0: vec4<f32>, col1: vec4<f32>, col2: vec4<f32> };
|
|
2220
|
+
struct Uniforms { col0: vec4<f32>, col1: vec4<f32>, col2: vec4<f32>, extra: vec4<f32> };
|
|
2221
2221
|
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
2222
2222
|
@group(0) @binding(1) var envSampler: sampler;
|
|
2223
2223
|
@group(0) @binding(2) var envTexture: texture_2d<f32>;
|
|
2224
2224
|
struct V { @builtin(position) pos: vec4<f32>, @location(0) dir: vec3<f32> };
|
|
2225
2225
|
const PI: f32 = 3.14159265358979;
|
|
2226
|
+
|
|
2227
|
+
fn dirToUv(d: vec3<f32>) -> vec2<f32> {
|
|
2228
|
+
return vec2(atan2(d.z, d.x) / (2.*PI) + .5, 1. - (asin(clamp(d.y,-1.,1.)) / PI + .5));
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2226
2231
|
@vertex fn vs(@builtin(vertex_index) vi: u32) -> V {
|
|
2227
2232
|
let ps = array<vec2<f32>,3>(vec2(-1.,-1.),vec2(3.,-1.),vec2(-1.,3.));
|
|
2228
2233
|
var o: V; let p = ps[vi]; o.pos = vec4(p, 0., 1.);
|
|
@@ -2230,10 +2235,46 @@ const PI: f32 = 3.14159265358979;
|
|
|
2230
2235
|
o.dir = vec3(dot(u.col0.xyz,e), dot(u.col1.xyz,e), dot(u.col2.xyz,e));
|
|
2231
2236
|
return o;
|
|
2232
2237
|
}
|
|
2238
|
+
|
|
2233
2239
|
@fragment fn fs(i: V) -> @location(0) vec4<f32> {
|
|
2234
2240
|
let d = normalize(i.dir);
|
|
2235
|
-
let
|
|
2236
|
-
let
|
|
2241
|
+
let camY = u.extra.x;
|
|
2242
|
+
let sphereR = u.extra.y;
|
|
2243
|
+
|
|
2244
|
+
// --- sky UV (always computed) ---
|
|
2245
|
+
let skyUv = dirToUv(d);
|
|
2246
|
+
|
|
2247
|
+
// --- ground projection (always computed for uniform control flow) ---
|
|
2248
|
+
// Ray from camera (0, camY, 0) in direction d hits plane y=0 at t
|
|
2249
|
+
let dyClamped = min(d.y, -0.0001);
|
|
2250
|
+
let t = -camY / dyClamped;
|
|
2251
|
+
let hitX = t * d.x;
|
|
2252
|
+
let hitZ = t * d.z;
|
|
2253
|
+
let hitDist = sqrt(hitX * hitX + hitZ * hitZ);
|
|
2254
|
+
|
|
2255
|
+
// Project the ground hit point back onto a sphere of radius R
|
|
2256
|
+
// centered at the camera projection on y=0 (i.e. center = origin).
|
|
2257
|
+
// For points beyond R, fade to horizon sampling.
|
|
2258
|
+
let ratio = min(hitDist, sphereR) / max(hitDist, 0.001);
|
|
2259
|
+
let pX = hitX * ratio;
|
|
2260
|
+
let pZ = hitZ * ratio;
|
|
2261
|
+
let pY = -sqrt(max(sphereR * sphereR - pX * pX - pZ * pZ, 0.0));
|
|
2262
|
+
let groundDir = normalize(vec3(pX, pY, pZ));
|
|
2263
|
+
let groundUv = dirToUv(groundDir);
|
|
2264
|
+
|
|
2265
|
+
// --- sample both (unconditional = uniform control flow) ---
|
|
2266
|
+
let skyColor = textureSample(envTexture, envSampler, skyUv).rgb;
|
|
2267
|
+
let groundColor = textureSample(envTexture, envSampler, groundUv).rgb;
|
|
2268
|
+
|
|
2269
|
+
// Blend: smooth transition near horizon
|
|
2270
|
+
// step(0.01, camY) disables ground projection when camera is at/below ground
|
|
2271
|
+
let groundFactor = smoothstep(0.01, -0.15, d.y) * step(0.01, camY);
|
|
2272
|
+
// Fade out ground color at the sphere edge to avoid hard seam
|
|
2273
|
+
let edgeFade = 1.0 - smoothstep(sphereR * 0.7, sphereR * 0.99, hitDist);
|
|
2274
|
+
let finalBlend = groundFactor * edgeFade;
|
|
2275
|
+
let c = mix(skyColor, groundColor, finalBlend);
|
|
2276
|
+
|
|
2277
|
+
// Reinhard tone mapping + gamma
|
|
2237
2278
|
let mapped = c / (c + vec3(1.));
|
|
2238
2279
|
let gamma = pow(mapped, vec3(1./2.2));
|
|
2239
2280
|
return vec4(gamma, 1.);
|
|
@@ -2244,7 +2285,7 @@ class SkyboxRenderer {
|
|
|
2244
2285
|
__publicField(this, "device");
|
|
2245
2286
|
__publicField(this, "uniformBuffer");
|
|
2246
2287
|
__publicField(this, "sampler");
|
|
2247
|
-
__publicField(this, "uniformData", new Float32Array(
|
|
2288
|
+
__publicField(this, "uniformData", new Float32Array(16));
|
|
2248
2289
|
__publicField(this, "cubePipeline");
|
|
2249
2290
|
__publicField(this, "cubeBindGroupLayout");
|
|
2250
2291
|
__publicField(this, "equirectPipeline");
|
|
@@ -2253,6 +2294,8 @@ class SkyboxRenderer {
|
|
|
2253
2294
|
__publicField(this, "bindGroup", null);
|
|
2254
2295
|
__publicField(this, "frameReady", false);
|
|
2255
2296
|
__publicField(this, "mode", "none");
|
|
2297
|
+
/** Ground projection sphere radius (world units). Larger = ground extends further, flatter. */
|
|
2298
|
+
__publicField(this, "groundRadius", 500);
|
|
2256
2299
|
this.device = device;
|
|
2257
2300
|
const depthStencil = {
|
|
2258
2301
|
format: depthFormat,
|
|
@@ -2261,7 +2304,7 @@ class SkyboxRenderer {
|
|
|
2261
2304
|
};
|
|
2262
2305
|
this.cubeBindGroupLayout = device.createBindGroupLayout({
|
|
2263
2306
|
entries: [
|
|
2264
|
-
{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } },
|
|
2307
|
+
{ binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
|
|
2265
2308
|
{ binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } },
|
|
2266
2309
|
{ binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float", viewDimension: "cube" } }
|
|
2267
2310
|
]
|
|
@@ -2275,7 +2318,7 @@ class SkyboxRenderer {
|
|
|
2275
2318
|
});
|
|
2276
2319
|
this.equirectBindGroupLayout = device.createBindGroupLayout({
|
|
2277
2320
|
entries: [
|
|
2278
|
-
{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } },
|
|
2321
|
+
{ binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
|
|
2279
2322
|
{ binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } },
|
|
2280
2323
|
{ binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float", viewDimension: "2d" } }
|
|
2281
2324
|
]
|
|
@@ -2288,7 +2331,7 @@ class SkyboxRenderer {
|
|
|
2288
2331
|
depthStencil
|
|
2289
2332
|
});
|
|
2290
2333
|
this.uniformBuffer = device.createBuffer({
|
|
2291
|
-
size:
|
|
2334
|
+
size: 64,
|
|
2292
2335
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
2293
2336
|
});
|
|
2294
2337
|
this.sampler = device.createSampler({ magFilter: "linear", minFilter: "linear" });
|
|
@@ -2371,7 +2414,7 @@ class SkyboxRenderer {
|
|
|
2371
2414
|
this.mode = "equirect";
|
|
2372
2415
|
}
|
|
2373
2416
|
// ---- common ----
|
|
2374
|
-
prepareFrame(viewMatrix, projectionMatrix) {
|
|
2417
|
+
prepareFrame(viewMatrix, projectionMatrix, cameraPosition) {
|
|
2375
2418
|
if (!this.isActive) {
|
|
2376
2419
|
this.frameReady = false;
|
|
2377
2420
|
return;
|
|
@@ -2389,6 +2432,10 @@ class SkyboxRenderer {
|
|
|
2389
2432
|
ud[9] = viewMatrix[9];
|
|
2390
2433
|
ud[10] = viewMatrix[10];
|
|
2391
2434
|
ud[11] = 0;
|
|
2435
|
+
ud[12] = cameraPosition ? cameraPosition[1] : 0;
|
|
2436
|
+
ud[13] = this.groundRadius;
|
|
2437
|
+
ud[14] = 0;
|
|
2438
|
+
ud[15] = 0;
|
|
2392
2439
|
this.device.queue.writeBuffer(this.uniformBuffer, 0, ud);
|
|
2393
2440
|
this.frameReady = true;
|
|
2394
2441
|
}
|
|
@@ -19025,9 +19072,11 @@ class App {
|
|
|
19025
19072
|
this.updateAdaptivePerformance();
|
|
19026
19073
|
this.hotspotManager.updateBillboards();
|
|
19027
19074
|
if ((_a2 = this.skyboxRenderer) == null ? void 0 : _a2.isActive) {
|
|
19075
|
+
const cam = this.camera.position;
|
|
19028
19076
|
this.skyboxRenderer.prepareFrame(
|
|
19029
19077
|
this.camera.viewMatrix,
|
|
19030
|
-
this.camera.projectionMatrix
|
|
19078
|
+
this.camera.projectionMatrix,
|
|
19079
|
+
[cam[0], cam[1], cam[2]]
|
|
19031
19080
|
);
|
|
19032
19081
|
}
|
|
19033
19082
|
const pass = this.renderer.beginFrame();
|
|
@@ -19222,6 +19271,11 @@ class App {
|
|
|
19222
19271
|
}
|
|
19223
19272
|
await this.skyboxRenderer.loadEquirectangular(url);
|
|
19224
19273
|
}
|
|
19274
|
+
setHdrGroundRadius(radius) {
|
|
19275
|
+
if (this.skyboxRenderer) {
|
|
19276
|
+
this.skyboxRenderer.groundRadius = radius;
|
|
19277
|
+
}
|
|
19278
|
+
}
|
|
19225
19279
|
clearSkybox() {
|
|
19226
19280
|
var _a2;
|
|
19227
19281
|
(_a2 = this.skyboxRenderer) == null ? void 0 : _a2.clear();
|