From 8c269c406110603877319bb65a17a57488fe150c Mon Sep 17 00:00:00 2001 From: Mugen87 Date: Sat, 14 Oct 2023 20:25:33 +0200 Subject: [PATCH] WebGLRenderer: Add `targetScene` parameter to `compile()` methods. --- examples/webgl_loader_gltf.html | 8 ++- src/renderers/WebGLRenderer.js | 92 +++++++++++++-------------------- 2 files changed, 41 insertions(+), 59 deletions(-) diff --git a/examples/webgl_loader_gltf.html b/examples/webgl_loader_gltf.html index 5fc7e80327b48a..7b89a65f4dce71 100644 --- a/examples/webgl_loader_gltf.html +++ b/examples/webgl_loader_gltf.html @@ -62,9 +62,13 @@ const loader = new GLTFLoader().setPath( 'models/gltf/DamagedHelmet/glTF/' ); loader.load( 'DamagedHelmet.gltf', async function ( gltf ) { - scene.add( gltf.scene ); + const model = gltf.scene; - await renderer.compileAsync( scene, camera ); + // wait until the model can be added to the scene without blocking due to shader compilation + + await renderer.compileAsync( model, camera, scene ); + + scene.add( model ); render(); diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 1930522ee58ff7..15ebd1c6434e2c 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -939,14 +939,18 @@ class WebGLRenderer { } - this.compile = function ( scene, camera ) { + this.compile = function ( scene, camera, targetScene = null ) { - currentRenderState = renderStates.get( scene ); + if ( targetScene === null ) targetScene = scene; + + currentRenderState = renderStates.get( targetScene ); currentRenderState.init(); renderStateStack.push( currentRenderState ); - scene.traverseVisible( function ( object ) { + // gather lights from both the target scene and the new object that will be added to the scene. + + targetScene.traverseVisible( function ( object ) { if ( object.isLight && object.layers.test( camera.layers ) ) { @@ -962,67 +966,31 @@ class WebGLRenderer { } ); - currentRenderState.setupLights( _this._useLegacyLights ); - - scene.traverse( function ( object ) { - - const material = object.material; + if ( scene !== targetScene ) { - if ( material ) { + scene.traverseVisible( function ( object ) { - if ( Array.isArray( material ) ) { + if ( object.isLight && object.layers.test( camera.layers ) ) { - for ( let i = 0; i < material.length; i ++ ) { + currentRenderState.pushLight( object ); - const material2 = material[ i ]; + if ( object.castShadow ) { - prepareMaterial( material2, scene, object ); + currentRenderState.pushShadow( object ); } - } else { - - prepareMaterial( material, scene, object ); - } - } - - } ); - - renderStateStack.pop(); - currentRenderState = null; - - }; - - // compileAsync - - this.compileAsync = function ( scene, camera ) { - - currentRenderState = renderStates.get( scene ); - currentRenderState.init(); - - renderStateStack.push( currentRenderState ); - - scene.traverseVisible( function ( object ) { - - if ( object.isLight && object.layers.test( camera.layers ) ) { - - currentRenderState.pushLight( object ); - - if ( object.castShadow ) { - - currentRenderState.pushShadow( object ); - - } - - } + } ); - } ); + } currentRenderState.setupLights( _this._useLegacyLights ); - const compiling = new Set(); + // Only initialize materials in the new scene, not the targetScene. + + const materials = new Set(); scene.traverse( function ( object ) { @@ -1036,15 +1004,15 @@ class WebGLRenderer { const material2 = material[ i ]; - prepareMaterial( material2, scene, object ); - compiling.add( material2 ); + prepareMaterial( material2, targetScene, object ); + materials.add( material2 ); } } else { - prepareMaterial( material, scene, object ); - compiling.add( material ); + prepareMaterial( material, targetScene, object ); + materials.add( material ); } @@ -1055,6 +1023,16 @@ class WebGLRenderer { renderStateStack.pop(); currentRenderState = null; + return materials; + + }; + + // compileAsync + + this.compileAsync = function ( scene, camera, targetScene = null ) { + + const materials = this.compile( scene, camera, targetScene ); + // Wait for all the materials in the new object to indicate that they're // ready to be used before resolving the promise. @@ -1062,7 +1040,7 @@ class WebGLRenderer { function checkMaterialsReady() { - compiling.forEach( function ( material ) { + materials.forEach( function ( material ) { const materialProperties = properties.get( material ); const program = materialProperties.currentProgram; @@ -1070,7 +1048,7 @@ class WebGLRenderer { if ( program.isReady() ) { // remove any programs that report they're ready to use from the list - compiling.delete( material ); + materials.delete( material ); } @@ -1078,7 +1056,7 @@ class WebGLRenderer { // once the list of compiling materials is empty, call the callback - if ( compiling.size === 0 ) { + if ( materials.size === 0 ) { resolve( scene ); return;