@@ -20,8 +20,7 @@ import {
2020 TONEMAP_ACES2 ,
2121 TONEMAP_NEUTRAL ,
2222 Vec3 ,
23- GSplatComponent ,
24- platform
23+ GSplatComponent
2524} from 'playcanvas' ;
2625
2726import { Annotations } from './annotations' ;
@@ -332,13 +331,22 @@ class Viewer {
332331
333332 const { gsplat } = app . scene ;
334333
335- // lod ranges
336- const low = [ 2 , 5 ] ;
337- const high = [ 0 , 2 ] ;
334+ // quality ranges
335+ const quality = {
336+ low : {
337+ range : [ 2 , 8 ] ,
338+ splatBudget : 1
339+ } ,
340+ high : {
341+ range : [ 0 , 8 ] ,
342+ splatBudget : 4
343+ }
344+ } ;
338345
339- // in unified mode, for now we hard-code LOD range on mobile vs desktop
340- gsplat . lodRangeMin = low [ 0 ] ;
341- gsplat . lodRangeMax = low [ 1 ] ;
346+ // start in low quality mode so we can get user interacting asap
347+ gsplat . lodRangeMin = quality . low . range [ 0 ] ;
348+ gsplat . lodRangeMax = quality . low . range [ 1 ] ;
349+ gsplat . splatBudget = quality . low . splatBudget * 1000000 ;
342350
343351 // these two allow LOD behind camera to drop, saves lots of splats
344352 gsplat . lodUpdateAngle = 90 ;
@@ -349,23 +357,30 @@ class Viewer {
349357
350358 const eventHandler = app . systems . gsplat ;
351359
352- // force render empty frames otherwise unified rendering doesn't update
360+ // we must force continuous rendering with streaming & lod system
353361 this . forceRenderNextFrame = true ;
354362
355363 let current = 0 ;
356364 let watermark = 1 ;
357365 const readyHandler = ( camera : CameraComponent , layer : Layer , ready : boolean , loading : number ) => {
358- if ( ready && ! loading ) {
366+ if ( ready && loading === 0 ) {
359367 // scene is done loading
360-
361368 eventHandler . off ( 'frame:ready' , readyHandler ) ;
362369
363- this . forceRenderNextFrame = false ;
364370 state . readyToRender = true ;
365371
366- const range = platform . mobile ? low : high ;
367- gsplat . lodRangeMin = range [ 0 ] ;
368- gsplat . lodRangeMax = range [ 1 ] ;
372+ // handle quality mode changes
373+ const updateLod = ( ) => {
374+ const settings = state . hqMode ? quality . high : quality . low ;
375+ gsplat . lodRangeMin = settings . range [ 0 ] ;
376+ gsplat . lodRangeMax = settings . range [ 1 ] ;
377+ gsplat . splatBudget = settings . splatBudget * 1000000 ;
378+ } ;
379+ events . on ( 'hqMode:changed' , updateLod ) ;
380+ updateLod ( ) ;
381+
382+ // debug colorize lods
383+ gsplat . colorizeLod = config . colorize ;
369384
370385 // wait for the first valid frame to complete rendering
371386 app . once ( 'frameend' , ( ) => {
@@ -376,18 +391,13 @@ class Viewer {
376391 } ) ;
377392 }
378393
379- if ( ready ) {
380- app . renderNextFrame = true ;
381- }
382-
383394 // update loading status
384395 if ( loading !== current ) {
385396 watermark = Math . max ( watermark , loading ) ;
386397 current = watermark - loading ;
387398 state . progress = Math . trunc ( current / watermark * 100 ) ;
388399 }
389400 } ;
390-
391401 eventHandler . on ( 'frame:ready' , readyHandler ) ;
392402 }
393403 } ) ;
0 commit comments