 			return blockerDepthSum / float( numBlockers );
 		}
 
-		float percentCloserFilter( sampler2D shadowMap, vec2 uv, float zReceiverClipSpace, float filterRadius ) {
+		float percentCloserFilter( sampler2D shadowMap, const in vec2 uv, const in float zReceiverClipSpace, const in float filterRadius ) {
 			float sum = 0.0;
 
-			for( int i = 0; i < PCSS_NUM_POISSON_SAMPLES; i ++ ) {
-
-				vec2 offset = poissonDisk[i] * filterRadius;
-
-				float depth1 = unpackRGBAToDepth( texture2D( shadowMap, uv + offset ) );
-				if( zReceiverClipSpace <= depth1 ) sum += 1.0;
-
-				float depth2 = unpackRGBAToDepth( texture2D( shadowMap, uv - offset.yx ) );
-				if( zReceiverClipSpace <= depth2 ) sum += 1.0;
+			for( int j = 0; j < PCSS_QUALITY_LEVEL; j ++ ) {
+
+				mat2 poissonRotation = createRotationMatrix( uv.yx + vec2( 0.12, 0.30 ) * float( j ) );
+
+				for( int i = 0; i < PCSS_NUM_POISSON_SAMPLES; i ++ ) {
+
+					vec2 uvOffset = ( poissonDisk[i] * poissonRotation ) * filterRadius;
+
+					float depth = unpackRGBAToDepth( texture2D( shadowMap, uv + uvOffset ) );
+					if( zReceiverClipSpace <= depth ) sum += 1.0;
+
+					depth = unpackRGBAToDepth( texture2D( shadowMap, uv - uvOffset ) );
+					if( zReceiverClipSpace <= depth ) sum += 1.0;
+
+				}
 
 			}
 
-			return sum / ( 2.0 * float( PCSS_NUM_POISSON_SAMPLES ) );
+			return sum / ( 2.0 * float( PCSS_NUM_POISSON_SAMPLES * PCSS_QUALITY_LEVEL ) );
 		}
 
 		float percentCloserSoftShadow( sampler2D shadowMap, const in float shadowRadius, const in vec2 shadowCameraNearFar, const in vec4 coords ) {

	#endif

	#if defined( SHADOWMAP_TYPE_PCSS )
		#define PCSS_NUM_POISSON_SAMPLES 16
		#define PCSS_ROTATE_POISSON_SAMPLES 1

		#define LIGHT_FRUSTUM_WIDTH 3.75 // remove me


			float blockerDepthSum = 0.0;
			int numBlockers = 0;

			for( int j = 0; j < PCSS_QUALITY_LEVEL; j ++ ) {

				mat2 poissonRotation = createRotationMatrix( uv + vec2( 0.33, 0.66 ) * float( j ) );

				for( int i = 0; i < PCSS_NUM_POISSON_SAMPLES; i++ ) {

					vec2 uvOffset = ( poissonDisk[i] * poissonRotation ) * searchRadius;

					float shadowMapDepth = unpackRGBAToDepth( texture2D( shadowMap, uv + uvOffset ) );
					if ( shadowMapDepth < zReceiverClipSpace ) {
						blockerDepthSum += shadowMapDepth;
						numBlockers ++;
					}

				}

			}
