Skip to content

Commit f6f4ade

Browse files
authored
Merge pull request #334 from mkkellogg/dev
Update version to 0.4.5
2 parents 2d80511 + ec8831c commit f6f4ade

21 files changed

+599
-272
lines changed

README.md

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,22 @@ When I started, web-based viewers were already available -- A WebGL-based viewer
2222
- WASM splat sort: Implemented in C++ using WASM SIMD instructions
2323
- Partially GPU accelerated splat sort: Uses transform feedback to pre-calculate splat distances
2424

25+
## Tips
26+
27+
- Progressively loaded `.ply` and `.splat` files will not have certain optimizations such as cache-optimized splat ordering applied to them. For optimial performance, convert these file types to `.ksplat` or load them non-progressively.
28+
- Converting your scenes to `.ksplat` will result in the fastest loading times since its format matches the internal format for splat data.
29+
- Scenes with large dimensions or high splat density will cause issues with the default settings. For those scenes, you can try a couple of things:
30+
- Set the viewer parameter `integerBasedSort` to `false` to force a slower, floating-point based splat sort.
31+
- Experiment with a larger value for viewer parameter `splatSortDistanceMapPrecision`, to adjust the precision for the distance map in the splat sort. Larger precision values will result in reduced performance, but often can alleviate visual artifacts that arise when the precision is too low.
32+
33+
2534
## Known issues
2635

2736
- Splat sort runs on the CPU – would be great to figure out a GPU-based approach
2837
- Artifacts are visible when you move or rotate too fast (due to CPU-based splat sort)
2938
- Sub-optimal performance on mobile devices
3039
- Custom `.ksplat` file format still needs work, especially around compression
31-
- The default, integer based splat sort does not work well for larger scenes. In that case a value of `false` for the `integerBasedSort` viewer parameter can force a slower, floating-point based sort
40+
- Scenes with very large dimensions will probably crash (often with an `Index out of bounds` error from the splat sort). Changing `splatSortDistanceMapPrecision` or `integerBasedSort` will probably not help in those cases.
3241

3342
## Limitations
3443

@@ -288,7 +297,7 @@ const viewer = new GaussianSplats3D.Viewer({
288297
'logLevel': GaussianSplats3D.LogLevel.None,
289298
'sphericalHarmonicsDegree': 0,
290299
`enableOptionalEffects`: false,
291-
`plyInMemoryCompressionLevel`: 2
300+
`inMemoryCompressionLevel`: 2
292301
`freeIntermediateSplatData`: false
293302
});
294303
viewer.addSplatScene('<path to .ply, .ksplat, or .splat file>')
@@ -317,19 +326,23 @@ Advanced `Viewer` parameters
317326
| `enableSIMDInSort` | Enable the usage of SIMD WebAssembly instructions for the splat sort. Default is `true`.
318327
| `sharedMemoryForWorkers` | Tells the viewer to use shared memory via a `SharedArrayBuffer` to transfer data to and from the sorting web worker. If set to `false`, it is recommended that `gpuAcceleratedSort` be set to `false` as well. Defaults to `true`.
319328
| `integerBasedSort` | Tells the sorting web worker to use the integer versions of relevant data to compute the distance of splats from the camera. Since integer arithmetic is faster than floating point, this reduces sort time. However it can result in integer overflows in larger scenes so it should only be used for small scenes. Defaults to `true`.
329+
| `splatSortDistanceMapPrecision` | Specify the precision for the distance map used in the splat sort algorithm. Defaults to 16 (16-bit). A lower precision is faster, but may result in visual artifacts in larger or denser scenes.
320330
| `halfPrecisionCovariancesOnGPU` | Tells the viewer to use 16-bit floating point values when storing splat covariance data in textures, instead of 32-bit. Defaults to `false`.
321331
| `dynamicScene` | Tells the viewer to not make any optimizations that depend on the scene being static. Additionally all splat data retrieved from the viewer's splat mesh will not have their respective scene transform applied to them by default.
322332
| `webXRMode` | Tells the viewer whether or not to enable built-in Web VR or Web AR. Valid values are defined in the `WebXRMode` enum: `None`, `VR`, and `AR`. Defaults to `None`.
333+
| `webXRSessionInit` | Tells the viewer to build a WebXR session with some options. Defaults with {}. For more details : https://developer.mozilla.org/en-US/docs/Web/API/XRSystem/requestSession#options
323334
| `renderMode` | Controls when the viewer renders the scene. Valid values are defined in the `RenderMode` enum: `Always`, `OnChange`, and `Never`. Defaults to `Always`.
324335
| `sceneRevealMode` | Controls the fade-in effect used when the scene is loaded. Valid values are defined in the `SceneRevealMode` enum: `Default`, `Gradual`, and `Instant`. `Default` results in a nice, slow fade-in effect for progressively loaded scenes, and a fast fade-in for non progressively loaded scenes. `Gradual` will force a slow fade-in for all scenes. `Instant` will force all loaded scene data to be immediately visible.
325336
| `antialiased` | When true, will perform additional steps during rendering to address artifacts caused by the rendering of gaussians at substantially different resolutions than that at which they were rendered during training. This will only work correctly for models that were trained using a process that utilizes this compensation calculation. For more details: https://github.com/nerfstudio-project/gsplat/pull/117, https://github.com/graphdeco-inria/gaussian-splatting/issues/294#issuecomment-1772688093
326337
| `focalAdjustment` | Hacky, non-scientific parameter for tweaking focal length related calculations. For scenes with very small gaussians & small details, increasing this value can help improve visual quality. Default value is 1.0.
327338
| `logLevel` | Verbosity of the console logging. Defaults to `GaussianSplats3D.LogLevel.None`.
328339
| `sphericalHarmonicsDegree` | Degree of spherical harmonics to utilize in rendering splats (assuming the data is present in the splat scene). Valid values are 0, 1, or 2. Default value is 0.
329340
| `enableOptionalEffects` | When true, allows for usage of extra properties and attributes during rendering for effects such as opacity adjustment. Default is `false` for performance reasons. These properties are separate from transform properties (scale, rotation, position) that are enabled by the `dynamicScene` parameter.
330-
| `plyInMemoryCompressionLevel` | Level to compress `.ply` files when loading them for direct rendering (not exporting to `.ksplat`). Valid values are the same as `.ksplat` compression levels (0, 1, or 2). Default is 2.
341+
| `inMemoryCompressionLevel` | Level to compress `.ply` or `.ksplat` files when loading them for direct rendering (not exporting to `.ksplat`). Valid values are the same as `.ksplat` compression levels (0, 1, or 2). Default is 0.
342+
| `optimizeSplatData` | Reorder splat data in memory after loading is complete to optimize cache utilization. Default is `true`. Does not apply if splat scene is progressively loaded.
331343
| `freeIntermediateSplatData` | When true, the intermediate splat data that is the result of decompressing splat bufffer(s) and used to populate data textures will be freed. This will reduces memory usage, but if that data needs to be modified it will need to be re-populated from the splat buffer(s). Defaults to `false`.
332344
| `splatRenderMode` | Determine which splat rendering mode to enable. Valid values are defined in the `SplatRenderMode` enum: `ThreeD` and `TwoD`. `ThreeD` is the original/traditional mode and `TwoD` is the new mode described here: https://surfsplatting.github.io/
345+
| `sceneFadeInRateMultiplier` | Customize the speed at which the scene is revealed. Default is 1.0.
333346
<br>
334347

335348
### Creating KSPLAT files
@@ -342,8 +355,12 @@ const compressionLevel = 1;
342355
const splatAlphaRemovalThreshold = 5; // out of 255
343356
const sphericalHarmonicsDegree = 1;
344357
GaussianSplats3D.PlyLoader.loadFromURL('<path to .ply or .splat file>',
358+
onProgress,
359+
progressiveLoad,
360+
onProgressiveLoadSectionProgress,
361+
minimumAlpha,
345362
compressionLevel,
346-
splatAlphaRemovalThreshold,
363+
optimizeSplatData,
347364
sphericalHarmonicsDegree)
348365
.then((splatBuffer) => {
349366
GaussianSplats3D.KSplatLoader.downloadFile(splatBuffer, 'converted_file.ksplat');

demo/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,10 @@
294294

295295
function fileBufferToSplatBuffer(fileBufferData, format, alphaRemovalThreshold, compressionLevel, sectionSize, sceneCenter, blockSize, bucketSize, outSphericalHarmonicsDegree = 0) {
296296
if (format === GaussianSplats3D.SceneFormat.Ply) {
297-
return GaussianSplats3D.PlyLoader.loadFromFileData(fileBufferData.data, alphaRemovalThreshold, compressionLevel, outSphericalHarmonicsDegree, sectionSize, sceneCenter, blockSize, bucketSize);
297+
return GaussianSplats3D.PlyLoader.loadFromFileData(fileBufferData.data, alphaRemovalThreshold, compressionLevel, true, outSphericalHarmonicsDegree, sectionSize, sceneCenter, blockSize, bucketSize);
298298
} else {
299299
if (format === GaussianSplats3D.SceneFormat.Splat) {
300-
return GaussianSplats3D.SplatLoader.loadFromFileData(fileBufferData.data, alphaRemovalThreshold, compressionLevel, sectionSize, sceneCenter, blockSize, bucketSize);
300+
return GaussianSplats3D.SplatLoader.loadFromFileData(fileBufferData.data, alphaRemovalThreshold, compressionLevel, true, sectionSize, sceneCenter, blockSize, bucketSize);
301301
} else {
302302
return GaussianSplats3D.KSplatLoader.loadFromFileData(fileBufferData.data);
303303
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"type": "git",
55
"url": "https://github.com/mkkellogg/GaussianSplats3D"
66
},
7-
"version": "0.4.4",
7+
"version": "0.4.5",
88
"description": "Three.js-based 3D Gaussian splat viewer",
99
"module": "build/gaussian-splats-3d.module.js",
1010
"main": "build/gaussian-splats-3d.umd.cjs",

src/ArrowHelper.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import * as THREE from 'three';
22

3+
const _axis = new THREE.Vector3();
4+
35
export class ArrowHelper extends THREE.Object3D {
46

57
constructor(dir = new THREE.Vector3(0, 0, 1), origin = new THREE.Vector3(0, 0, 0), length = 1,

src/Constants.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export class Constants {
22

3-
static DepthMapRange = 1 << 16;
3+
static DefaultSplatSortDistanceMapPrecision = 16;
44
static MemoryPageSize = 65536;
55
static BytesPerFloat = 4;
66
static BytesPerInt = 4;

src/DropInViewer.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,12 @@ export class DropInViewer extends THREE.Group {
112112
return this.viewer.getSceneCount();
113113
}
114114

115-
dispose() {
116-
return this.viewer.dispose();
115+
setActiveSphericalHarmonicsDegrees(activeSphericalHarmonicsDegrees) {
116+
this.viewer.setActiveSphericalHarmonicsDegrees(activeSphericalHarmonicsDegrees);
117+
}
118+
119+
async dispose() {
120+
return await this.viewer.dispose();
117121
}
118122

119123
static onBeforeRender(viewer, renderer, threeScene, camera) {

src/Util.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,20 @@ export const fetchWithProgress = function(path, onProgress, saveChunks = true) {
6060
const signal = abortController.signal;
6161
let aborted = false;
6262
const abortHandler = (reason) => {
63-
abortController.abort(new AbortedPromiseError(reason));
63+
abortController.abort(reason);
6464
aborted = true;
6565
};
6666

6767
return new AbortablePromise((resolve, reject) => {
6868
fetch(path, { signal })
6969
.then(async (data) => {
70+
// Handle error conditions where data is still returned
71+
if (!data.ok) {
72+
const errorText = await data.text();
73+
reject(new Error(`Fetch failed: ${data.status} ${data.statusText} ${errorText}`));
74+
return;
75+
}
76+
7077
const reader = data.body.getReader();
7178
let bytesDownloaded = 0;
7279
let _fileSize = data.headers.get('Content-Length');
@@ -96,19 +103,20 @@ export const fetchWithProgress = function(path, onProgress, saveChunks = true) {
96103
percent = bytesDownloaded / fileSize * 100;
97104
percentLabel = `${percent.toFixed(2)}%`;
98105
}
99-
if (saveChunks) chunks.push(chunk);
106+
if (saveChunks) {
107+
chunks.push(chunk);
108+
}
100109
if (onProgress) {
101-
const cancelSaveChucnks = onProgress(percent, percentLabel, chunk, fileSize);
102-
if (cancelSaveChucnks) saveChunks = false;
110+
onProgress(percent, percentLabel, chunk, fileSize);
103111
}
104112
} catch (error) {
105113
reject(error);
106-
break;
114+
return;
107115
}
108116
}
109117
})
110118
.catch((error) => {
111-
reject(error);
119+
reject(new AbortedPromiseError(error));
112120
});
113121
}, abortHandler);
114122

0 commit comments

Comments
 (0)