Browse Source

Merge pull request #7236 from tschw/DRYinShadowMap

ShadowMap: Refactored repetitive code.
Mr.doob 10 years ago
parent
commit
001e5d463e

+ 5 - 5
src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl

@@ -51,7 +51,7 @@
 
 
 						float cubeTexelSize = 1.0 / ( shadowMapSize[ i ].x * 0.25 );
 						float cubeTexelSize = 1.0 / ( shadowMapSize[ i ].x * 0.25 );
 						vec3 baseDirection3D = normalize( lightToPosition );
 						vec3 baseDirection3D = normalize( lightToPosition );
-						vec2 baseDirection2D = cubeToUV( baseDirection3D, texelSizeX, texelSizeY );
+						vec2 baseDirection2D = cubeToUV( baseDirection3D, texelSizeY );
 
 
 						initGridSamplingDisk();
 						initGridSamplingDisk();
 
 
@@ -71,7 +71,7 @@
 						 
 						 
 							vec3 offset = gridSamplingDisk[ s ] * diskRadius * cubeTexelSize;
 							vec3 offset = gridSamplingDisk[ s ] * diskRadius * cubeTexelSize;
 							vec3 adjustedBaseDirection3D = baseDirection3D + offset;
 							vec3 adjustedBaseDirection3D = baseDirection3D + offset;
-							vec2 adjustedBaseDirection2D = cubeToUV( adjustedBaseDirection3D, texelSizeX, texelSizeY );
+							vec2 adjustedBaseDirection2D = cubeToUV( adjustedBaseDirection3D, texelSizeY );
 							dist = unpack1K( texture2D( shadowMap[ i ],  adjustedBaseDirection2D ) ) + shadowBias[ i ];
 							dist = unpack1K( texture2D( shadowMap[ i ],  adjustedBaseDirection2D ) ) + shadowBias[ i ];
 							if ( curDistance >= dist )
 							if ( curDistance >= dist )
 								shadow += 1.0;
 								shadow += 1.0;
@@ -159,7 +159,7 @@
 
 
 						float cubeTexelSize = 1.0 / ( shadowMapSize[ i ].x * 0.25 );
 						float cubeTexelSize = 1.0 / ( shadowMapSize[ i ].x * 0.25 );
 						vec3 baseDirection3D = normalize( lightToPosition );
 						vec3 baseDirection3D = normalize( lightToPosition );
-						vec2 baseDirection2D = cubeToUV( baseDirection3D, texelSizeX, texelSizeY );
+						vec2 baseDirection2D = cubeToUV( baseDirection3D, texelSizeY );
 
 
 						initGridSamplingDisk();
 						initGridSamplingDisk();
 
 
@@ -179,7 +179,7 @@
 
 
 							vec3 offset = gridSamplingDisk[ s ] * diskRadius * cubeTexelSize;
 							vec3 offset = gridSamplingDisk[ s ] * diskRadius * cubeTexelSize;
 							vec3 adjustedBaseDirection3D = baseDirection3D + offset;
 							vec3 adjustedBaseDirection3D = baseDirection3D + offset;
-							vec2 adjustedBaseDirection2D = cubeToUV( adjustedBaseDirection3D, texelSizeX, texelSizeY );
+							vec2 adjustedBaseDirection2D = cubeToUV( adjustedBaseDirection3D, texelSizeY );
 							dist = unpack1K( texture2D( shadowMap[ i ],  adjustedBaseDirection2D ) ) + shadowBias[ i ];
 							dist = unpack1K( texture2D( shadowMap[ i ],  adjustedBaseDirection2D ) ) + shadowBias[ i ];
 							if ( curDistance >= dist )
 							if ( curDistance >= dist )
 								shadow += 1.0;
 								shadow += 1.0;
@@ -258,7 +258,7 @@
 					if( isPointLight ) {
 					if( isPointLight ) {
 
 
 						vec3 baseDirection3D = normalize( lightToPosition );
 						vec3 baseDirection3D = normalize( lightToPosition );
-						vec2 baseDirection2D = cubeToUV( baseDirection3D, texelSizeX, texelSizeY );
+						vec2 baseDirection2D = cubeToUV( baseDirection3D, texelSizeY );
 						vec4 data = texture2D( shadowMap[ i ],  baseDirection2D );
 						vec4 data = texture2D( shadowMap[ i ],  baseDirection2D );
 						float dist = unpack1K( data ) + shadowBias[ i ];
 						float dist = unpack1K( data ) + shadowBias[ i ];
 						if ( length( lightToPosition ) >= dist)
 						if ( length( lightToPosition ) >= dist)

+ 26 - 28
src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl

@@ -1,5 +1,5 @@
 #ifdef USE_SHADOWMAP
 #ifdef USE_SHADOWMAP
-	
+
 	uniform sampler2D shadowMap[ MAX_SHADOWS ];
 	uniform sampler2D shadowMap[ MAX_SHADOWS ];
 	uniform vec2 shadowMapSize[ MAX_SHADOWS ];
 	uniform vec2 shadowMapSize[ MAX_SHADOWS ];
 
 
@@ -19,32 +19,30 @@
 	#if defined(POINT_LIGHT_SHADOWS)
 	#if defined(POINT_LIGHT_SHADOWS)
 
 
 		float unpack1K ( vec4 color ) {
 		float unpack1K ( vec4 color ) {
-		
+
 			const vec4 bitSh = vec4( 1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0 );
 			const vec4 bitSh = vec4( 1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0 );
 			return dot( color, bitSh ) * 1000.0;
 			return dot( color, bitSh ) * 1000.0;
-			
+
 		}
 		}
 
 
-		/**
-		*  cubeToUV() maps a 3D direction vector suitable for cube texture mapping to a 2D
-		*  vector suitable for 2D texture mapping. This code uses the following layout for the
-		*  2D texture:		
-		*  
-		*  xzXZ
-		*   y Y
-		*
-		*  Y - Positive y direction
-		*  y - Negative y direction
-		*  X - Positive x direction
-		*  x - Negative x direction
-		*  Z - Positive z direction
-		*  z - Negative z direction
-		*
-		*  Alternate code for a horizontal cross layout can be found here:
-		*  https://gist.github.com/tschw/da10c43c467ce8afd0c4
-		*/
-
-		vec2 cubeToUV( vec3 v, float texelSizeX, float texelSizeY ) {
+		// cubeToUV() maps a 3D direction vector suitable for cube texture mapping to a 2D
+		// vector suitable for 2D texture mapping. This code uses the following layout for the
+		// 2D texture:
+		//
+		// xzXZ
+		//  y Y
+		//
+		// Y - Positive y direction
+		// y - Negative y direction
+		// X - Positive x direction
+		// x - Negative x direction
+		// Z - Positive z direction
+		// z - Negative z direction
+		//
+		// Source and test bed:
+		// https://gist.github.com/tschw/da10c43c467ce8afd0c4
+
+		vec2 cubeToUV( vec3 v, float texelSizeY ) {
 
 
 			// Number of texels to avoid at the edge of each square
 			// Number of texels to avoid at the edge of each square
 
 
@@ -95,15 +93,15 @@
 			// scale := 0.5 / dim
 			// scale := 0.5 / dim
 			// translate := ( center + 0.5 ) / dim
 			// translate := ( center + 0.5 ) / dim
 			return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );
 			return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );
-			
+
 		}
 		}
 
 
 		vec3 gridSamplingDisk[ 20 ];
 		vec3 gridSamplingDisk[ 20 ];
 		bool gridSamplingInitialized = false;
 		bool gridSamplingInitialized = false;
 
 
-		void initGridSamplingDisk(){
+		void initGridSamplingDisk() {
 
 
-			if( gridSamplingInitialized ){
+			if( gridSamplingInitialized ) {
 
 
 				return;
 				return;
 
 
@@ -131,9 +129,9 @@
 			gridSamplingDisk[19] = vec3(0, 1, -1);
 			gridSamplingDisk[19] = vec3(0, 1, -1);
 
 
 			gridSamplingInitialized = true;
 			gridSamplingInitialized = true;
-			
+
 		}
 		}
 
 
 	#endif
 	#endif
 
 
-#endif
+#endif

+ 72 - 123
src/renderers/webgl/WebGLShadowMap.js

@@ -16,15 +16,20 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 	_lookTarget = new THREE.Vector3(),
 	_lookTarget = new THREE.Vector3(),
 	_lightPositionWorld = new THREE.Vector3(),
 	_lightPositionWorld = new THREE.Vector3(),
 
 
-	_renderList = [];
+	_renderList = [],
 
 
-	var _depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin,
-	_distanceMaterial, _distanceMaterialMorph, _distanceMaterialSkin, _distanceMaterialMorphSkin;
+	_MorphingFlag = 1,
+	_SkinningFlag = 2,
 
 
-	var cubeDirections = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( - 1, 0, 0 ), new THREE.Vector3( 0, 0, 1 ), 
+	_NumberOfMaterialVariants = _MorphingFlag | _SkinningFlag,
+
+	_depthMaterials = new Array( _NumberOfMaterialVariants ),
+	_distanceMaterials = new Array( _NumberOfMaterialVariants );
+
+	var cubeDirections = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( - 1, 0, 0 ), new THREE.Vector3( 0, 0, 1 ),
 						   new THREE.Vector3( 0, 0, - 1 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, - 1, 0 ) ];
 						   new THREE.Vector3( 0, 0, - 1 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, - 1, 0 ) ];
 
 
-	var cubeUps = [ new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 1, 0 ), 
+	var cubeUps = [ new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 1, 0 ),
 					new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ),	new THREE.Vector3( 0, 0, - 1 ) ];
 					new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ),	new THREE.Vector3( 0, 0, - 1 ) ];
 
 
 	var cube2DViewPorts = [ new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4(),
 	var cube2DViewPorts = [ new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4(),
@@ -37,75 +42,41 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 	var depthShader = THREE.ShaderLib[ "depthRGBA" ];
 	var depthShader = THREE.ShaderLib[ "depthRGBA" ];
 	var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
 	var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
 
 
-	_depthMaterial = new THREE.ShaderMaterial( {
-		uniforms: depthUniforms,
-		vertexShader: depthShader.vertexShader,
-		fragmentShader: depthShader.fragmentShader
-	 } );
-
-	_depthMaterialMorph = new THREE.ShaderMaterial( {
-		uniforms: depthUniforms,
-		vertexShader: depthShader.vertexShader,
-		fragmentShader: depthShader.fragmentShader,
-		morphTargets: true
-	} );
-
-	_depthMaterialSkin = new THREE.ShaderMaterial( {
-		uniforms: depthUniforms,
-		vertexShader: depthShader.vertexShader,
-		fragmentShader: depthShader.fragmentShader,
-		skinning: true
-	} );
-
-	_depthMaterialMorphSkin = new THREE.ShaderMaterial( {
-		uniforms: depthUniforms,
-		vertexShader: depthShader.vertexShader,
-		fragmentShader: depthShader.fragmentShader,
-		morphTargets: true,
-		skinning: true
-	} );
-
-	_depthMaterial._shadowPass = true;
-	_depthMaterialMorph._shadowPass = true;
-	_depthMaterialSkin._shadowPass = true;
-	_depthMaterialMorphSkin._shadowPass = true;
-
-
 	var distanceShader = THREE.ShaderLib[ "distanceRGBA" ];
 	var distanceShader = THREE.ShaderLib[ "distanceRGBA" ];
 	var distanceUniforms = THREE.UniformsUtils.clone( distanceShader.uniforms );
 	var distanceUniforms = THREE.UniformsUtils.clone( distanceShader.uniforms );
 
 
-	_distanceMaterial = new THREE.ShaderMaterial( {
-		uniforms: distanceUniforms,
-		vertexShader: distanceShader.vertexShader,
-		fragmentShader: distanceShader.fragmentShader
-	 } );
-
-	_distanceMaterialMorph = new THREE.ShaderMaterial( {
-		uniforms: distanceUniforms,
-		vertexShader: distanceShader.vertexShader,
-		fragmentShader: distanceShader.fragmentShader,
-		morphTargets: true
-	} );
-
-	_distanceMaterialSkin = new THREE.ShaderMaterial( {
-		uniforms: distanceUniforms,
-		vertexShader: distanceShader.vertexShader,
-		fragmentShader: distanceShader.fragmentShader,
-		skinning: true
-	} );
-
-	_distanceMaterialMorphSkin = new THREE.ShaderMaterial( {
-		uniforms: distanceUniforms,
-		vertexShader: distanceShader.vertexShader,
-		fragmentShader: distanceShader.fragmentShader,
-		morphTargets: true,
-		skinning: true
-	} );
-
-	_distanceMaterial._shadowPass = true;
-	_distanceMaterialMorph._shadowPass = true;
-	_distanceMaterialSkin._shadowPass = true;
-	_distanceMaterialMorphSkin._shadowPass = true;
+	for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
+
+		var useMorphing = ( i & _MorphingFlag ) !== 0;
+	    var useSkinning = ( i & _SkinningFlag ) !== 0;
+
+
+		var depthMaterial = new THREE.ShaderMaterial( {
+			uniforms: depthUniforms,
+			vertexShader: depthShader.vertexShader,
+			fragmentShader: depthShader.fragmentShader,
+			morphTargets: useMorphing,
+			skinning: useSkinning
+		} );
+
+		depthMaterial._shadowPass = true;
+
+		_depthMaterials[ i ] = depthMaterial;
+
+
+		var distanceMaterial = new THREE.ShaderMaterial( {
+			uniforms: distanceUniforms,
+			vertexShader: distanceShader.vertexShader,
+			fragmentShader: distanceShader.fragmentShader,
+			morphTargets: useMorphing,
+			skinning: useSkinning
+		} );
+
+		distanceMaterial._shadowPass = true;
+
+		_distanceMaterials[ i ] = distanceMaterial;
+
+	}
 
 
 	//
 	//
 
 
@@ -160,22 +131,18 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 				var vpWidth = light.shadowMapWidth / 4.0;
 				var vpWidth = light.shadowMapWidth / 4.0;
 				var vpHeight = light.shadowMapHeight / 2.0;
 				var vpHeight = light.shadowMapHeight / 2.0;
 
 
-				/*
-				*
-				* These viewports map a cube-map onto a 2D texture with the
-				* following orientation:
-				*
-				*  xzXZ
-				*   y Y
-				*
-				*  Y - Positive y direction
-				*  y - Negative y direction
-				*  X - Positive x direction
-				*  x - Negative x direction
-				*  Z - Positive z direction
-				*  z - Negative z direction
-				*
-				*/
+				// These viewports map a cube-map onto a 2D texture with the
+				// following orientation:
+				//
+				//  xzXZ
+				//   y Y
+				//
+				// X - Positive x direction
+				// x - Negative x direction
+				// Y - Positive y direction
+				// y - Negative y direction
+				// Z - Positive z direction
+				// z - Negative z direction
 
 
 				// positive X
 				// positive X
 				cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
 				cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
@@ -203,7 +170,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 
 				var shadowFilter = THREE.LinearFilter;
 				var shadowFilter = THREE.LinearFilter;
 
 
-				if ( scope.type === THREE.PCFSoftShadowMap) {
+				if ( scope.type === THREE.PCFSoftShadowMap ) {
 
 
 					shadowFilter = THREE.NearestFilter;
 					shadowFilter = THREE.NearestFilter;
 
 
@@ -258,7 +225,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 			_renderer.getViewport( _vector4 );
 			_renderer.getViewport( _vector4 );
 
 
 			_renderer.setRenderTarget( shadowMap );
 			_renderer.setRenderTarget( shadowMap );
-			_renderer.clear();		
+			_renderer.clear();
 
 
 			// render shadow map for each cube face (if omni-directional) or
 			// render shadow map for each cube face (if omni-directional) or
 			// run a single pass if not
 			// run a single pass if not
@@ -377,48 +344,34 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 
 		var geometry = object.geometry;
 		var geometry = object.geometry;
 
 
-		var useMorphing = geometry.morphTargets !== undefined && geometry.morphTargets.length > 0 && material.morphTargets;
-		var useSkinning = object instanceof THREE.SkinnedMesh && material.skinning;
-
-		var newMaterial;
+		var newMaterial = null;
 
 
-		var depthMaterial = _depthMaterial;
-		var depthMaterialMorph = _depthMaterialMorph;
-		var depthMaterialSkin = _depthMaterialSkin;
-		var depthMaterialMorphSkin = _depthMaterialMorphSkin;
+		var materialVariants = _depthMaterials;
+		var customMaterial = object.customDepthMaterial;
 
 
 		if ( isPointLight ) {
 		if ( isPointLight ) {
 
 
-			depthMaterial = _distanceMaterial;
-			depthMaterialMorph = _distanceMaterialMorph;
-			depthMaterialSkin = _distanceMaterialSkin;
-			depthMaterialMorphSkin = _distanceMaterialMorphSkin;
+			materialVariants = _distanceMaterials;
+			customMaterial = object.customDistanceMaterial;
 
 
 		}
 		}
 
 
-		if ( object.customDepthMaterial || object.customDistanceMaterial ) {
+		if ( ! customMaterial ) {
 
 
-			if ( isPointLight ) {
+			var useMorphing = geometry.morphTargets !== undefined &&
+					geometry.morphTargets.length > 0 && material.morphTargets;
 
 
-				newMaterial = object.customDistanceMaterial;
-
-			} else {
-
-				newMaterial = object.customDepthMaterial;
-
-			}
+			var useSkinning = object instanceof THREE.SkinnedMesh && material.skinning;
 
 
-		} else if ( useSkinning ) {
+			var variantIndex = 0;
+			if ( useMorphing ) variantIndex |= _MorphingFlag;
+			if ( useSkinning ) variantIndex |= _SkinningFlag;
 
 
-			newMaterial = useMorphing ? depthMaterialMorphSkin : depthMaterialSkin;
-
-		} else if ( useMorphing ) {
-
-			newMaterial = depthMaterialMorph;
+			newMaterial = materialVariants[ variantIndex ];
 
 
 		} else {
 		} else {
 
 
-			newMaterial = depthMaterial;
+			newMaterial = customMaterial;
 
 
 		}
 		}
 
 
@@ -426,13 +379,9 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 		newMaterial.wireframe = material.wireframe;
 		newMaterial.wireframe = material.wireframe;
 		newMaterial.wireframeLinewidth = material.wireframeLinewidth;
 		newMaterial.wireframeLinewidth = material.wireframeLinewidth;
 
 
-		if ( isPointLight ) {
-
-			if ( newMaterial.uniforms.lightPos ) {
-
-				newMaterial.uniforms.lightPos.value.copy( lightPositionWorld );
+		if ( isPointLight && newMaterial.uniforms.lightPos !== undefined ) {
 
 
-			}
+			newMaterial.uniforms.lightPos.value.copy( lightPositionWorld );
 
 
 		}
 		}