|
@@ -67,8 +67,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
var _lightPrePass = false;
|
|
|
var _cacheKeepAlive = false;
|
|
|
|
|
|
- var _invisibleMaterial = new THREE.ShaderMaterial( { visible: false } );
|
|
|
-
|
|
|
+ var _tmpMaterial = new THREE.ShaderMaterial( { visible: false } );
|
|
|
var _tmpVector3 = new THREE.Vector3();
|
|
|
|
|
|
// scene/material/light cache for deferred rendering.
|
|
@@ -80,13 +79,12 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
var _lightScenesCache = {};
|
|
|
var _lightFullscreenScenesCache = {};
|
|
|
|
|
|
- // originalMaterial.uuid -> deferredMaterial
|
|
|
- // (no mapping from children of MultiMaterial)
|
|
|
+ // object.material.uuid -> deferredMaterial or
|
|
|
+ // object.material[ n ].uuid -> deferredMaterial
|
|
|
var _normalDepthMaterialsCache = {};
|
|
|
var _normalDepthShininessMaterialsCache = {};
|
|
|
var _colorMaterialsCache = {};
|
|
|
var _reconstructionMaterialsCache = {};
|
|
|
- var _invisibleMultiMaterialsCache = {};
|
|
|
|
|
|
// originalLight.uuid -> deferredLight
|
|
|
var _deferredLightsCache = {};
|
|
@@ -97,8 +95,8 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
var _removeThresholdCount = 60;
|
|
|
|
|
|
- // object.uuid -> originalMaterial
|
|
|
- // deferred materials.uuid -> originalMaterial
|
|
|
+ // deferredMaterials.uuid -> object.material or
|
|
|
+ // deferredMaterials.uuid -> object.material[ n ]
|
|
|
// save before render and release after render.
|
|
|
var _originalMaterialsTable = {};
|
|
|
|
|
@@ -106,6 +104,11 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
// save before render and release after render.
|
|
|
var _originalOnBeforeRendersTable = {};
|
|
|
|
|
|
+ // object.material.uuid -> object.material.visible or
|
|
|
+ // object.material[ i ].uuid -> object.material[ i ].visible or
|
|
|
+ // save before render and release after render.
|
|
|
+ var _originalVisibleTable = {};
|
|
|
+
|
|
|
// external properties
|
|
|
|
|
|
this.renderer = undefined;
|
|
@@ -328,70 +331,73 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- function getMaterialFromCacheOrCreate( originalMaterial, cache, func ) {
|
|
|
+ function getMaterialFromCacheOrCreate( originalMaterial, cache, createFunc, updateFunc ) {
|
|
|
|
|
|
var data = cache[ originalMaterial.uuid ];
|
|
|
|
|
|
if ( data === undefined ) {
|
|
|
|
|
|
data = createCacheData();
|
|
|
+ data.material = createFunc( originalMaterial );
|
|
|
+ cache[ originalMaterial.uuid ] = data;
|
|
|
|
|
|
- var material;
|
|
|
+ }
|
|
|
|
|
|
- if ( originalMaterial.isMultiMaterial === true ) {
|
|
|
+ data.used = true;
|
|
|
|
|
|
- var materials = [];
|
|
|
+ updateFunc( data.material, originalMaterial );
|
|
|
|
|
|
- for ( var i = 0, il = originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
+ _originalMaterialsTable[ data.material.uuid ] = originalMaterial;
|
|
|
|
|
|
- materials.push( func( originalMaterial.materials[ i ] ) );
|
|
|
+ return data.material;
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- material = new THREE.MultiMaterial( materials );
|
|
|
+ function overrideMaterialAndOnBeforeRender( object, getMaterialFunc, onBeforeRender ) {
|
|
|
|
|
|
- } else {
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
+
|
|
|
+ if ( Array.isArray( object.material ) ) {
|
|
|
|
|
|
- material = func( originalMaterial );
|
|
|
+ for ( var i = 0, il = object.material.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ object.material[ i ] = getMaterialFunc( object.material[ i ] );
|
|
|
|
|
|
}
|
|
|
|
|
|
- data.material = material;
|
|
|
+ } else {
|
|
|
|
|
|
- cache[ originalMaterial.uuid ] = data;
|
|
|
+ object.material = getMaterialFunc( object.material );
|
|
|
|
|
|
}
|
|
|
|
|
|
- return data.material;
|
|
|
+ object.onBeforeRender = onBeforeRender;
|
|
|
|
|
|
}
|
|
|
|
|
|
- function setMaterialNormalDepth( object ) {
|
|
|
+ function restoreOriginalMaterial( object ) {
|
|
|
|
|
|
if ( object.material === undefined ) return;
|
|
|
|
|
|
- var originalMaterial = _originalMaterialsTable[ object.uuid ];
|
|
|
- var material = getNormalDepthMaterial( originalMaterial );
|
|
|
-
|
|
|
- _originalMaterialsTable[ material.uuid ] = originalMaterial;
|
|
|
+ if ( Array.isArray( object.material ) ) {
|
|
|
|
|
|
- if ( material.isMultiMaterial === true ) {
|
|
|
+ for ( var i = 0, il = object.material.length; i < il; i ++ ) {
|
|
|
|
|
|
- for ( var i = 0, il = material.materials.length; i < il; i ++ ) {
|
|
|
-
|
|
|
- _originalMaterialsTable[ material.materials[ i ].uuid ] = originalMaterial.materials[ i ];
|
|
|
- updateDeferredNormalDepthMaterial( material.materials[ i ], originalMaterial.materials[ i ] );
|
|
|
+ object.material[ i ] = _originalMaterialsTable[ object.material[ i ].uuid ];
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- updateDeferredNormalDepthMaterial( material, originalMaterial );
|
|
|
+ object.material = _originalMaterialsTable[ object.material.uuid ];
|
|
|
|
|
|
}
|
|
|
|
|
|
- object.material = material;
|
|
|
- object.onBeforeRender = updateDeferredNormalDepthUniforms;
|
|
|
+ }
|
|
|
+
|
|
|
+ function setMaterialNormalDepth( object ) {
|
|
|
+
|
|
|
+ overrideMaterialAndOnBeforeRender( object, getNormalDepthMaterial, updateDeferredNormalDepthUniforms );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -400,7 +406,8 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
return getMaterialFromCacheOrCreate(
|
|
|
originalMaterial,
|
|
|
( _lightPrePass ) ? _normalDepthShininessMaterialsCache : _normalDepthMaterialsCache,
|
|
|
- createDeferredNormalDepthMaterial
|
|
|
+ createDeferredNormalDepthMaterial,
|
|
|
+ updateDeferredNormalDepthMaterial
|
|
|
);
|
|
|
|
|
|
}
|
|
@@ -448,30 +455,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
function setMaterialColor( object ) {
|
|
|
|
|
|
- if ( object.material === undefined ) return;
|
|
|
-
|
|
|
- var originalMaterial = _originalMaterialsTable[ object.uuid ];
|
|
|
- var material = getColorMaterial( originalMaterial );
|
|
|
-
|
|
|
- _originalMaterialsTable[ material.uuid ] = originalMaterial;
|
|
|
-
|
|
|
- if ( originalMaterial.isMultiMaterial === true ) {
|
|
|
-
|
|
|
- for ( var i = 0, il = originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
-
|
|
|
- _originalMaterialsTable[ material.materials[ i ].uuid ] = originalMaterial.materials[ i ];
|
|
|
- updateDeferredColorMaterial( material.materials[ i ], originalMaterial.materials[ i ] );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- updateDeferredColorMaterial( material, originalMaterial );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- object.material = material;
|
|
|
- object.onBeforeRender = updateDeferredColorUniforms;
|
|
|
+ overrideMaterialAndOnBeforeRender( object, getColorMaterial, updateDeferredColorUniforms );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -480,7 +464,8 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
return getMaterialFromCacheOrCreate(
|
|
|
originalMaterial,
|
|
|
_colorMaterialsCache,
|
|
|
- createDeferredColorMaterial
|
|
|
+ createDeferredColorMaterial,
|
|
|
+ updateDeferredColorMaterial
|
|
|
);
|
|
|
|
|
|
}
|
|
@@ -551,48 +536,24 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
function setMaterialReconstruction( object ) {
|
|
|
|
|
|
- if ( object.material === undefined ) return;
|
|
|
-
|
|
|
- var originalMaterial = _originalMaterialsTable[ object.uuid ];
|
|
|
-
|
|
|
- if ( originalMaterial.transparent === true ) {
|
|
|
-
|
|
|
- object.material = originalMaterial;
|
|
|
- object.onBeforeRender = _originalOnBeforeRendersTable[ object.uuid ];
|
|
|
-
|
|
|
- return;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var material = getReconstructionMaterial( originalMaterial );
|
|
|
- _originalMaterialsTable[ material.uuid ] = originalMaterial;
|
|
|
+ overrideMaterialAndOnBeforeRender( object, getReconstructionMaterial, updateDeferredReconstructionUniforms );
|
|
|
|
|
|
- if ( originalMaterial.isMultiMaterial === true ) {
|
|
|
-
|
|
|
- for ( var i = 0, il = originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
-
|
|
|
- _originalMaterialsTable[ material.materials[ i ].uuid ] = originalMaterial.materials[ i ];
|
|
|
- updateDeferredReconstructionMaterial( material.materials[ i ], originalMaterial.materials[ i ] );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ function getReconstructionMaterial( originalMaterial ) {
|
|
|
|
|
|
- } else {
|
|
|
+ if ( originalMaterial.transparent === true ) {
|
|
|
|
|
|
- updateDeferredReconstructionMaterial( material, originalMaterial );
|
|
|
+ _originalMaterialsTable[ originalMaterial.uuid ] = originalMaterial;
|
|
|
+ return originalMaterial;
|
|
|
|
|
|
}
|
|
|
|
|
|
- object.material = material;
|
|
|
- object.onBeforeRender = updateDeferredReconstructionUniforms;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function getReconstructionMaterial( originalMaterial ) {
|
|
|
-
|
|
|
return getMaterialFromCacheOrCreate(
|
|
|
originalMaterial,
|
|
|
_reconstructionMaterialsCache,
|
|
|
- createDeferredReconstructionMaterial
|
|
|
+ createDeferredReconstructionMaterial,
|
|
|
+ updateDeferredReconstructionMaterial
|
|
|
);
|
|
|
|
|
|
}
|
|
@@ -622,65 +583,72 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
function updateDeferredReconstructionUniforms( renderer, scene, camera, geometry, material, group ) {
|
|
|
|
|
|
+ if ( material.transparent === true ) {
|
|
|
+
|
|
|
+ // 'this' is object here because this method is set as object.onBefore()
|
|
|
+ var onBeforeRender = _originalOnBeforeRendersTable[ this.uuid ];
|
|
|
+
|
|
|
+ if ( onBeforeRender ) {
|
|
|
+
|
|
|
+ onBeforeRender.call( this, renderer, scene, camera, geometry, material, group );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
updateDeferredColorUniforms( renderer, scene, camera, geometry, material, group );
|
|
|
|
|
|
material.uniforms.samplerLight.value = _compLight.renderTarget2.texture;
|
|
|
|
|
|
}
|
|
|
|
|
|
- function setMaterialForwardRendering( object ) {
|
|
|
+ function setVisibleForForwardRendering( object ) {
|
|
|
|
|
|
if ( object.material === undefined ) return;
|
|
|
|
|
|
- var originalMaterial = _originalMaterialsTable[ object.uuid ];
|
|
|
+ if ( Array.isArray( object.material ) ) {
|
|
|
|
|
|
- if ( originalMaterial.isMultiMaterial === true ) {
|
|
|
+ for ( var i = 0, il = object.material.length; i < il; i ++ ) {
|
|
|
|
|
|
- var material = getInvisibleMultiMaterial( originalMaterial );
|
|
|
+ if ( _originalVisibleTable[ object.material[ i ].uuid ] === undefined ) {
|
|
|
|
|
|
- for ( var i = 0, il = originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
+ _originalVisibleTable[ object.material[ i ].uuid ] = object.material[ i ].visible;
|
|
|
+ object.material[ i ].visible = object.material[ i ].transparent && object.material[ i ].visible;
|
|
|
|
|
|
- material.materials[ i ] = getForwardRenderingMaterial( originalMaterial.materials[ i ] );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- object.material = material;
|
|
|
-
|
|
|
} else {
|
|
|
|
|
|
- object.material = getForwardRenderingMaterial( originalMaterial );
|
|
|
+ if ( _originalVisibleTable[ object.material.uuid ] === undefined ) {
|
|
|
|
|
|
- }
|
|
|
+ _originalVisibleTable[ object.material.uuid ] = object.material.visible;
|
|
|
+ object.material.visible = object.material.transparent && object.material.visible;
|
|
|
|
|
|
- object.onBeforeRender = _originalOnBeforeRendersTable[ object.uuid ];
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function getInvisibleMultiMaterial( originalMaterial ) {
|
|
|
+ }
|
|
|
|
|
|
- return getMaterialFromCacheOrCreate(
|
|
|
- originalMaterial,
|
|
|
- _invisibleMultiMaterialsCache,
|
|
|
- createInvisibleMaterial
|
|
|
- );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- function createInvisibleMaterial( originalMaterial ) {
|
|
|
+ function restoreVisible( object ) {
|
|
|
|
|
|
- return _invisibleMaterial;
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
|
|
|
- }
|
|
|
+ if ( Array.isArray( object.material ) ) {
|
|
|
|
|
|
- function getForwardRenderingMaterial( originalMaterial ) {
|
|
|
+ for ( var i = 0, il = object.material.length; i < il; i ++ ) {
|
|
|
|
|
|
- if ( originalMaterial.transparent === true && originalMaterial.visible === true ) {
|
|
|
+ object.material[ i ].visible = _originalVisibleTable[ object.material[ i ].uuid ];
|
|
|
|
|
|
- return originalMaterial;
|
|
|
+ }
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- return _invisibleMaterial;
|
|
|
+ object.material.visible = _originalVisibleTable[ object.material.uuid ];
|
|
|
|
|
|
}
|
|
|
|
|
@@ -761,11 +729,12 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
data = createCacheData();
|
|
|
data.material = createDeferredLightMaterial( light.userData.originalLight );
|
|
|
-
|
|
|
cache[ light.uuid ] = data;
|
|
|
|
|
|
}
|
|
|
|
|
|
+ data.used = true;
|
|
|
+
|
|
|
return data.material;
|
|
|
|
|
|
}
|
|
@@ -784,7 +753,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
function createDeferredLightMesh( light, geometry ) {
|
|
|
|
|
|
- var mesh = new THREE.Mesh( geometry, _invisibleMaterial );
|
|
|
+ var mesh = new THREE.Mesh( geometry, _tmpMaterial );
|
|
|
|
|
|
mesh.userData.originalLight = light;
|
|
|
|
|
@@ -973,21 +942,22 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- function saveOriginalMaterialAndCheckTransparency( object ) {
|
|
|
+ function saveOriginalOnBeforeRenderAndCheckTransparency( object ) {
|
|
|
|
|
|
if ( object.material === undefined ) return;
|
|
|
|
|
|
- _originalMaterialsTable[ object.uuid ] = object.material;
|
|
|
_originalOnBeforeRendersTable[ object.uuid ] = object.onBeforeRender;
|
|
|
|
|
|
// _hasTransparentObject is used only for Classic Deferred Rendering
|
|
|
if ( _hasTransparentObject || _lightPrePass ) return;
|
|
|
|
|
|
- if ( object.material.isMultiMaterial === true ) {
|
|
|
+ if ( ! object.visible ) return;
|
|
|
+
|
|
|
+ if ( Array.isArray( object.material ) ) {
|
|
|
|
|
|
- for ( var i = 0, il = object.material.materials.length; i < il; i ++ ) {
|
|
|
+ for ( var i = 0, il = object.material.length; i < il; i ++ ) {
|
|
|
|
|
|
- if ( object.material.materials[ i ].transparent === true ) {
|
|
|
+ if ( object.material[ i ].visible === true && object.material[ i ].transparent === true ) {
|
|
|
|
|
|
_hasTransparentObject = true;
|
|
|
break;
|
|
@@ -998,17 +968,16 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- if ( object.material.transparent === true ) _hasTransparentObject = true;
|
|
|
+ if ( object.material.visible === true && object.material.transparent === true ) _hasTransparentObject = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- function restoreOriginalMaterial( object ) {
|
|
|
+ function restoreOriginalOnBeforeRender( object ) {
|
|
|
|
|
|
if ( object.material === undefined ) return;
|
|
|
|
|
|
- object.material = _originalMaterialsTable[ object.uuid ];
|
|
|
object.onBeforeRender = _originalOnBeforeRendersTable[ object.uuid ];
|
|
|
|
|
|
}
|
|
@@ -1023,11 +992,12 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
data = createCacheData();
|
|
|
data.light = createDeferredLight( object );
|
|
|
-
|
|
|
_deferredLightsCache[ object.uuid ] = data;
|
|
|
|
|
|
}
|
|
|
|
|
|
+ data.used = true;
|
|
|
+
|
|
|
var light = data.light;
|
|
|
|
|
|
if ( light === null ) return;
|
|
@@ -1225,7 +1195,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
function cleanupTable( table ) {
|
|
|
|
|
|
- var keys = Object.keys( cache );
|
|
|
+ var keys = Object.keys( table );
|
|
|
|
|
|
for ( var i = 0, il = keys.length; i < il; i ++ ) {
|
|
|
|
|
@@ -1245,13 +1215,13 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
cleanupCache( _normalDepthShininessMaterialsCache );
|
|
|
cleanupCache( _colorMaterialsCache );
|
|
|
cleanupCache( _reconstructionMaterialsCache );
|
|
|
- cleanupCache( _invisibleMultiMaterialsCache );
|
|
|
cleanupCache( _classicDeferredLightMaterialsCache );
|
|
|
cleanupCache( _lightPrePassMaterialsCache );
|
|
|
cleanupCache( _deferredLightsCache );
|
|
|
|
|
|
cleanupTable( _originalMaterialsTable );
|
|
|
cleanupTable( _originalOnBeforeRendersTable );
|
|
|
+ cleanupTable( _originalVisibleTable );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1289,6 +1259,8 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
_compNormalDepth.render();
|
|
|
|
|
|
+ scene.traverse( restoreOriginalMaterial );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1317,6 +1289,8 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
_compColor.render();
|
|
|
|
|
|
+ scene.traverse( restoreOriginalMaterial );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1397,6 +1371,8 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
_gl.disable( _gl.STENCIL_TEST );
|
|
|
|
|
|
+ scene.traverse( restoreOriginalMaterial );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1426,7 +1402,8 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
if ( ! _lightPrePass && _hasTransparentObject ) {
|
|
|
|
|
|
- scene.traverse( setMaterialForwardRendering );
|
|
|
+ scene.traverse( setVisibleForForwardRendering );
|
|
|
+ scene.traverse( restoreOriginalOnBeforeRender );
|
|
|
|
|
|
_passForward.scene = scene;
|
|
|
_passForward.camera = camera;
|
|
@@ -1440,6 +1417,12 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
_compFinal.render();
|
|
|
|
|
|
+ if ( ! _lightPrePass && _hasTransparentObject ) {
|
|
|
+
|
|
|
+ scene.traverse( restoreVisible );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
// external APIs
|
|
@@ -1504,7 +1487,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
_hasTransparentObject = false;
|
|
|
|
|
|
- scene.traverse( saveOriginalMaterialAndCheckTransparency );
|
|
|
+ scene.traverse( saveOriginalOnBeforeRenderAndCheckTransparency );
|
|
|
|
|
|
updateDeferredCommonUniforms( camera );
|
|
|
|
|
@@ -1524,7 +1507,9 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
|
|
renderFinal( scene, camera );
|
|
|
|
|
|
- scene.traverse( restoreOriginalMaterial );
|
|
|
+ scene.traverse( restoreOriginalOnBeforeRender );
|
|
|
+
|
|
|
+ cleanupCaches();
|
|
|
|
|
|
scene.autoUpdate = currentSceneAutoUpdate;
|
|
|
this.renderer.autoClearColor = currentAutoClearColor;
|