Skip to content

Commit 307e2e6

Browse files
authored
WebGLRenderer: Add targetScene parameter to compile() methods. (#26966)
1 parent d50c76d commit 307e2e6

File tree

2 files changed

+41
-59
lines changed

2 files changed

+41
-59
lines changed

examples/webgl_loader_gltf.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,13 @@
6262
const loader = new GLTFLoader().setPath( 'models/gltf/DamagedHelmet/glTF/' );
6363
loader.load( 'DamagedHelmet.gltf', async function ( gltf ) {
6464

65-
scene.add( gltf.scene );
65+
const model = gltf.scene;
6666

67-
await renderer.compileAsync( scene, camera );
67+
// wait until the model can be added to the scene without blocking due to shader compilation
68+
69+
await renderer.compileAsync( model, camera, scene );
70+
71+
scene.add( model );
6872

6973
render();
7074

src/renderers/WebGLRenderer.js

Lines changed: 35 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -939,14 +939,18 @@ class WebGLRenderer {
939939

940940
}
941941

942-
this.compile = function ( scene, camera ) {
942+
this.compile = function ( scene, camera, targetScene = null ) {
943943

944-
currentRenderState = renderStates.get( scene );
944+
if ( targetScene === null ) targetScene = scene;
945+
946+
currentRenderState = renderStates.get( targetScene );
945947
currentRenderState.init();
946948

947949
renderStateStack.push( currentRenderState );
948950

949-
scene.traverseVisible( function ( object ) {
951+
// gather lights from both the target scene and the new object that will be added to the scene.
952+
953+
targetScene.traverseVisible( function ( object ) {
950954

951955
if ( object.isLight && object.layers.test( camera.layers ) ) {
952956

@@ -962,67 +966,31 @@ class WebGLRenderer {
962966

963967
} );
964968

965-
currentRenderState.setupLights( _this._useLegacyLights );
966-
967-
scene.traverse( function ( object ) {
968-
969-
const material = object.material;
969+
if ( scene !== targetScene ) {
970970

971-
if ( material ) {
971+
scene.traverseVisible( function ( object ) {
972972

973-
if ( Array.isArray( material ) ) {
973+
if ( object.isLight && object.layers.test( camera.layers ) ) {
974974

975-
for ( let i = 0; i < material.length; i ++ ) {
975+
currentRenderState.pushLight( object );
976976

977-
const material2 = material[ i ];
977+
if ( object.castShadow ) {
978978

979-
prepareMaterial( material2, scene, object );
979+
currentRenderState.pushShadow( object );
980980

981981
}
982982

983-
} else {
984-
985-
prepareMaterial( material, scene, object );
986-
987983
}
988984

989-
}
990-
991-
} );
992-
993-
renderStateStack.pop();
994-
currentRenderState = null;
995-
996-
};
997-
998-
// compileAsync
999-
1000-
this.compileAsync = function ( scene, camera ) {
1001-
1002-
currentRenderState = renderStates.get( scene );
1003-
currentRenderState.init();
1004-
1005-
renderStateStack.push( currentRenderState );
1006-
1007-
scene.traverseVisible( function ( object ) {
1008-
1009-
if ( object.isLight && object.layers.test( camera.layers ) ) {
1010-
1011-
currentRenderState.pushLight( object );
1012-
1013-
if ( object.castShadow ) {
1014-
1015-
currentRenderState.pushShadow( object );
1016-
1017-
}
1018-
1019-
}
985+
} );
1020986

1021-
} );
987+
}
1022988

1023989
currentRenderState.setupLights( _this._useLegacyLights );
1024990

1025-
const compiling = new Set();
991+
// Only initialize materials in the new scene, not the targetScene.
992+
993+
const materials = new Set();
1026994

1027995
scene.traverse( function ( object ) {
1028996

@@ -1036,15 +1004,15 @@ class WebGLRenderer {
10361004

10371005
const material2 = material[ i ];
10381006

1039-
prepareMaterial( material2, scene, object );
1040-
compiling.add( material2 );
1007+
prepareMaterial( material2, targetScene, object );
1008+
materials.add( material2 );
10411009

10421010
}
10431011

10441012
} else {
10451013

1046-
prepareMaterial( material, scene, object );
1047-
compiling.add( material );
1014+
prepareMaterial( material, targetScene, object );
1015+
materials.add( material );
10481016

10491017
}
10501018

@@ -1055,30 +1023,40 @@ class WebGLRenderer {
10551023
renderStateStack.pop();
10561024
currentRenderState = null;
10571025

1026+
return materials;
1027+
1028+
};
1029+
1030+
// compileAsync
1031+
1032+
this.compileAsync = function ( scene, camera, targetScene = null ) {
1033+
1034+
const materials = this.compile( scene, camera, targetScene );
1035+
10581036
// Wait for all the materials in the new object to indicate that they're
10591037
// ready to be used before resolving the promise.
10601038

10611039
return new Promise( ( resolve ) => {
10621040

10631041
function checkMaterialsReady() {
10641042

1065-
compiling.forEach( function ( material ) {
1043+
materials.forEach( function ( material ) {
10661044

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

10701048
if ( program.isReady() ) {
10711049

10721050
// remove any programs that report they're ready to use from the list
1073-
compiling.delete( material );
1051+
materials.delete( material );
10741052

10751053
}
10761054

10771055
} );
10781056

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

1081-
if ( compiling.size === 0 ) {
1059+
if ( materials.size === 0 ) {
10821060

10831061
resolve( scene );
10841062
return;

0 commit comments

Comments
 (0)