Jelajahi Sumber

Merge pull request #7271 from mkkellogg/dev

Fix for #7260: PointLight shadows work properly only if shadow is applied to first light added to the scene.
Mr.doob 9 tahun lalu
induk
melakukan
80c63992c8

+ 5 - 0
src/renderers/WebGLRenderer.js

@@ -1989,6 +1989,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					if ( light instanceof THREE.PointLight ) {
 
+						// for point lights we set the shadow matrix to be a translation-only matrix
+						// equal to inverse of the light's position
+						_vector3.setFromMatrixPosition( light.matrixWorld ).negate();
+						light.shadowMatrix.identity().setPosition( _vector3 );
+
 						// for point lights we set the sign of the shadowDarkness uniform to be negative
 						uniforms.shadowDarkness.value[ j ] = - light.shadowDarkness;
 

+ 175 - 231
src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl

@@ -1,322 +1,266 @@
 #ifdef USE_SHADOWMAP
 
-	#ifdef SHADOWMAP_DEBUG
-
-		vec3 frustumColors[3];
-		frustumColors[0] = vec3( 1.0, 0.5, 0.0 );
-		frustumColors[1] = vec3( 0.0, 1.0, 0.8 );
-		frustumColors[2] = vec3( 0.0, 0.5, 1.0 );
-
-	#endif
-
-	float fDepth;
-	vec3 shadowColor = vec3( 1.0 );
+	vec3 shadowMask = vec3( 1.0 );
 
 	for( int i = 0; i < MAX_SHADOWS; i ++ ) {
-
-		// to save on uniform space, we use the sign of @shadowDarkness[ i ] to determine
-		// whether or not this light is a point light ( shadowDarkness[ i ] < 0 == point light)
-		bool isPointLight = shadowDarkness[ i ] < 0.0;
-
-		// get the real shadow darkness
-		float realShadowDarkness = abs( shadowDarkness[ i ] );
-
-		// for point lights, the uniform @vShadowCoord is re-purposed to hold
-		// the distance from the light to the world-space position of the fragment.
-		vec3 lightToPosition = vShadowCoord[ i ].xyz;
-
-		float texelSizeX =  1.0 / shadowMapSize[ i ].x;
+		
 		float texelSizeY =  1.0 / shadowMapSize[ i ].y;
 
-		vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;
-		float shadow = 0.0;
-
-		// if ( something && something ) breaks ATI OpenGL shader compiler
-		// if ( all( something, something ) ) using this instead
+		float shadow = 0.0;	
 
-		bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
-		bool inFrustum = all( inFrustumVec );
+#if defined( POINT_LIGHT_SHADOWS )
 
-		bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
-
-		bool frustumTest = all( frustumTestVec );
+		// to save on uniform space, we use the sign of @shadowDarkness[ i ] to determine
+		// whether or not this light is a point light ( shadowDarkness[ i ] < 0 == point light)
+		bool isPointLight = shadowDarkness[ i ] < 0.0;	
 
-		if ( frustumTest || isPointLight ) {			
+		if( isPointLight ) {
 
-			#if defined( SHADOWMAP_TYPE_PCF )
+			// get the real shadow darkness
+			float realShadowDarkness = abs( shadowDarkness[ i ] );
 
-				#if defined(POINT_LIGHT_SHADOWS)
+			// for point lights, the uniform @vShadowCoord is re-purposed to hold
+			// the distance from the light to the world-space position of the fragment.
+			vec3 lightToPosition = vShadowCoord[ i ].xyz;
 
-					if( isPointLight ) {
+	#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )
 
-						// bd3D = base direction 3D
-						vec3 bd3D = normalize( lightToPosition );
-						// dp = distance from light to fragment position
-						float dp = length( lightToPosition );
+			// bd3D = base direction 3D
+			vec3 bd3D = normalize( lightToPosition );
+			// dp = distance from light to fragment position
+			float dp = length( lightToPosition );
 
-						shadow = 0.0;						
+			// base measurement
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
 
-						// base measurement
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
+			// Dr = disk radius
 
-						// dr = disk radius
-						const float dr = 1.25;
-						// os = offset scale
-						float os = dr *  2.0 * texelSizeY;
+	#if defined( SHADOWMAP_TYPE_PCF )
+			const float Dr = 1.25;
+	#elif defined( SHADOWMAP_TYPE_PCF_SOFT )
+			const float Dr = 2.25;
+	#endif
 
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd0 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd1 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd2 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd3 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd4 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd5 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd6 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd7 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd8 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd9 * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			// os = offset scale
+			float os = Dr *  2.0 * texelSizeY;
 
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd10 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd11 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd12 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd13 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd14 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd15 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd16 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd17 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd18 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd19 * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			const vec3 Gsd = vec3( - 1, 0, 1 );
 
-						shadow /= 21.0;
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzy * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxy * os, texelSizeY ) ), shadowBias[ i ], shadow );
 
-					} else {
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxy * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzy * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zyz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xyz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zyx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xyx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
 
-				#endif
+			shadow *= realShadowDarkness * ( 1.0 / 21.0 );
 
-						// Percentage-close filtering
-						// (9 pixel kernel)
-						// http://fabiensanglard.net/shadowmappingPCF/
-						
-						/*
-								// nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
-								// must enroll loop manually
-							for ( float y = -1.25; y <= 1.25; y += 1.25 )
-								for ( float x = -1.25; x <= 1.25; x += 1.25 ) {
-									vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );
-											// doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup
-											//vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );
-									float fDepth = unpackDepth( rgbaDepth );
-									if ( fDepth < shadowCoord.z )
-										shadow += 1.0;
-							}
-							shadow /= 9.0;
-						*/
+	#else // no percentage-closer filtering:
 
-						shadowCoord.z += shadowBias[ i ];
+			vec3 bd3D = normalize( lightToPosition );
+			float dp = length( lightToPosition );
 
-						const float shadowDelta = 1.0 / 9.0;
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
 
-						float xPixelOffset = texelSizeX;
-						float yPixelOffset = texelSizeY;
+			shadow *= realShadowDarkness;
 
-						float dx0 = -1.25 * xPixelOffset;
-						float dy0 = -1.25 * yPixelOffset;
-						float dx1 = 1.25 * xPixelOffset;
-						float dy1 = 1.25 * yPixelOffset;
+	#endif
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+		} else {
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+#endif // POINT_LIGHT_SHADOWS
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			float texelSizeX =  1.0 / shadowMapSize[ i ].x;
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			// if ( something && something ) breaks ATI OpenGL shader compiler
+			// if ( all( something, something ) ) using this instead
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
+			bool inFrustum = all( inFrustumVec );
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			bool frustumTest = all( frustumTestVec );
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
-
-				#if defined(POINT_LIGHT_SHADOWS)
+			if( frustumTest ) {
 
+	#if defined( SHADOWMAP_TYPE_PCF )
+		
+				// Percentage-close filtering
+				// (9 pixel kernel)
+				// http://fabiensanglard.net/shadowmappingPCF/
+				
+				/*
+						// nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
+						// must enroll loop manually
+					for ( float y = -1.25; y <= 1.25; y += 1.25 )
+						for ( float x = -1.25; x <= 1.25; x += 1.25 ) {
+							vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );
+									// doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup
+									//vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );
+							float fDepth = unpackDepth( rgbaDepth );
+							if ( fDepth < shadowCoord.z )
+								shadow += 1.0;
 					}
+					shadow /= 9.0;
+				*/
 
-				#endif
-
-				shadowColor = shadowColor * vec3( ( 1.0 - realShadowDarkness * shadow ) );
-
-			#elif defined( SHADOWMAP_TYPE_PCF_SOFT )
+				shadowCoord.z += shadowBias[ i ];
 
-				#if defined(POINT_LIGHT_SHADOWS)
+				const float ShadowDelta = 1.0 / 9.0;
 
-					if( isPointLight ) {
+				float xPixelOffset = texelSizeX;
+				float yPixelOffset = texelSizeY;
 
-						// bd3D = base direction 3D
-						vec3 bd3D = normalize( lightToPosition );
-						// dp = distance from light to fragment position
-						float dp = length( lightToPosition );
+				float dx0 = - 1.25 * xPixelOffset;
+				float dy0 = - 1.25 * yPixelOffset;
+				float dx1 = 1.25 * xPixelOffset;
+				float dy1 = 1.25 * yPixelOffset;
 
-						shadow = 0.0;						
+				float fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						// base measurement
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						// dr = disk radius
-						const float dr = 2.25;
-						// os = offset scale
-						float os = dr *  2.0 * texelSizeY;
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd0 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd1 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd2 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd3 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd4 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd5 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd6 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd7 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd8 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd9 * os, texelSizeY ) ), shadowBias[ i ], shadow );
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd10 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd11 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd12 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd13 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd14 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd15 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd16 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd17 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd18 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd19 * os, texelSizeY ) ), shadowBias[ i ], shadow );
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						shadow /= 21.0;
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-					} else {
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-				#endif
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						// Percentage-close filtering
-						// (9 pixel kernel)
-						// http://fabiensanglard.net/shadowmappingPCF/
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						shadowCoord.z += shadowBias[ i ];
+				shadow *= shadowDarkness[ i ];
 
-						float xPixelOffset = texelSizeX;
-						float yPixelOffset = texelSizeY;
+	#elif defined( SHADOWMAP_TYPE_PCF_SOFT )				
 
-						float dx0 = -1.0 * xPixelOffset;
-						float dy0 = -1.0 * yPixelOffset;
-						float dx1 = 1.0 * xPixelOffset;
-						float dy1 = 1.0 * yPixelOffset;
+				// Percentage-close filtering
+				// (9 pixel kernel)
+				// http://fabiensanglard.net/shadowmappingPCF/
 
-						mat3 shadowKernel;
-						mat3 depthKernel;
+				shadowCoord.z += shadowBias[ i ];
 
-						depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
-						depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
-						depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
-						depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
-						depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
-						depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
-						depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
-						depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
-						depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
+				float xPixelOffset = texelSizeX;
+				float yPixelOffset = texelSizeY;
 
-						vec3 shadowZ = vec3( shadowCoord.z );
-						shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));
-						shadowKernel[0] *= vec3(0.25);
+				float dx0 = - 1.0 * xPixelOffset;
+				float dy0 = - 1.0 * yPixelOffset;
+				float dx1 = 1.0 * xPixelOffset;
+				float dy1 = 1.0 * yPixelOffset;
 
-						shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));
-						shadowKernel[1] *= vec3(0.25);
+				mat3 shadowKernel;
+				mat3 depthKernel;
 
-						shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));
-						shadowKernel[2] *= vec3(0.25);
+				depthKernel[ 0 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
+				depthKernel[ 0 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
+				depthKernel[ 0 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
+				depthKernel[ 1 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
+				depthKernel[ 1 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
+				depthKernel[ 1 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
+				depthKernel[ 2 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
+				depthKernel[ 2 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
+				depthKernel[ 2 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
 
-						vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );
+				vec3 shadowZ = vec3( shadowCoord.z );
+				shadowKernel[ 0 ] = vec3( lessThan( depthKernel[ 0 ], shadowZ ) );
+				shadowKernel[ 0 ] *= vec3( 0.25 );
 
-						shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );
-						shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );
+				shadowKernel[ 1 ] = vec3( lessThan( depthKernel[ 1 ], shadowZ ) );
+				shadowKernel[ 1 ] *= vec3( 0.25 );
 
-						vec4 shadowValues;
-						shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );
-						shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );
-						shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );
-						shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );
-
-						shadow = dot( shadowValues, vec4( 1.0 ) );
-
-				#if defined(POINT_LIGHT_SHADOWS)
-					
-					}
+				shadowKernel[ 2 ] = vec3( lessThan( depthKernel[ 2 ], shadowZ ) );
+				shadowKernel[ 2 ] *= vec3( 0.25 );
 
-				#endif
+				vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[ i ].xy );
 
-				shadowColor = shadowColor * vec3( ( 1.0 - realShadowDarkness * shadow ) );
+				shadowKernel[ 0 ] = mix( shadowKernel[ 1 ], shadowKernel[ 0 ], fractionalCoord.x );
+				shadowKernel[ 1 ] = mix( shadowKernel[ 2 ], shadowKernel[ 1 ], fractionalCoord.x );
 
-			#else
+				vec4 shadowValues;
+				shadowValues.x = mix( shadowKernel[ 0 ][ 1 ], shadowKernel[ 0 ][ 0 ], fractionalCoord.y );
+				shadowValues.y = mix( shadowKernel[ 0 ][ 2 ], shadowKernel[ 0 ][ 1 ], fractionalCoord.y );
+				shadowValues.z = mix( shadowKernel[ 1 ][ 1 ], shadowKernel[ 1 ][ 0 ], fractionalCoord.y );
+				shadowValues.w = mix( shadowKernel[ 1 ][ 2 ], shadowKernel[ 1 ][ 1 ], fractionalCoord.y );
 
-				#if defined(POINT_LIGHT_SHADOWS)
+				shadow = dot( shadowValues, vec4( 1.0 ) ) * shadowDarkness[ i ];
 
-					if( isPointLight ) {
+	#else // no percentage-closer filtering:
+				
+				shadowCoord.z += shadowBias[ i ];
 
-						vec3 bd3D = normalize( lightToPosition );
-						float dp = length( lightToPosition );
+				vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
+				float fDepth = unpackDepth( rgbaDepth );
 
-						float shadow = 0.0;
+				if ( fDepth < shadowCoord.z )
+					shadow = shadowDarkness[ i ];				
 
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
+	#endif
 
-						shadowColor = shadowColor * vec3( 1.0 - realShadowDarkness * shadow );
+			}
 
-					} else {
+#ifdef SHADOWMAP_DEBUG
 
-				#endif
-						shadowCoord.z += shadowBias[ i ];
+			if ( inFrustum ) {
 
-						vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
-						float fDepth = unpackDepth( rgbaDepth );
+				if ( i == 0 ) {
 
-						if ( fDepth < shadowCoord.z )
+					outgoingLight *= vec3( 1.0, 0.5, 0.0 );
 
-						// spot with multiple shadows is darker
+				} else if ( i == 1 ) {
 
-						shadowColor = shadowColor * vec3( 1.0 - realShadowDarkness );
+					outgoingLight *= vec3( 0.0, 1.0, 0.8 );
 
-						// spot with multiple shadows has the same color as single shadow spot
+				} else {
 
-						// 	shadowColor = min( shadowColor, vec3( realShadowDarkness ) );
+					outgoingLight *= vec3( 0.0, 0.5, 1.0 );
 
-				#if defined(POINT_LIGHT_SHADOWS)
+				}
 
-					}
+			}
 
-				#endif
+#endif
 
-			#endif
+#if defined( POINT_LIGHT_SHADOWS )
 
 		}
 
+#endif
 
-		#ifdef SHADOWMAP_DEBUG
-
-			if ( inFrustum ) outgoingLight *= frustumColors[ i ];
-
-		#endif
+		shadowMask = shadowMask * vec3( 1.0 - shadow );	
 
 	}
 
-	outgoingLight = outgoingLight * shadowColor;
+	outgoingLight = outgoingLight * shadowMask;
 
 #endif

+ 0 - 24
src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl

@@ -101,30 +101,6 @@
 
 		}
 
-		// gsdXX = grid sampling disk XX
-		// these values are used when rendering PCF shadow maps for point lights
-		
-		const vec3 gsd0 = vec3( 1, 1, 1 );
-		const vec3 gsd1 = vec3( 1, - 1, 1 );
-		const vec3 gsd2 = vec3( - 1, - 1, 1 );
-		const vec3 gsd3 = vec3( - 1, 1, 1 );
-		const vec3 gsd4 = vec3( 1, 1, - 1 );
-		const vec3 gsd5 = vec3( 1, - 1, - 1 );
-		const vec3 gsd6 = vec3( - 1, - 1, - 1 );
-		const vec3 gsd7 = vec3( -1, 1, - 1 );
-		const vec3 gsd8 = vec3( 1, 1, 0 );
-		const vec3 gsd9 = vec3( 1, - 1, 0 );
-		const vec3 gsd10 = vec3( - 1, - 1, 0 );
-		const vec3 gsd11 = vec3( - 1, 1, 0 );
-		const vec3 gsd12 = vec3( 1, 0, 1 );
-		const vec3 gsd13 = vec3( - 1, 0, 1 );
-		const vec3 gsd14 = vec3( 1, 0, - 1 );
-		const vec3 gsd15 = vec3( - 1, 0, - 1 );
-		const vec3 gsd16 = vec3( 0, 1, 1 );
-		const vec3 gsd17 = vec3( 0, - 1, 1 );
-		const vec3 gsd18 = vec3( 0, - 1, - 1 );
-		const vec3 gsd19 = vec3( 0, 1, - 1 );
-
 	#endif
 
 #endif

+ 0 - 32
src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl

@@ -2,40 +2,8 @@
 
 	for( int i = 0; i < MAX_SHADOWS; i ++ ) {
 
-		#if defined(POINT_LIGHT_SHADOWS)
-
-			// if shadowDarkness[ i ] < 0.0, that means we have a point light with a cube
-			// shadow map
-			if( shadowDarkness[ i ] < 0.0 ) {
-
-				// calculate vector from light to vertex in view space
-
-				vec3 fromLight = mvPosition.xyz - pointLightPosition[ i ];
-
-				// Transform 'fromLight' into world space by multiplying it on the left
-				// side of 'viewMatrix'. This is equivalent to multiplying it on the right
-				// side of the transpose of 'viewMatrix'. Since 'viewMatrix' is orthogonal, 
-				// its transpose is the same as its inverse.
-
-				fromLight = fromLight * mat3( viewMatrix );
-
-				// We repurpose vShadowCoord to hold the distance in world space from the
-				// light to the vertex. This value will be interpolated correctly in the fragment shader.
-
-				vShadowCoord[ i ] = vec4( fromLight, 1.0 );
-
-			} else {
-
-				vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;
-
-			}
-
-		#else
-
 			vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;
 
-		#endif
-
 	}
 
 #endif

+ 12 - 22
src/renderers/webgl/WebGLShadowMap.js

@@ -100,27 +100,15 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 		var faceCount, isPointLight;
 
 		if ( scope.enabled === false ) return;
-		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
-
-		// set GL state for depth map
+		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;	
 
+		// Set GL state for depth map. 
 		_gl.clearColor( 1, 1, 1, 1 );
 		_state.disable( _gl.BLEND );
-
 		_state.enable( _gl.CULL_FACE );
 		_gl.frontFace( _gl.CCW );
-
-		if ( scope.cullFace === THREE.CullFaceFront ) {
-
-			_gl.cullFace( _gl.FRONT );
-
-		} else {
-
-			_gl.cullFace( _gl.BACK );
-
-		}
-
-		_state.setDepthTest( true );
+		_gl.cullFace( scope.cullFace === THREE.CullFaceFront ? _gl.FRONT : _gl.BACK );
+		_state.setDepthTest( true );			
 
 		// save the existing viewport so it can be restored later
 		_renderer.getViewport( _vector4 );
@@ -131,6 +119,8 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 			var light = _lights[ i ];
 
+			if ( ! light.castShadow ) continue;
+
 			if ( light instanceof THREE.PointLight ) {
 
 				faceCount = 6;
@@ -172,8 +162,6 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 			}
 
-			if ( ! light.castShadow ) continue;
-
 			if ( ! light.shadowMap ) {
 
 				var shadowFilter = THREE.LinearFilter;
@@ -321,15 +309,17 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 			}
 
-			_renderer.setViewport( _vector4.x, _vector4.y, _vector4.z, _vector4.w );
+			//We must call _renderer.resetGLState() at the end of each iteration of
+			// the light loop in order to force material updates for each light.
+			_renderer.resetGLState();			
 
 		}
 
-		// restore GL state
+		_renderer.setViewport( _vector4.x, _vector4.y, _vector4.z, _vector4.w );
 
+		// Restore GL state. 
 		var clearColor = _renderer.getClearColor(),
 		clearAlpha = _renderer.getClearAlpha();
-
 		_renderer.setClearColor( clearColor, clearAlpha );
 		_state.enable( _gl.BLEND );
 
@@ -339,7 +329,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 		}
 
-		_renderer.resetGLState();
+		_renderer.resetGLState();			
 
 		scope.needsUpdate = false;