|
@@ -917,29 +917,87 @@ class WebGLRenderer {
|
|
|
|
|
|
// Compile
|
|
|
|
|
|
+ function prepareMaterial( material, scene, object ) {
|
|
|
+
|
|
|
+ if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
|
|
|
+
|
|
|
+ material.side = BackSide;
|
|
|
+ material.needsUpdate = true;
|
|
|
+ getProgram( material, scene, object );
|
|
|
+
|
|
|
+ material.side = FrontSide;
|
|
|
+ material.needsUpdate = true;
|
|
|
+ getProgram( material, scene, object );
|
|
|
+
|
|
|
+ material.side = DoubleSide;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ getProgram( material, scene, object );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
this.compile = function ( scene, camera ) {
|
|
|
|
|
|
- function prepare( material, scene, object ) {
|
|
|
+ currentRenderState = renderStates.get( scene );
|
|
|
+ currentRenderState.init();
|
|
|
|
|
|
- if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
|
|
|
+ renderStateStack.push( currentRenderState );
|
|
|
|
|
|
- material.side = BackSide;
|
|
|
- material.needsUpdate = true;
|
|
|
- getProgram( material, scene, object );
|
|
|
+ scene.traverseVisible( function ( object ) {
|
|
|
|
|
|
- material.side = FrontSide;
|
|
|
- material.needsUpdate = true;
|
|
|
- getProgram( material, scene, object );
|
|
|
+ if ( object.isLight && object.layers.test( camera.layers ) ) {
|
|
|
|
|
|
- material.side = DoubleSide;
|
|
|
+ currentRenderState.pushLight( object );
|
|
|
|
|
|
- } else {
|
|
|
+ if ( object.castShadow ) {
|
|
|
|
|
|
- getProgram( material, scene, object );
|
|
|
+ currentRenderState.pushShadow( object );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ } );
|
|
|
+
|
|
|
+ currentRenderState.setupLights( _this._useLegacyLights );
|
|
|
+
|
|
|
+ scene.traverse( function ( object ) {
|
|
|
+
|
|
|
+ const material = object.material;
|
|
|
+
|
|
|
+ if ( material ) {
|
|
|
+
|
|
|
+ if ( Array.isArray( material ) ) {
|
|
|
+
|
|
|
+ for ( let i = 0; i < material.length; i ++ ) {
|
|
|
+
|
|
|
+ const material2 = material[ i ];
|
|
|
+
|
|
|
+ prepareMaterial( material2, scene, object );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ prepareMaterial( material, scene, object );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ renderStateStack.pop();
|
|
|
+ currentRenderState = null;
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ // compileAsync
|
|
|
+
|
|
|
+ this.compileAsync = function ( scene, camera ) {
|
|
|
|
|
|
currentRenderState = renderStates.get( scene );
|
|
|
currentRenderState.init();
|
|
@@ -964,6 +1022,8 @@ class WebGLRenderer {
|
|
|
|
|
|
currentRenderState.setupLights( _this._useLegacyLights );
|
|
|
|
|
|
+ const compiling = new Set();
|
|
|
+
|
|
|
scene.traverse( function ( object ) {
|
|
|
|
|
|
const material = object.material;
|
|
@@ -976,13 +1036,15 @@ class WebGLRenderer {
|
|
|
|
|
|
const material2 = material[ i ];
|
|
|
|
|
|
- prepare( material2, scene, object );
|
|
|
+ prepareMaterial( material2, scene, object );
|
|
|
+ compiling.add( material2 );
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- prepare( material, scene, object );
|
|
|
+ prepareMaterial( material, scene, object );
|
|
|
+ compiling.add( material );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -993,6 +1055,60 @@ class WebGLRenderer {
|
|
|
renderStateStack.pop();
|
|
|
currentRenderState = null;
|
|
|
|
|
|
+ // 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 ) {
|
|
|
+
|
|
|
+ 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 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ // once the list of compiling materials is empty, call the callback
|
|
|
+
|
|
|
+ if ( compiling.size === 0 ) {
|
|
|
+
|
|
|
+ resolve( scene );
|
|
|
+ return;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // if some materials are still not ready, wait a bit and check again
|
|
|
+
|
|
|
+ setTimeout( checkMaterialsReady, 10 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) {
|
|
|
+
|
|
|
+ // If we can check the compilation status of the materials without
|
|
|
+ // blocking then do so right away.
|
|
|
+
|
|
|
+ checkMaterialsReady();
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ // Otherwise start by waiting a bit to give the materials we just
|
|
|
+ // initialized a chance to finish.
|
|
|
+
|
|
|
+ setTimeout( checkMaterialsReady, 10 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
};
|
|
|
|
|
|
// Animation Loop
|