Browse Source

Added handling of multiple shadows. Added matrix4 array and texture array uniform types.

alteredq 14 years ago
parent
commit
ae2357a099
4 changed files with 293 additions and 196 deletions
  1. 100 101
      build/Three.js
  2. 49 50
      build/custom/ThreeWebGL.js
  3. 109 26
      src/renderers/WebGLRenderer.js
  4. 35 19
      src/renderers/WebGLShaders.js

File diff suppressed because it is too large
+ 100 - 101
build/Three.js


File diff suppressed because it is too large
+ 49 - 50
build/custom/ThreeWebGL.js


+ 109 - 26
src/renderers/WebGLRenderer.js

@@ -103,11 +103,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 	this.shadowCameraFar = 5000;
 	this.shadowCameraFov = 50;
 
-	this.shadowMap = null;
+	this.shadowMap = [];
 	this.shadowMapEnabled = false;
 
 	var _cameraLight,
-		_shadowMatrix = new THREE.Matrix4();
+		_shadowMatrix = [];
 
 	var depthShader = THREE.ShaderLib[ "depthRGBA" ];
 	var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
@@ -2567,8 +2567,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( uniforms.shadowMatrix ) {
 
-			uniforms.shadowMatrix.value.copy( _shadowMatrix );
-			uniforms.shadowMap.texture = _this.shadowMap;
+			for ( var i = 0; i < _shadowMatrix.length; i ++ ) {
+
+				uniforms.shadowMatrix.value[ i ] = _shadowMatrix[ i ];
+				uniforms.shadowMap.texture[ i ] = _this.shadowMap[ i ];
+
+
+			}
 
 			uniforms.shadowDarkness.value = _this.shadowMapDarkness;
 			uniforms.shadowBias.value = _this.shadowMapBias;
@@ -2579,7 +2584,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	this.initMaterial = function ( material, lights, fog, object ) {
 
-		var u, a, identifiers, i, parameters, maxLightCount, maxBones, shaderID;
+		var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
 
 		if ( material instanceof THREE.MeshDepthMaterial ) {
 
@@ -2626,6 +2631,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		maxLightCount = allocateLights( lights, 4 );
 
+		maxShadows = allocateShadows( lights );
+
 		maxBones = allocateBones( object );
 
 		parameters = {
@@ -2638,7 +2645,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 			maxMorphTargets: this.maxMorphTargets,
 			maxDirLights: maxLightCount.directional, maxPointLights: maxLightCount.point,
 			maxBones: maxBones,
-			shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow
+			shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
+			maxShadows: maxShadows
 
 		};
 
@@ -3464,7 +3472,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
-
 	function painterSort( a, b ) {
 
 		return b.z - a.z;
@@ -3474,6 +3481,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 	function renderShadowMap( scene, camera ) {
 
 		var i, il, light,
+			j = 0,
+			shadowMap, shadowMatrix,
 			oil,
 			material,
 			o, ol, webglObject, object,
@@ -3486,20 +3495,28 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-		if ( ! _this.shadowMap ) {
-
-			var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
-			//var pars = { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat };
-			_this.shadowMap = new THREE.WebGLRenderTarget( _this.shadowMapWidth, _this.shadowMapHeight, pars );
-
-		}
-
 		for ( i = 0, il = lights.length; i < il; i ++ ) {
 
 			light = lights[ i ];
 
 			if ( light instanceof THREE.SpotLight && light.castShadow ) {
 
+				if ( ! _this.shadowMap[ j ] ) {
+
+					var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
+					_this.shadowMap[ j ] = new THREE.WebGLRenderTarget( _this.shadowMapWidth, _this.shadowMapHeight, pars );
+
+				}
+
+				if ( ! _shadowMatrix[ j ] ) {
+
+					_shadowMatrix[ j ] = new THREE.Matrix4();
+
+				}
+
+				shadowMap = _this.shadowMap[ j ];
+				shadowMatrix = _shadowMatrix[ j ];
+
 				_cameraLight.position.copy( light.position );
 				_cameraLight.target.position.copy( light.target.position );
 
@@ -3509,13 +3526,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				// compute shadow matrix
 
-				_shadowMatrix.set( 0.5, 0.0, 0.0, 0.5,
-								   0.0, 0.5, 0.0, 0.5,
-								   0.0, 0.0, 0.5, 0.5,
-								   0.0, 0.0, 0.0, 1.0 );
+				shadowMatrix.set( 0.5, 0.0, 0.0, 0.5,
+								  0.0, 0.5, 0.0, 0.5,
+								  0.0, 0.0, 0.5, 0.5,
+								  0.0, 0.0, 0.0, 1.0 );
 
-				_shadowMatrix.multiplySelf( _cameraLight.projectionMatrix );
-				_shadowMatrix.multiplySelf( _cameraLight.matrixWorldInverse );
+				shadowMatrix.multiplySelf( _cameraLight.projectionMatrix );
+				shadowMatrix.multiplySelf( _cameraLight.matrixWorldInverse );
 
 				// render shadow map
 
@@ -3527,7 +3544,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				_this.initWebGLObjects( scene );
 
-				setRenderTarget( _this.shadowMap );
+				setRenderTarget( shadowMap );
 
 				// using arbitrary clear color in depth pass
 				// creates variance in shadows
@@ -3625,6 +3642,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				//_gl.cullFace( _gl.BACK );
 
+				j ++;
+
 			}
 
 		}
@@ -5041,6 +5060,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
 			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
 
+			"#define MAX_SHADOWS " + parameters.maxShadows,
+
 			"#define MAX_BONES " + parameters.maxBones,
 
 			parameters.map ? "#define USE_MAP" : "",
@@ -5108,6 +5129,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
 			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
 
+			"#define MAX_SHADOWS " + parameters.maxShadows,
+
 			parameters.fog ? "#define USE_FOG" : "",
 			parameters.fog instanceof THREE.FogExp2 ? "#define FOG_EXP2" : "",
 
@@ -5205,7 +5228,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	function loadUniformsGeneric( program, uniforms ) {
 
-		var u, uniform, value, type, location, texture;
+		var u, uniform, value, type, location, texture, i, il;
 
 		for( u in uniforms ) {
 
@@ -5256,6 +5279,22 @@ THREE.WebGLRenderer = function ( parameters ) {
 				value.flattenToArray( uniform._array );
 				_gl.uniformMatrix4fv( location, false, uniform._array );
 
+			} else if( type == "m4v" ) {
+
+				if ( ! uniform._array ) {
+
+					uniform._array = new Float32Array( 16 * value.length );
+
+				}
+
+				for ( i = 0, il = value.length; i < il; i ++ ) {
+
+					value[ i ].flattenToArrayOffset( uniform._array, i * 16 );
+
+				}
+
+				_gl.uniformMatrix4fv( location, false, uniform._array );
+
 			} else if( type == "c" ) {
 
 				_gl.uniform3f( location, value.r, value.g, value.b );
@@ -5278,6 +5317,32 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				}
 
+			} else if( type == "tv" ) {
+
+				if ( ! uniform._array ) {
+
+					uniform._array = [];
+
+					for( i = 0, il = uniform.texture.length; i < il; i ++ ) {
+
+						uniform._array[ i ] = value + i;
+
+					}
+
+				}
+
+				_gl.uniform1iv( location, uniform._array );
+
+				for( i = 0, il = uniform.texture.length; i < il; i ++ ) {
+
+					texture = uniform.texture[ i ];
+
+					if ( !texture ) continue;
+
+					setTexture( texture, uniform._array[ i ] );
+
+				}
+
 			}
 
 		}
@@ -5864,9 +5929,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			light = lights[ l ];
 
-			if ( light instanceof THREE.SpotLight ) dirLights++; // hack, not a proper spotlight
-			if ( light instanceof THREE.DirectionalLight ) dirLights++;
-			if ( light instanceof THREE.PointLight ) pointLights++;
+			if ( light instanceof THREE.SpotLight ) dirLights ++; // hack, not a proper spotlight
+			if ( light instanceof THREE.DirectionalLight ) dirLights ++;
+			if ( light instanceof THREE.PointLight ) pointLights ++;
 
 		}
 
@@ -5886,6 +5951,24 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
+	function allocateShadows( lights ) {
+
+		var l, ll, light,
+			maxShadows = 0;
+
+		for ( l = 0, ll = lights.length; l < ll; l++ ) {
+
+			light = lights[ l ];
+
+			if ( light instanceof THREE.SpotLight && light.castShadow ) maxShadows ++;
+
+		}
+
+		return maxShadows;
+
+	};
+
+
 	/* DEBUG
 	function getGLParams() {
 

+ 35 - 19
src/renderers/WebGLShaders.js

@@ -107,7 +107,7 @@ THREE.ShaderChunk = {
 	"#ifdef USE_ENVMAP",
 
 		"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
-		"vec3 nWorld = mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal;",
+		"vec3 nWorld = mat3( objectMatrix[ 0 ].xyz, objectMatrix[ 1 ].xyz, objectMatrix[ 2 ].xyz ) * normal;",
 
 		"if ( useRefract ) {",
 
@@ -275,7 +275,7 @@ THREE.ShaderChunk = {
 
 		"#if MAX_DIR_LIGHTS > 0",
 
-		"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
+		"for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
 
 			"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
 			"float directionalLightWeighting = max( dot( transformedNormal, normalize( lDirection.xyz ) ), 0.0 );",
@@ -287,7 +287,7 @@ THREE.ShaderChunk = {
 
 		"#if MAX_POINT_LIGHTS > 0",
 
-			"for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
+			"for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 
 				"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
 
@@ -369,7 +369,7 @@ THREE.ShaderChunk = {
 		"vec4 dirDiffuse  = vec4( 0.0 );",
 		"vec4 dirSpecular = vec4( 0.0 );" ,
 
-		"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
+		"for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
 
 			"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
 
@@ -536,12 +536,12 @@ THREE.ShaderChunk = {
 
 	"#ifdef USE_SHADOWMAP",
 
-		"uniform sampler2D shadowMap;",
+		"uniform sampler2D shadowMap[ MAX_SHADOWS ];",
 
 		"uniform float shadowDarkness;",
 		"uniform float shadowBias;",
 
-		"varying vec4 vShadowCoord;",
+		"varying vec4 vShadowCoord[ MAX_SHADOWS ];",
 
 		"float unpackDepth( const in vec4 rgba_depth ) {",
 
@@ -559,18 +559,30 @@ THREE.ShaderChunk = {
 
 	"#ifdef USE_SHADOWMAP",
 
-		"vec3 shadowCoord = vShadowCoord.xyz / vShadowCoord.w;",
+		"vec4 shadowColor = vec4( 1.0 );",
 
-		"vec4 rgbaDepth = texture2D( shadowMap, shadowCoord.xy );",
-		"float fDepth = unpackDepth( rgbaDepth );",
+		"for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
 
-		"if ( fDepth < ( shadowCoord.z + shadowBias ) && ( shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0 ) )",
-			"gl_FragColor = gl_FragColor * vec4( vec3( shadowDarkness ), 1.0 );",
+			"vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;",
 
-		// uncomment to see light frustum boundaries
-		//"if ( !( shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0 ) )",
-		//	"gl_FragColor =  gl_FragColor * vec4( 1.0, 0.0, 0.0, 1.0 );",
+			"vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );",
+			"float fDepth = unpackDepth( rgbaDepth );",
 
+			"if ( fDepth < ( shadowCoord.z + shadowBias ) && ( shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0 ) )",
+
+				// spot with multiple shadows is darker
+				"shadowColor = shadowColor * vec4( vec3( shadowDarkness ), 1.0 );",
+
+				// spot with multiple shadows has the same color as single shadow spot
+				//"shadowColor = min( shadowColor, vec4( vec3( shadowDarkness ), 1.0 ) );",
+
+			// uncomment to see light frustum boundaries
+			//"if ( !( shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0 ) )",
+			//	"gl_FragColor =  gl_FragColor * vec4( 1.0, 0.0, 0.0, 1.0 );",
+
+		"}",
+
+		"gl_FragColor = gl_FragColor * shadowColor;",
 
 	"#endif"
 
@@ -580,8 +592,8 @@ THREE.ShaderChunk = {
 
 	"#ifdef USE_SHADOWMAP",
 
-		"varying vec4 vShadowCoord;",
-		"uniform mat4 shadowMatrix;",
+		"varying vec4 vShadowCoord[ MAX_SHADOWS ];",
+		"uniform mat4 shadowMatrix[ MAX_SHADOWS ];",
 
 	"#endif"
 
@@ -591,7 +603,11 @@ THREE.ShaderChunk = {
 
 	"#ifdef USE_SHADOWMAP",
 
-		"vShadowCoord = shadowMatrix * objectMatrix * vec4( position, 1.0 );",
+		"for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
+
+			"vShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );",
+
+		"}",
 
 	"#endif"
 
@@ -722,8 +738,8 @@ THREE.UniformsLib = {
 
 	shadowmap: {
 
-		"shadowMap": { type: "t", value: 3, texture: null },
-		"shadowMatrix" : { type: "m4", value: new THREE.Matrix4() },
+		"shadowMap": { type: "tv", value: 3, texture: [] },
+		"shadowMatrix" : { type: "m4v", value: [] },
 
 		"shadowBias" : { type: "f", value: 0.0039 },
 		"shadowDarkness": { type: "f", value: 0.2 }

Some files were not shown because too many files changed in this diff