Skip to content

Commit 5e0f4d2

Browse files
authored
Clamp camera near clip and switch gsplat rendering to on-demand (#265)
1 parent 4c49661 commit 5e0f4d2

3 files changed

Lines changed: 16 additions & 37 deletions

File tree

src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,6 @@ const main = async (canvas: HTMLCanvasElement, settingsJson: any, config: Config
221221

222222
const state = observe(events, {
223223
loaded: false,
224-
readyToRender: false,
225224
performanceMode: storedPerformanceMode !== null ? storedPerformanceMode === 'true' : platform.mobile,
226225
progress: 0,
227226
inputMode: platform.mobile ? 'touch' : 'desktop',

src/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ type Config = {
3131
// observable state that can change at runtime
3232
type State = {
3333
loaded: boolean; // true once first frame is rendered
34-
readyToRender: boolean; // don't render till this is set
3534
performanceMode: boolean;
3635
progress: number; // content loading progress 0-100
3736
inputMode: InputMode;

src/viewer.ts

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,6 @@ class Viewer {
155155

156156
annotations: Annotations;
157157

158-
forceRenderNextFrame = false;
159-
160158
voxelOverlay: VoxelDebugOverlay | null = null;
161159

162160
meshOverlay: MeshDebugOverlay | null = null;
@@ -200,8 +198,13 @@ class Viewer {
200198
}
201199
};
202200

203-
// disable auto render, we'll render only when camera changes
204-
app.autoRender = false;
201+
// Render every frame while the scene loads, then switch to on-demand rendering once the
202+
// first complete frame is ready (autoRender is disabled in the frame:ready handler below).
203+
// Loading progress and the ready transition are both reported via frame:ready, which only
204+
// fires when a frame is rendered — so we must render continuously through loading. After
205+
// that, rendering is driven on demand by frame:request and camera-change detection. This
206+
// mirrors the engine's simple-on-demand gsplat example.
207+
app.autoRender = true;
205208

206209
// configure the camera
207210
this.configureCamera(settings);
@@ -252,15 +255,6 @@ class Viewer {
252255
}
253256
}
254257

255-
// suppress rendering till we're ready
256-
if (!state.readyToRender) {
257-
app.renderNextFrame = false;
258-
}
259-
260-
if (this.forceRenderNextFrame) {
261-
app.renderNextFrame = true;
262-
}
263-
264258
if (app.renderNextFrame) {
265259
prevWorld.copy(world);
266260
prevProj.copy(proj);
@@ -287,7 +281,7 @@ class Viewer {
287281
const near = Math.max(dist - boundRadius, far / (1024 * 16));
288282

289283
cameraEntity.camera.farClip = far;
290-
cameraEntity.camera.nearClip = near;
284+
cameraEntity.camera.nearClip = Math.min(1.0, near);
291285
};
292286

293287
// handle application update
@@ -445,35 +439,22 @@ class Viewer {
445439

446440
const eventHandler = app.systems.gsplat;
447441

448-
// idle timer: force continuous rendering until 4s of inactivity
449-
let idleTime = 0;
450-
this.forceRenderNextFrame = true;
451-
452-
app.on('update', (dt: number) => {
453-
idleTime += dt;
454-
this.forceRenderNextFrame = idleTime < 4;
455-
});
456-
457-
events.on('inputEvent', (type: string) => {
458-
if (type !== 'interact') {
459-
idleTime = 0;
460-
}
461-
});
462-
463-
eventHandler.on('frame:ready', (_camera: CameraComponent, _layer: Layer, ready: boolean, loading: number) => {
464-
if (loading > 0 || !ready) {
465-
idleTime = 0;
466-
}
442+
// Once on demand (autoRender is disabled at ready, below), render when gsplat streaming
443+
// produces new data a render would show (new LOD/world-state, pending sort). This also
444+
// keeps work-buffer texture lifetime coupled to the submit under app.autoRender = false.
445+
eventHandler.on('frame:request', () => {
446+
app.renderNextFrame = true;
467447
});
468448

469449
let current = 0;
470450
let watermark = 1;
471451
const readyHandler = (camera: CameraComponent, layer: Layer, ready: boolean, loading: number) => {
472452
if (ready && loading === 0) {
473-
// scene is done loading
453+
// scene is done with initial/reveal loading
474454
eventHandler.off('frame:ready', readyHandler);
475455

476-
state.readyToRender = true;
456+
// switch to on-demand rendering (frame:request + camera-change detection)
457+
app.autoRender = false;
477458

478459
// handle quality mode changes
479460
events.on('performanceMode:changed', applyPerfSettings);

0 commit comments

Comments
 (0)