three-blocks-benchmark 0.4.0 → 0.5.0-alpha.384.g6baf5c5aba0f
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/CHANGELOG.md +63 -0
- package/README.md +3 -3
- package/browser/harness.js +7 -10
- package/lib/run.mjs +32 -4
- package/package.json +7 -3
- package/vendor/README.md +45 -0
- package/vendor/three-dev/build/three.core.js +60911 -0
- package/vendor/three-dev/build/three.tsl.js +672 -0
- package/vendor/three-dev/build/three.webgpu.js +90737 -0
- package/vendor/three-gs/loaders/GaussianSplatPLYLoader.js +386 -0
- package/vendor/three-gs/loaders/PLYLoader.js +968 -0
- package/vendor/three-gs/objects/GaussianSplat.js +859 -0
- package/vendor/three-gs/utils/GaussianSplatUtils.js +136 -125
- package/vendor/three-gs/README.md +0 -29
- package/vendor/three-gs/objects/GaussianSplatMesh.js +0 -474
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,68 @@
|
|
|
1
1
|
# three-blocks-benchmark
|
|
2
2
|
|
|
3
|
+
## 0.5.0-alpha.384.g6baf5c5aba0f
|
|
4
|
+
|
|
5
|
+
- Website: Example previews and precompiled shaders now match the current release.
|
|
6
|
+
|
|
7
|
+
- Library: Large PLY splat files now load through bundled workers.
|
|
8
|
+
|
|
9
|
+
- Devtools: Shader checks bound browser startup and shutdown before the next verification.
|
|
10
|
+
|
|
11
|
+
- Library: Baked Motion automatically prefers HEVC and falls back to AVC on every device.
|
|
12
|
+
|
|
13
|
+
- Library: Baked Motion can author narrower depth tracks to reduce package downloads.
|
|
14
|
+
|
|
15
|
+
- Library: Baked Motion bounds tilt warp reprojection so a starved blend goes stale, not stretched.
|
|
16
|
+
|
|
17
|
+
- Packages: Gaussian benchmarks add the three.js GaussianSplat runtime on its matching dev build.
|
|
18
|
+
|
|
19
|
+
- Library: Gaussian splats keep equal-depth ordering stable and avoid duplicate tile staging.
|
|
20
|
+
|
|
21
|
+
- Library: HMR replaces outgoing shader registrations without reporting false conflicts.
|
|
22
|
+
|
|
23
|
+
- Starter: New projects install the current Three Blocks and Devtools releases.
|
|
24
|
+
|
|
25
|
+
- Tools: Exact-count splats no longer drop small mesh objects with dense triangulation.
|
|
26
|
+
|
|
27
|
+
- Library: WaterVolume keeps hydrostatic density stable at high particle counts.
|
|
28
|
+
|
|
29
|
+
- Library: Sphere rasterization ignores inconsistent overflow readbacks instead of rebuilding.
|
|
30
|
+
|
|
31
|
+
- Website: The water surface demo starts at 500K particles, caps at 1M, and opens wider.
|
|
32
|
+
|
|
33
|
+
- Website: Water demos add larger tiers and a tunable floorless monochrome PBR particle view.
|
|
34
|
+
|
|
35
|
+
- Website: Example recording mode hides every interface except the rendered canvas.
|
|
36
|
+
|
|
37
|
+
- Website: The body-tracking demo now shows the whole live SDF volume instead of one slice.
|
|
38
|
+
|
|
39
|
+
- Library: SDFFieldNodes provides reusable distance, normal, shadow, and occlusion nodes.
|
|
40
|
+
|
|
41
|
+
- Website: Login, setup, and tool stories now use polished, selectable terminals.
|
|
42
|
+
|
|
43
|
+
- Library: Baked Motion preserves atlas alpha, resolves paused seeks, and fits mobile budgets.
|
|
44
|
+
|
|
45
|
+
- Library: Baked Motion tilt packages can ship a coarse all-view atlas for undecoded corners.
|
|
46
|
+
|
|
47
|
+
- Library: Baked Motion and Gaussian splat types now match their supported runtime contracts.
|
|
48
|
+
|
|
49
|
+
- Library: Baked Motion fuses each atlas page into one RGBA texture, halving its GPU memory.
|
|
50
|
+
|
|
51
|
+
- Tools: Baked Motion writes one package format; timelines and camera grids no longer differ.
|
|
52
|
+
|
|
53
|
+
- Tools: Baked Motion can now publish verified HEVC renditions alongside H.264.
|
|
54
|
+
|
|
55
|
+
- Tools: Blender reports consistent hub and Mesh to Splat versions in every install mode.
|
|
56
|
+
|
|
57
|
+
- Website: The launch film now opens on its title and keeps every proof to one fast minute.
|
|
58
|
+
|
|
59
|
+
- Library: Water accepts a shared interaction world, so moving bodies can push it.
|
|
60
|
+
|
|
61
|
+
- Packages: Indirect batching and its dependent examples are no longer included.
|
|
62
|
+
|
|
63
|
+
- Packages: Built from `6baf5c5aba0f`.
|
|
64
|
+
|
|
65
|
+
|
|
3
66
|
## 0.4.0
|
|
4
67
|
|
|
5
68
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# three-blocks-benchmark
|
|
2
2
|
|
|
3
|
-
Reproducible browser benchmarks for Three Blocks, the
|
|
4
|
-
|
|
5
|
-
GaussianSplats3D, and Babylon.js.
|
|
3
|
+
Reproducible browser benchmarks for Three Blocks, the three.js `GaussianSplat`
|
|
4
|
+
addon ([merged into `dev`][pr], vendored with the `dev` build it needs — see
|
|
5
|
+
`vendor/README.md`), Spark, SuperSplat, GaussianSplats3D, and Babylon.js.
|
|
6
6
|
|
|
7
7
|
[pr]: https://github.com/mrdoob/three.js/pull/33950
|
|
8
8
|
The default `standard` suite uses fixed held-out cameras from Mip-NeRF 360
|
package/browser/harness.js
CHANGED
|
@@ -228,11 +228,10 @@ async function createThreeBlocks( bytes ) {
|
|
|
228
228
|
|
|
229
229
|
async function createThreeGS( bytes ) {
|
|
230
230
|
|
|
231
|
-
const [ THREE, {
|
|
231
|
+
const [ THREE, { GaussianSplatPLYLoader }, { GaussianSplat } ] = await Promise.all( [
|
|
232
232
|
import( 'three/webgpu' ),
|
|
233
|
-
import( 'three/
|
|
234
|
-
import( '../vendor/three-gs/objects/
|
|
235
|
-
import( '../vendor/three-gs/utils/GaussianSplatUtils.js' ),
|
|
233
|
+
import( '../vendor/three-gs/loaders/GaussianSplatPLYLoader.js' ),
|
|
234
|
+
import( '../vendor/three-gs/objects/GaussianSplat.js' ),
|
|
236
235
|
] );
|
|
237
236
|
const renderer = new THREE.WebGPURenderer( {
|
|
238
237
|
canvas,
|
|
@@ -254,12 +253,10 @@ async function createThreeGS( bytes ) {
|
|
|
254
253
|
const camera = new THREE.PerspectiveCamera( benchmarkViewport.fov, benchmarkViewport.width / benchmarkViewport.height, 0.01, 100 );
|
|
255
254
|
setThreeCamera( camera, benchmarkPose );
|
|
256
255
|
|
|
257
|
-
// The
|
|
258
|
-
//
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
const splatGeometry = splatUtils.createGaussianSplatGeometryFromPLYGeometry( loader.parse( bytes ) );
|
|
262
|
-
const splats = new GaussianSplatMesh( splatGeometry );
|
|
256
|
+
// The merged addon ships its own splat PLY loader, which detects the file's spherical
|
|
257
|
+
// harmonics degree from the header, so the benchmark loads it exactly that way.
|
|
258
|
+
const splatGeometry = new GaussianSplatPLYLoader().parse( bytes );
|
|
259
|
+
const splats = new GaussianSplat( splatGeometry );
|
|
263
260
|
// The dataset PLY is in source (COLMAP-style Y-down) space; apply the suite's shared Rx180
|
|
264
261
|
// model transform, as the other runtimes do.
|
|
265
262
|
splats.quaternion.set( 1, 0, 0, 0 );
|
package/lib/run.mjs
CHANGED
|
@@ -36,6 +36,11 @@ const superSplatRuntime = path.resolve(
|
|
|
36
36
|
path.dirname( fileURLToPath( import.meta.resolve( '@playcanvas/supersplat-viewer' ) ) ),
|
|
37
37
|
'../public/index.js',
|
|
38
38
|
);
|
|
39
|
+
// The Gaussian splat addon merged into three.js `dev` after r185 and ships in no npm
|
|
40
|
+
// release yet, so its lane runs against the vendored `dev` build it was merged into. Every
|
|
41
|
+
// other runtime keeps the installed `three` release.
|
|
42
|
+
const THREE_DEV_COMMIT = '00ea66ecb4b253c78e65b5f5a558af4696ba88a7';
|
|
43
|
+
const threeDevBuild = path.join( packageRoot, 'vendor/three-dev/build' );
|
|
39
44
|
const ownManifest = JSON.parse( await fs.readFile( path.join( packageRoot, 'package.json' ), 'utf8' ) );
|
|
40
45
|
const threeBlocksManifest = JSON.parse( await fs.readFile( path.join( threeBlocksRoot, 'package.json' ), 'utf8' ) );
|
|
41
46
|
|
|
@@ -50,10 +55,10 @@ const RENDERERS = [
|
|
|
50
55
|
{
|
|
51
56
|
id: 'three-gs',
|
|
52
57
|
label: 'three.js splats',
|
|
53
|
-
version: '
|
|
58
|
+
version: 'dev',
|
|
54
59
|
backend: 'WebGPU',
|
|
55
|
-
source: 'https://github.com/mrdoob/three.js/
|
|
56
|
-
commit:
|
|
60
|
+
source: 'https://github.com/mrdoob/three.js/blob/dev/examples/jsm/objects/GaussianSplat.js',
|
|
61
|
+
commit: THREE_DEV_COMMIT,
|
|
57
62
|
},
|
|
58
63
|
{
|
|
59
64
|
id: 'spark',
|
|
@@ -262,9 +267,13 @@ async function serveDirectory( root, externalFiles = new Map() ) {
|
|
|
262
267
|
|
|
263
268
|
async function runPage( browser, baseUrl, { renderer, suite, item, warmup, frames } ) {
|
|
264
269
|
|
|
270
|
+
const viewport = { width: item.width ?? VIEWPORT.width, height: item.height ?? VIEWPORT.height };
|
|
265
271
|
const context = await browser.newContext( {
|
|
266
|
-
viewport
|
|
272
|
+
viewport,
|
|
267
273
|
deviceScaleFactor: item.dpr ?? VIEWPORT.dpr,
|
|
274
|
+
// Presentation capture only: one .webm per page run at the exact viewport,
|
|
275
|
+
// off by default so published metrics never carry the recorder's overhead.
|
|
276
|
+
...( process.env.TB_RECORD_VIDEO ? { recordVideo: { dir: process.env.TB_RECORD_VIDEO, size: viewport } } : {} ),
|
|
268
277
|
} );
|
|
269
278
|
const page = await context.newPage();
|
|
270
279
|
const diagnostics = [];
|
|
@@ -315,12 +324,24 @@ async function runPage( browser, baseUrl, { renderer, suite, item, warmup, frame
|
|
|
315
324
|
|
|
316
325
|
} finally {
|
|
317
326
|
|
|
327
|
+
const video = process.env.TB_RECORD_VIDEO ? page.video() : null;
|
|
318
328
|
await context.close();
|
|
329
|
+
if ( video ) {
|
|
330
|
+
|
|
331
|
+
// The recorder finalizes on close; rename from playwright's random hash
|
|
332
|
+
// to the run order so a capture maps back to its stdout line.
|
|
333
|
+
const sequence = String( recordedRuns ++ ).padStart( 3, '0' );
|
|
334
|
+
await video.saveAs( path.join( process.env.TB_RECORD_VIDEO, `${sequence}-${item.id}-${renderer}.webm` ) );
|
|
335
|
+
await video.delete();
|
|
336
|
+
|
|
337
|
+
}
|
|
319
338
|
|
|
320
339
|
}
|
|
321
340
|
|
|
322
341
|
}
|
|
323
342
|
|
|
343
|
+
let recordedRuns = 0;
|
|
344
|
+
|
|
324
345
|
function gpuSummary( systemInfo ) {
|
|
325
346
|
|
|
326
347
|
const gpu = systemInfo.gpu ?? {};
|
|
@@ -430,6 +451,13 @@ export async function runBenchmark( options ) {
|
|
|
430
451
|
resolve: {
|
|
431
452
|
alias: [
|
|
432
453
|
{ find: 'supersplat-viewer-runtime', replacement: superSplatRuntime },
|
|
454
|
+
// The three.js addon lane resolves every `three` specifier to the vendored
|
|
455
|
+
// `dev` build, exactly as the addon's own example importmap does.
|
|
456
|
+
...( renderer === 'three-gs' ? [
|
|
457
|
+
{ find: 'three/tsl', replacement: path.join( threeDevBuild, 'three.tsl.js' ) },
|
|
458
|
+
{ find: 'three/webgpu', replacement: path.join( threeDevBuild, 'three.webgpu.js' ) },
|
|
459
|
+
{ find: 'three', replacement: path.join( threeDevBuild, 'three.webgpu.js' ) },
|
|
460
|
+
] : [] ),
|
|
433
461
|
// Both loaders spell their worker as `new URL( './<name>.js', import.meta.url )` so
|
|
434
462
|
// bundlers emit the entry. The published chunks sit at the dist root, where those
|
|
435
463
|
// paths do not exist; point them at the real worker modules.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "three-blocks-benchmark",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Reproducible Gaussian splat browser benchmarks for Three Blocks, the three.js
|
|
3
|
+
"version": "0.5.0-alpha.384.g6baf5c5aba0f",
|
|
4
|
+
"description": "Reproducible Gaussian splat browser benchmarks for Three Blocks, the three.js GaussianSplat addon, Spark, SuperSplat, GaussianSplats3D, and Babylon.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"three",
|
|
7
7
|
"threejs",
|
|
@@ -52,7 +52,11 @@
|
|
|
52
52
|
"playwright": "1.61.1",
|
|
53
53
|
"pngjs": "7.0.0",
|
|
54
54
|
"three": "0.185.1",
|
|
55
|
-
"three-blocks": "0.
|
|
55
|
+
"three-blocks": "0.11.0-alpha.384.g6baf5c5aba0f",
|
|
56
56
|
"vite": "8.1.3"
|
|
57
|
+
},
|
|
58
|
+
"threeBlocks": {
|
|
59
|
+
"channel": "alpha",
|
|
60
|
+
"site": "https://preprod.threejs-blocks.com"
|
|
57
61
|
}
|
|
58
62
|
}
|
package/vendor/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# three.js Gaussian splat addon (`dev`)
|
|
2
|
+
|
|
3
|
+
Verbatim copies of the merged Gaussian splat addon from mrdoob/three.js
|
|
4
|
+
([PR #33950][pr], merged 2026-08-08) and of the `three` build it runs against,
|
|
5
|
+
both pinned to commit `00ea66ecb4b253c78e65b5f5a558af4696ba88a7`.
|
|
6
|
+
|
|
7
|
+
The addon uses TSL nodes that landed after r185 (`unpackUnorm4x8`), so it runs
|
|
8
|
+
on no published `three` release. Until r186 ships, the benchmark vendors the
|
|
9
|
+
`dev` build alongside the addon and resolves every `three` specifier in the
|
|
10
|
+
`three-gs` bundle to it — the same mapping the addon's own example importmap
|
|
11
|
+
uses. Every other runtime keeps the installed `three` release.
|
|
12
|
+
|
|
13
|
+
| File | SHA-256 |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| `three-gs/objects/GaussianSplat.js` | `c239cde1abe239307c7dcc919d2a94c10e79a9393ffc3ba3e57dd8da53c367e6` |
|
|
16
|
+
| `three-gs/gpgpu/CountingSort.js` | `e9e90b6940a4da923534c3f249e8e7bd2c7603f8b432c54c62ecdc6db4be47e3` |
|
|
17
|
+
| `three-gs/utils/GaussianSplatUtils.js` | `4b9b010149b3e1a7673de37638365e937e005a03ba706e4cd81301b717d30f54` |
|
|
18
|
+
| `three-gs/loaders/GaussianSplatPLYLoader.js` | `072def58e1c9d081bb5b3ce2641a652d1075f3a45d778874a38a765cfcd1dd60` |
|
|
19
|
+
| `three-gs/loaders/PLYLoader.js` | `67b8c1015209b89081a92fdd69dc9df4a61284c3e9f8bb5380e441e4c64e5111` |
|
|
20
|
+
| `three-dev/build/three.core.js` | `262ac37bc647e6e0393bb3ff1be9a610971ac6c9e49643a4a5ee914947cd5d88` |
|
|
21
|
+
| `three-dev/build/three.webgpu.js` | `e906db5b44edcdf547eb3d7705e3a527ac851a7fad04db04c930066cb760fced` |
|
|
22
|
+
| `three-dev/build/three.tsl.js` | `24728c07fcdb9a57afb5a41c9bc05db2052ebd528c945e7e5fe0963e48eb7937` |
|
|
23
|
+
|
|
24
|
+
Refresh with:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
sha=00ea66ecb4b253c78e65b5f5a558af4696ba88a7
|
|
28
|
+
for f in objects/GaussianSplat.js gpgpu/CountingSort.js utils/GaussianSplatUtils.js \
|
|
29
|
+
loaders/GaussianSplatPLYLoader.js loaders/PLYLoader.js; do
|
|
30
|
+
curl -sSfL "https://raw.githubusercontent.com/mrdoob/three.js/$sha/examples/jsm/$f" -o "three-gs/$f"
|
|
31
|
+
done
|
|
32
|
+
for f in three.core.js three.webgpu.js three.tsl.js; do
|
|
33
|
+
curl -sSfL "https://raw.githubusercontent.com/mrdoob/three.js/$sha/build/$f" -o "three-dev/build/$f"
|
|
34
|
+
done
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The `three-gs` layout mirrors `examples/jsm/` so the files stay byte-identical
|
|
38
|
+
to upstream (`GaussianSplat.js` imports `../gpgpu/CountingSort.js`, the splat
|
|
39
|
+
PLY loader imports `./PLYLoader.js`). Drop `three-dev/` and alias the `three`
|
|
40
|
+
specifiers back to the installed release once r186 publishes the addon.
|
|
41
|
+
|
|
42
|
+
[pr]: https://github.com/mrdoob/three.js/pull/33950
|
|
43
|
+
|
|
44
|
+
Licensed under the MIT License, Copyright © 2010-2026 three.js authors:
|
|
45
|
+
<https://github.com/mrdoob/three.js/blob/dev/LICENSE>
|