three-blocks-benchmark 0.2.1 → 0.3.0-alpha.320.g7e6e67cd7214
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 +15 -0
- package/README.md +2 -1
- package/browser/harness.js +104 -1
- package/lib/run.mjs +9 -0
- package/package.json +9 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# three-blocks-benchmark
|
|
2
2
|
|
|
3
|
+
## 0.3.0-alpha.320.g7e6e67cd7214
|
|
4
|
+
|
|
5
|
+
- Website: Stripe billing events now reach the production webhook reliably.
|
|
6
|
+
|
|
7
|
+
- Devtools: Loading no longer spins the status chip or terminal progress indicator.
|
|
8
|
+
|
|
9
|
+
- Devtools: Vite asset config and inspection handle HDR files and report exact GPU memory.
|
|
10
|
+
|
|
11
|
+
- Packages: Text projects hydrate precompiled shaders and stay crisp across display resolutions.
|
|
12
|
+
|
|
13
|
+
- Packages: Gaussian benchmarks now compare Babylon.js and fully revealed GaussianSplats3D scenes.
|
|
14
|
+
|
|
15
|
+
- Packages: Built from `7e6e67cd7214`.
|
|
16
|
+
|
|
17
|
+
|
|
3
18
|
## 0.2.1
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# three-blocks-benchmark
|
|
2
2
|
|
|
3
|
-
Reproducible browser benchmarks for Three Blocks, Spark,
|
|
3
|
+
Reproducible browser benchmarks for Three Blocks, Spark, SuperSplat,
|
|
4
|
+
GaussianSplats3D, and Babylon.js.
|
|
4
5
|
The default `standard` suite uses fixed held-out cameras from Mip-NeRF 360
|
|
5
6
|
Bonsai and a pinned NerfBaselines Graphdeco 30K artifact. The synthetic
|
|
6
7
|
`micro` suite is performance-only.
|
package/browser/harness.js
CHANGED
|
@@ -317,6 +317,10 @@ async function createGS3D( bytes ) {
|
|
|
317
317
|
sharedMemoryForWorkers,
|
|
318
318
|
sphericalHarmonicsDegree: 3,
|
|
319
319
|
logLevel: 0,
|
|
320
|
+
// Faithful-viewing configuration: render the whole checkpoint immediately instead of
|
|
321
|
+
// the default progressive reveal animation, whose expanding visible region leaves
|
|
322
|
+
// distant splats black until enough update() calls have elapsed.
|
|
323
|
+
sceneRevealMode: GaussianSplats3D.SceneRevealMode.Instant,
|
|
320
324
|
} );
|
|
321
325
|
// The dataset PLY is in source (COLMAP-style Y-down) space; the suite's other meshes
|
|
322
326
|
// carry an Rx180 model transform, so give GS3D the identical scene rotation.
|
|
@@ -369,6 +373,104 @@ async function createGS3D( bytes ) {
|
|
|
369
373
|
|
|
370
374
|
}
|
|
371
375
|
|
|
376
|
+
async function createBabylon( bytes ) {
|
|
377
|
+
|
|
378
|
+
const [ { Engine }, { Scene }, { TargetCamera }, { Matrix, Quaternion, Vector3 }, { Color4 }, { ImportMeshAsync } ] = await Promise.all( [
|
|
379
|
+
import( '@babylonjs/core/Engines/engine.js' ),
|
|
380
|
+
import( '@babylonjs/core/scene.js' ),
|
|
381
|
+
import( '@babylonjs/core/Cameras/targetCamera.js' ),
|
|
382
|
+
import( '@babylonjs/core/Maths/math.vector.js' ),
|
|
383
|
+
import( '@babylonjs/core/Maths/math.color.js' ),
|
|
384
|
+
import( '@babylonjs/core/Loading/sceneLoader.js' ),
|
|
385
|
+
// Registers the SPLAT/PLY scene-loader plugin (side effect).
|
|
386
|
+
import( '@babylonjs/loaders/SPLAT/splatFileLoader.js' ),
|
|
387
|
+
] );
|
|
388
|
+
const engine = new Engine( canvas, false, {
|
|
389
|
+
antialias: false,
|
|
390
|
+
alpha: false,
|
|
391
|
+
preserveDrawingBuffer: true,
|
|
392
|
+
powerPreference: 'high-performance',
|
|
393
|
+
} );
|
|
394
|
+
engine.setSize( benchmarkViewport.width, benchmarkViewport.height );
|
|
395
|
+
const scene3d = new Scene( engine );
|
|
396
|
+
scene3d.useRightHandedSystem = true;
|
|
397
|
+
scene3d.clearColor = suiteId === 'standard'
|
|
398
|
+
? new Color4( 0, 0, 0, 1 )
|
|
399
|
+
: new Color4( 7 / 255, 10 / 255, 15 / 255, 1 );
|
|
400
|
+
const camera = new TargetCamera( 'camera', Vector3.Zero(), scene3d );
|
|
401
|
+
camera.minZ = 0.01;
|
|
402
|
+
camera.maxZ = 100;
|
|
403
|
+
const setBabylonCamera = pose => {
|
|
404
|
+
|
|
405
|
+
camera.fov = pose.fov * Math.PI / 180;
|
|
406
|
+
if ( pose.matrix ) {
|
|
407
|
+
|
|
408
|
+
// Right-handed Babylon cameras share the three.js convention (forward -Z, up +Y),
|
|
409
|
+
// so the dataset camera-to-world matrix transfers directly. Babylon has no
|
|
410
|
+
// principal-point offset API; views render with a centered pinhole projection.
|
|
411
|
+
camera.updateUpVectorFromRotation = true;
|
|
412
|
+
if ( ! camera.rotationQuaternion ) camera.rotationQuaternion = new Quaternion();
|
|
413
|
+
Quaternion.FromRotationMatrixToRef(
|
|
414
|
+
Matrix.FromArray( pose.matrix ).getRotationMatrix(),
|
|
415
|
+
camera.rotationQuaternion,
|
|
416
|
+
);
|
|
417
|
+
camera.position.set( pose.matrix[ 12 ], pose.matrix[ 13 ], pose.matrix[ 14 ] );
|
|
418
|
+
|
|
419
|
+
} else {
|
|
420
|
+
|
|
421
|
+
camera.position.set( ...pose.position );
|
|
422
|
+
camera.setTarget( new Vector3( ...pose.target ) );
|
|
423
|
+
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
};
|
|
427
|
+
setBabylonCamera( benchmarkPose );
|
|
428
|
+
|
|
429
|
+
const result = await ImportMeshAsync( new File( [ bytes ], benchmarkFileName ), scene3d );
|
|
430
|
+
const splats = result.meshes[ 0 ];
|
|
431
|
+
// The dataset PLY is in source (COLMAP-style Y-down) space. The loader ships a Y-mirror
|
|
432
|
+
// (scaling.y = -1) for Babylon's default left-handed world; in this right-handed scene
|
|
433
|
+
// the suite's shared model transform is the proper rotation Rx180, so reset the mirror.
|
|
434
|
+
splats.scaling.set( 1, 1, 1 );
|
|
435
|
+
splats.rotationQuaternion = new Quaternion( 1, 0, 0, 0 );
|
|
436
|
+
|
|
437
|
+
const gl = canvas.getContext( 'webgl2' );
|
|
438
|
+
const fencePixel = new Uint8Array( 4 );
|
|
439
|
+
const render = async pose => {
|
|
440
|
+
|
|
441
|
+
setBabylonCamera( pose );
|
|
442
|
+
scene3d.render();
|
|
443
|
+
// Babylon depth-sorts on a worker outside the frame (like GS3D and SuperSplat); the
|
|
444
|
+
// timed frame is the raster. The 1x1 readback forces true GPU completion.
|
|
445
|
+
gl.readPixels( 0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, fencePixel );
|
|
446
|
+
|
|
447
|
+
};
|
|
448
|
+
// Load ends at the first frame whose worker sort has been applied, so the first
|
|
449
|
+
// counted frame really displays the scene.
|
|
450
|
+
while ( ! splats.isReady( true ) ) {
|
|
451
|
+
|
|
452
|
+
scene3d.render();
|
|
453
|
+
await new Promise( resolve => requestAnimationFrame( resolve ) );
|
|
454
|
+
|
|
455
|
+
}
|
|
456
|
+
await render( benchmarkPose );
|
|
457
|
+
return {
|
|
458
|
+
backend: 'WebGL2',
|
|
459
|
+
render,
|
|
460
|
+
async diagnostics() {
|
|
461
|
+
|
|
462
|
+
return {
|
|
463
|
+
reportedGpuBytes: null,
|
|
464
|
+
reportedGpuBytesScope: null,
|
|
465
|
+
shDegree: splats.shDegree,
|
|
466
|
+
webgl: webGLInfo( gl ),
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
},
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
}
|
|
473
|
+
|
|
372
474
|
function superSplatSettings() {
|
|
373
475
|
|
|
374
476
|
const initialFov = suiteId === 'standard' ? benchmarkPose.fov : QUALITY_CAMERA.fov;
|
|
@@ -534,7 +636,7 @@ async function measureBrowserMemory() {
|
|
|
534
636
|
async function run() {
|
|
535
637
|
|
|
536
638
|
if ( ! [ 'standard', 'micro' ].includes( suiteId ) ) throw new Error( `Unknown suite: ${suiteId}` );
|
|
537
|
-
if ( ! [ 'three-blocks', 'spark', 'supersplat', 'gs3d' ].includes( rendererId ) ) {
|
|
639
|
+
if ( ! [ 'three-blocks', 'spark', 'supersplat', 'gs3d', 'babylon' ].includes( rendererId ) ) {
|
|
538
640
|
|
|
539
641
|
throw new Error( `Unknown renderer: ${rendererId}` );
|
|
540
642
|
|
|
@@ -576,6 +678,7 @@ async function run() {
|
|
|
576
678
|
if ( rendererId === 'spark' ) adapter = await createSpark( bytes );
|
|
577
679
|
if ( rendererId === 'supersplat' ) adapter = await createSuperSplat( bytes, 'webgpu' );
|
|
578
680
|
if ( rendererId === 'gs3d' ) adapter = await createGS3D( bytes );
|
|
681
|
+
if ( rendererId === 'babylon' ) adapter = await createBabylon( bytes );
|
|
579
682
|
const loadMilliseconds = performance.now();
|
|
580
683
|
const measurementPose = frame => suiteId === 'micro'
|
|
581
684
|
? cameraPose( frame )
|
package/lib/run.mjs
CHANGED
|
@@ -72,6 +72,15 @@ const RENDERERS = [
|
|
|
72
72
|
backend: 'WebGL2',
|
|
73
73
|
source: 'https://github.com/mkkellogg/GaussianSplats3D',
|
|
74
74
|
},
|
|
75
|
+
{
|
|
76
|
+
id: 'babylon',
|
|
77
|
+
label: 'Babylon.js',
|
|
78
|
+
version: '9.19.1',
|
|
79
|
+
backend: 'WebGL2',
|
|
80
|
+
source: 'https://github.com/BabylonJS/Babylon.js',
|
|
81
|
+
commit: 'c37eae3db20d04335d7cf4b2e6e4491070e2848d',
|
|
82
|
+
integrity: 'sha512-Uu2VchxBGBEEUh73YoobP1U5aNGO7AH4nZB2hs1azxd9fWxj5C1obIVs5wcA05fppAsYPJiNy/+HfaaPdoqbbQ==',
|
|
83
|
+
},
|
|
75
84
|
];
|
|
76
85
|
|
|
77
86
|
function percentile( sorted, fraction ) {
|
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, Spark, and
|
|
3
|
+
"version": "0.3.0-alpha.320.g7e6e67cd7214",
|
|
4
|
+
"description": "Reproducible Gaussian splat browser benchmarks for Three Blocks, Spark, SuperSplat, GaussianSplats3D, and Babylon.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"three",
|
|
7
7
|
"threejs",
|
|
@@ -44,12 +44,18 @@
|
|
|
44
44
|
"prepack": "node --test tests/run.test.mjs"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
+
"@babylonjs/core": "9.19.1",
|
|
48
|
+
"@babylonjs/loaders": "9.19.1",
|
|
47
49
|
"@playcanvas/supersplat-viewer": "1.28.0",
|
|
48
50
|
"@sparkjsdev/spark": "2.1.0",
|
|
49
51
|
"playwright": "1.61.1",
|
|
50
52
|
"pngjs": "7.0.0",
|
|
51
53
|
"three": "0.185.1",
|
|
52
|
-
"three-blocks": "0.
|
|
54
|
+
"three-blocks": "0.6.0-alpha.320.g7e6e67cd7214",
|
|
53
55
|
"vite": "8.1.3"
|
|
56
|
+
},
|
|
57
|
+
"threeBlocks": {
|
|
58
|
+
"channel": "alpha",
|
|
59
|
+
"site": "https://preprod.threejs-blocks.com"
|
|
54
60
|
}
|
|
55
61
|
}
|