Skip to content

Commit

Permalink
WebGLRenderer: Add targetScene parameter to compile() methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mugen87 committed Oct 14, 2023
1 parent 641b108 commit 8c269c4
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 59 deletions.
8 changes: 6 additions & 2 deletions examples/webgl_loader_gltf.html
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
92 changes: 35 additions & 57 deletions src/renderers/WebGLRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) ) {

Expand All @@ -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 ) {

Expand All @@ -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 );

}

Expand All @@ -1055,30 +1023,40 @@ 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.

return new Promise( ( resolve ) => {

function checkMaterialsReady() {

compiling.forEach( function ( material ) {
materials.forEach( function ( material ) {

const materialProperties = properties.get( material );
const program = materialProperties.currentProgram;

if ( program.isReady() ) {

// remove any programs that report they're ready to use from the list
compiling.delete( material );
materials.delete( material );

}

} );

// once the list of compiling materials is empty, call the callback

if ( compiling.size === 0 ) {
if ( materials.size === 0 ) {

resolve( scene );
return;
Expand Down

0 comments on commit 8c269c4

Please sign in to comment.