浏览代码

Remove MultiMaterial from WebGLDeferredRenderer

Takahiro 8 年之前
父节点
当前提交
8349b07b5d
共有 1 个文件被更改,包括 119 次插入134 次删除
  1. 119 134
      examples/js/renderers/WebGLDeferredRenderer.js

+ 119 - 134
examples/js/renderers/WebGLDeferredRenderer.js

@@ -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;