Browse Source

Added shadow functionality for point lights.

Mark Kellogg 10 years ago
parent
commit
01e0199b3c

+ 1 - 0
examples/index.html

@@ -362,6 +362,7 @@
 				"webgl_shadowmap",
 				"webgl_shadowmap_performance",
 				"webgl_shadowmap_viewer",
+				"webgl_shadowmap_omnidirectional",		
 				"webgl_shadowmesh",
 				"webgl_skinning_simple",
 				"webgl_sprites",

+ 295 - 0
examples/webgl_shadowmap_omnidirectional.html

@@ -0,0 +1,295 @@
+
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - Omni-directional Shadow map viewer example </title>
+		<meta charset="utf-8">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#info {
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				z-index: 100;
+				display:block;
+			}
+			#info a { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
+		</style>
+	</head>
+	<body>
+		<div id="info">
+		<a href="http://threejs.org" target="_blank">three.js</a> - Omni-directional Shadow map viewer example by <a href="https://github.com/mkkellogg">mkkellogg</a>
+		</div>
+
+		<script src="../build/three.min.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
+		<script src="js/Detector.js"></script>		
+		<script src="js/libs/stats.min.js"></script>
+		<script>
+		
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var camera, scene, renderer, clock, stats;
+			var dirLight, pointLight;
+			var pointLightParent;
+			var torusKnot, cube, cube2, cube3, cube4;
+			var cubeMaterial;
+			var wallMaterial;
+			var ground;
+
+			init();
+			animate();
+
+			function init() {
+
+				initScene();
+				initMisc();
+
+				document.body.appendChild( renderer.domElement );
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function initScene() {
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.01, 1000 );
+				camera.position.set( 0, 15, 35 );
+
+				scene = new THREE.Scene();
+
+				// Lights
+				var ambient = new THREE.AmbientLight( 0x404040 );
+				scene.add( ambient );
+
+				pointLight = new THREE.PointLight( 0xffffff );
+				pointLight.position.set(0,11,4);
+				pointLight.castShadow = true;
+				pointLight.shadowCameraNear = .05;
+				pointLight.shadowCameraFar = 30;
+				pointLight.shadowDarkness = 0.5;
+				pointLight.shadowCameraVisible = true;
+				pointLight.shadowMapWidth = 1024;
+				pointLight.shadowMapHeight = 1024;
+				pointLight.name = 'Point Light';
+				scene.add( pointLight );
+
+				dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
+				dirLight.position.set( 0, 50, 0 );
+				dirLight.castShadow = true;
+				dirLight.shadowCameraNear = 0.01;
+				dirLight.shadowCameraFar = 100;
+				dirLight.shadowCameraRight = 15;
+				dirLight.shadowCameraLeft = -15;
+				dirLight.shadowCameraTop	= 15;
+				dirLight.shadowCameraBottom = -15;
+				dirLight.shadowDarkness = 0.5;
+				dirLight.shadowCameraVisible = true;
+				dirLight.shadowMapWidth = 1024;
+				dirLight.shadowMapHeight = 1024;
+				dirLight.name = 'Dir. Light';
+				//scene.add( dirLight );			
+
+				cubeMaterial = new THREE.MeshPhongMaterial( {
+					color: 0xff0000,
+					shininess: 150,
+					specular: 0x222222,
+					shading: THREE.SmoothShading,
+				} );
+
+				var cubeGeometry = new THREE.BoxGeometry( 3, 3, 3 );
+				cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
+				cube.name = "cube 1";
+				cube.position.set( 8, 3, 6 );
+				cube.castShadow = true;
+				cube.receiveShadow = true;
+				scene.add( cube );
+
+				cube2 = new THREE.Mesh( cubeGeometry, cubeMaterial );
+				cube2.name = "cube 2";
+				cube2.position.set( -8, 3, 4 );
+				cube2.castShadow = true;
+				cube2.receiveShadow = true;
+				scene.add( cube2 );
+
+				cube3 = new THREE.Mesh( cubeGeometry, cubeMaterial );
+				cube3.name = "cube 3";
+				cube3.position.set( -4, 15, -6 );
+				cube3.castShadow = true;
+				cube3.receiveShadow = true;
+				scene.add( cube3 );
+
+				var torusGeometry =  new THREE.TorusKnotGeometry( 25, 8, 75, 20 );
+				torusKnot = new THREE.Mesh( torusGeometry, cubeMaterial );
+				torusKnot.scale.multiplyScalar( 1 / 18 );
+				torusKnot.position.y = 3;
+				torusKnot.castShadow = true;
+				torusKnot.receiveShadow = true;
+				scene.add( torusKnot );
+			
+				wallMaterial = new THREE.MeshPhongMaterial( {
+					color: 0xa0adaf,
+					shininess: 150,
+					specular: 0xffffff,
+					shading: THREE.SmoothShading
+				} );				
+
+				var groundGeometry = new THREE.BoxGeometry( 10, 0.15, 10 );
+				ground = new THREE.Mesh( groundGeometry, wallMaterial );
+				ground.name = "ground";
+				ground.scale.multiplyScalar( 3 );
+				ground.castShadow = false;
+				ground.receiveShadow = true;
+				scene.add( ground );
+				ground.position.set(0,-5,0);
+
+				var ceiling = new THREE.Mesh( groundGeometry, wallMaterial );
+				ceiling.name = "ceiling";
+				ceiling.scale.multiplyScalar( 3 );
+				ceiling.castShadow = false;
+				ceiling.receiveShadow = true;
+				scene.add( ceiling );
+				ceiling.position.set(0,24,0);
+
+				var wall = new THREE.Mesh( groundGeometry, wallMaterial );
+				wall.name = "left wall";
+				wall.scale.multiplyScalar( 3 );
+				wall.castShadow = false;
+				wall.receiveShadow = true;				
+				scene.add( wall );
+				wall.position.set(-14,10,0);
+				rotateAroundWorldAxis(wall, new THREE.Vector3(0,0,-1), Math.PI / 180 * 90);
+
+				wall = new THREE.Mesh( groundGeometry, wallMaterial );
+				wall.name = "right wall";
+				wall.scale.multiplyScalar( 3 );
+				wall.castShadow = false;
+				wall.receiveShadow = true;				
+				scene.add( wall );
+				wall.position.set(14,10,0);
+				rotateAroundWorldAxis(wall, new THREE.Vector3(0,0,-1), Math.PI / 180 * 90);
+
+				wall = new THREE.Mesh( groundGeometry, wallMaterial );
+				wall.name = "back wall";
+				wall.scale.multiplyScalar( 3 );
+				wall.castShadow = false;
+				wall.receiveShadow = true;				
+				scene.add( wall );
+				wall.position.set(0,10,-14);
+				rotateAroundWorldAxis(wall, new THREE.Vector3(1,0,0), Math.PI / 180 * 90);
+
+				var sphereGeometry = new THREE.SphereGeometry( 1, 32, 32 );
+				var material = new THREE.MeshBasicMaterial( {color: 0xffffff} );
+				var sphere = new THREE.Mesh( sphereGeometry, material );
+				sphere.castShadow = false;
+				sphere.receiveShadow = false;	
+				sphere.position.set(0,11,4);
+				scene.add( sphere );
+
+				pointLightParent = new THREE.Object3D();
+				pointLightParent.add(pointLight);
+				pointLightParent.add(sphere);
+				scene.add(pointLightParent);			
+			}
+
+			// Rotate an object around an arbitrary axis in world space       
+			function rotateAroundWorldAxis(object, axis, radians) {
+			    var rotWorldMatrix = new THREE.Matrix4();
+			    rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);
+			    rotWorldMatrix.multiply(object.matrix);            
+			    object.matrix = rotWorldMatrix;
+			    object.rotation.setFromRotationMatrix(object.matrix);
+			}
+
+			// Rotate an object around an arbitrary axis in world space       
+			function rotateAroundWorldAxis(object, axis, radians) {
+			    var rotWorldMatrix = new THREE.Matrix4();
+			    rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);
+			    rotWorldMatrix.multiply(object.matrix);               
+			    object.matrix = rotWorldMatrix;
+			    object.rotation.setFromRotationMatrix(object.matrix);
+			}
+
+			function initMisc() {
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setClearColor( 0x000000 );				
+				renderer.shadowMap.enabled = true;
+				renderer.shadowMap.type = THREE.BasicShadowMap;
+
+				// Mouse control
+				controls = new THREE.OrbitControls( camera, renderer.domElement );
+				controls.target.set( 0, 2, 0 );
+				controls.update();
+
+				clock = new THREE.Clock();
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.right = '0px';
+				stats.domElement.style.top = '0px';
+				document.body.appendChild( stats.domElement );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+				render();
+
+				stats.update();
+
+			}
+
+			function renderScene() {
+				renderer.render( scene, camera );
+			}
+
+
+			var updateCount = 0;
+			function render() {
+
+				var delta = clock.getDelta();
+
+				pointLightParent.rotation.y += .05;
+				renderScene();
+
+				cube.rotation.x += 0.25 * delta;
+				cube.rotation.y += 2 * delta;
+				cube.rotation.z += 1 * delta;
+
+				cube2.rotation.x += 0.25 * delta;
+				cube2.rotation.y += 2 * delta;
+				cube2.rotation.z += 1 * delta;
+
+				cube3.rotation.x += 0.25 * delta;
+				cube3.rotation.y += 2 * delta;
+				cube3.rotation.z += 1 * delta;
+
+				//var pos = new THREE.Vector3();
+				//pos.setFromMatrixPosition(pointLight.matrixWorld);
+				//console.log(pos.x +","+pos.y+","+pos.z);
+
+				updateCount++;
+
+			}
+
+		</script>
+	</body>
+</html>

+ 40 - 0
src/lights/PointLight.js

@@ -2,6 +2,7 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
+
 THREE.PointLight = function ( color, intensity, distance, decay ) {
 
 	THREE.Light.call( this, color );
@@ -12,6 +13,30 @@ THREE.PointLight = function ( color, intensity, distance, decay ) {
 	this.distance = ( distance !== undefined ) ? distance : 0;
 	this.decay = ( decay !== undefined ) ? decay : 1;	// for physically correct lights, should be 2.
 
+	this.castShadow = false;
+	this.onlyShadow = false;
+
+	//
+
+	this.shadowCameraNear = 0;
+	this.shadowCameraFar = 5000;
+	this.shadowCameraFov = 90;
+
+	this.shadowCameraVisible = false;
+
+	this.shadowBias = 0;
+	this.shadowDarkness = 0.5;
+
+	this.shadowMapWidth = 512;
+	this.shadowMapHeight = 512;
+
+	//
+
+	this.shadowMap = null;
+	this.shadowMapSize = null;
+	this.shadowCamera = null;
+	this.shadowMatrix = null;
+
 };
 
 THREE.PointLight.prototype = Object.create( THREE.Light.prototype );
@@ -25,6 +50,21 @@ THREE.PointLight.prototype.copy = function ( source ) {
 	this.distance = source.distance;
 	this.decay = source.decay;
 
+	this.castShadow = source.castShadow;
+	this.onlyShadow = source.onlyShadow;
+
+	this.shadowCameraNear = source.shadowCameraNear;
+	this.shadowCameraFar = source.shadowCameraFar;
+	this.shadowCameraFov = source.shadowCameraFov;
+
+	this.shadowCameraVisible = source.shadowCameraVisible;
+
+	this.shadowBias = source.shadowBias;
+	this.shadowDarkness = source.shadowDarkness;
+
+	this.shadowMapWidth = source.shadowMapWidth;
+	this.shadowMapHeight = source.shadowMapHeight;
+
 	return this;
 
 };

+ 37 - 5
src/renderers/WebGLRenderer.js

@@ -1965,9 +1965,19 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( ! light.castShadow ) continue;
 
-				if ( light instanceof THREE.SpotLight || ( light instanceof THREE.DirectionalLight ) ) {
+				if ( light instanceof THREE.PointLight || light instanceof THREE.SpotLight || light instanceof THREE.DirectionalLight  ) {
+
+					if( light instanceof THREE.PointLight){
+						uniforms.shadowCube.value[ j ] = light.shadowMap;
+						uniforms.shadowMap.value[ j ] = null;
+						uniforms.isShadowCube.value[ j ] = 1;
+
+					} else {
+						uniforms.shadowMap.value[ j ] = light.shadowMap;
+						uniforms.isShadowCube.value[ j ] = 0;
+						uniforms.shadowCube.value[ j ] = null;
+					}					
 
-					uniforms.shadowMap.value[ j ] = light.shadowMap;
 					uniforms.shadowMapSize.value[ j ] = light.shadowMapSize;
 
 					uniforms.shadowMatrix.value[ j ] = light.shadowMatrix;
@@ -1975,6 +1985,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 					uniforms.shadowDarkness.value[ j ] = light.shadowDarkness;
 					uniforms.shadowBias.value[ j ] = light.shadowBias;
 
+					_vector3.setFromMatrixPosition(light.matrixWorld);
+					uniforms.shadowLightPosition.value[ j * 3] = _vector3.x;
+					uniforms.shadowLightPosition.value[ j * 3 + 1] = _vector3.y;
+					uniforms.shadowLightPosition.value[ j * 3 + 2] = _vector3.z;
+
 					j ++;
 
 				}
@@ -2308,7 +2323,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				case 'tv':
 
-					// array of THREE.Texture (2d)
+					// array of THREE.Texture (2d or cube)
 
 					if ( uniform._array === undefined ) {
 
@@ -2330,8 +2345,21 @@ THREE.WebGLRenderer = function ( parameters ) {
 						textureUnit = uniform._array[ i ];
 
 						if ( ! texture ) continue;
+						
+						if ( texture instanceof THREE.CubeTexture ||
+						   ( texture.image instanceof Array && texture.image.length === 6 ) ) { // CompressedTexture can have Array in image :/
 
-						_this.setTexture( texture, textureUnit );
+							setCubeTexture( texture, textureUnit );
+
+						} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
+
+							setCubeTextureDynamic( texture, textureUnit );
+
+						} else {
+
+							_this.setTexture( texture, textureUnit );
+
+						}
 
 					}
 
@@ -3011,7 +3039,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
 					renderTargetProperties.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
-
 					state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 
 					setupFrameBuffer( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
@@ -3124,6 +3151,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
+		if( isCube ){
+			var renderTargetProperties = properties.get( renderTarget );
+			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0,  _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, renderTargetProperties.__webglTexture , 0 );
+		}
+
 		_currentWidth = width;
 		_currentHeight = height;
 

+ 114 - 92
src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl

@@ -13,8 +13,13 @@
 	vec3 shadowColor = vec3( 1.0 );
 
 	for( int i = 0; i < MAX_SHADOWS; i ++ ) {
-
+		vec3 lightToPosition = vWPosition[ i ].xyz - shadowLightPosition[ i ];
+		vec3 lightToFragment = normalize( lightToPosition );
+		float distanceToLight = length( lightToPosition );
+		int currentIsCube = isShadowCube[ i ];
+		float cubeTexelSize = 1.0 / shadowMapSize[ i ].x;
 		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
@@ -26,148 +31,165 @@
 
 		bool frustumTest = all( frustumTestVec );
 
-		if ( frustumTest ) {
+		if ( frustumTest || currentIsCube == 1) {
 
 			shadowCoord.z += shadowBias[ i ];
 
 			#if defined( SHADOWMAP_TYPE_PCF )
+				if( currentIsCube == 1 ){
+				
+					shadow = sampleCubeShadowMapPCF( shadowCube[ i ], lightToFragment, distanceToLight, cubeTexelSize, 1.5);
+					
+				} else {
+					// 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
 
-						// Percentage-close filtering
-						// (9 pixel kernel)
-						// http://fabiensanglard.net/shadowmappingPCF/
-
-				float shadow = 0.0;
-
-		/*
-						// 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 ) {
 
-				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 );
 
-						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 ) );
 
-								// 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 );
 
-						float fDepth = unpackDepth( rgbaDepth );
+								if ( fDepth < shadowCoord.z )
+									shadow += 1.0;
 
-						if ( fDepth < shadowCoord.z )
-							shadow += 1.0;
-
-				}
+						}
 
-				shadow /= 9.0;
+						shadow /= 9.0;
 
-		*/
+					*/
 
-				const float shadowDelta = 1.0 / 9.0;
+					const float shadowDelta = 1.0 / 9.0;
 
-				float xPixelOffset = 1.0 / shadowMapSize[ i ].x;
-				float yPixelOffset = 1.0 / shadowMapSize[ i ].y;
+					float xPixelOffset = 1.0 / shadowMapSize[ i ].x;
+					float yPixelOffset = 1.0 / shadowMapSize[ i ].y;
 
-				float dx0 = -1.25 * xPixelOffset;
-				float dy0 = -1.25 * yPixelOffset;
-				float dx1 = 1.25 * xPixelOffset;
-				float dy1 = 1.25 * yPixelOffset;
+					float dx0 = -1.25 * xPixelOffset;
+					float dy0 = -1.25 * yPixelOffset;
+					float dx1 = 1.25 * xPixelOffset;
+					float dy1 = 1.25 * yPixelOffset;
 
-				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
-				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+					fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
+					if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
 
-				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
-				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+					fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
+					if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
 
-				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
-				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+					fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
+					if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
 
-				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
-				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+					fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
+					if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
 
-				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
-				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+					fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
+					if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
 
-				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
-				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+					fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
+					if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
 
-				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
-				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+					fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
+					if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
 
-				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
-				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+					fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
+					if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
 
-				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
-				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+					fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
+					if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
 
+				}
 				shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );
-
+				
 			#elif defined( SHADOWMAP_TYPE_PCF_SOFT )
+			
+				if( currentIsCube == 1 ){
 
-						// Percentage-close filtering
-						// (9 pixel kernel)
-						// http://fabiensanglard.net/shadowmappingPCF/
+					shadow = sampleCubeShadowMapPCF( shadowCube[ i ], lightToFragment, distanceToLight, cubeTexelSize, 2.5 );
 
-				float shadow = 0.0;
+				} else { 
 
-				float xPixelOffset = 1.0 / shadowMapSize[ i ].x;
-				float yPixelOffset = 1.0 / shadowMapSize[ i ].y;
+					// Percentage-close filtering
+					// (9 pixel kernel)
+					// http://fabiensanglard.net/shadowmappingPCF/
 
-				float dx0 = -1.0 * xPixelOffset;
-				float dy0 = -1.0 * yPixelOffset;
-				float dx1 = 1.0 * xPixelOffset;
-				float dy1 = 1.0 * yPixelOffset;
+					float xPixelOffset = 1.0 / shadowMapSize[ i ].x;
+					float yPixelOffset = 1.0 / shadowMapSize[ i ].y;
 
-				mat3 shadowKernel;
-				mat3 depthKernel;
+					float dx0 = -1.0 * xPixelOffset;
+					float dy0 = -1.0 * yPixelOffset;
+					float dx1 = 1.0 * xPixelOffset;
+					float dy1 = 1.0 * yPixelOffset;
 
-				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 ) ) );
+					mat3 shadowKernel;
+					mat3 depthKernel;
 
-				vec3 shadowZ = vec3( shadowCoord.z );
-				shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));
-				shadowKernel[0] *= 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 ) ) );
 
-				shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));
-				shadowKernel[1] *= vec3(0.25);
+					vec3 shadowZ = vec3( shadowCoord.z );
+					shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));
+					shadowKernel[0] *= vec3(0.25);
 
-				shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));
-				shadowKernel[2] *= vec3(0.25);
+					shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));
+					shadowKernel[1] *= vec3(0.25);
 
-				vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );
+					shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));
+					shadowKernel[2] *= vec3(0.25);
 
-				shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );
-				shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );
+					vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );
 
-				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 );
+					shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );
+					shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );
 
-				shadow = dot( shadowValues, vec4( 1.0 ) );
+					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 ) );
+				}
 
 				shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );
 
 			#else
 
-				vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
-				float fDepth = unpackDepth( rgbaDepth );
+				if( currentIsCube == 1 ){		
+				
+					float dist = getCubeMapFloat( shadowCube[ i ], lightToFragment );
+					if ( distanceToLight >= dist)
+						shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );
+						
+				} else {
+				
+					vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
+					float fDepth = unpackDepth( rgbaDepth );
 
-				if ( fDepth < shadowCoord.z )
+					if ( fDepth < shadowCoord.z )
 
-		// spot with multiple shadows is darker
+					// spot with multiple shadows is darker
 
 					shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );
 
-		// spot with multiple shadows has the same color as single shadow spot
+					// spot with multiple shadows has the same color as single shadow spot
 
-		// 					shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );
+					// 	shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );
+				}
 
 			#endif
 

File diff suppressed because it is too large
+ 0 - 19
src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl


+ 1 - 6
src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl

@@ -1,6 +1 @@
-#ifdef USE_SHADOWMAP
-
-	varying vec4 vShadowCoord[ MAX_SHADOWS ];
-	uniform mat4 shadowMatrix[ MAX_SHADOWS ];
-
-#endif
+#ifdef USE_SHADOWMAP

	varying vec4 vShadowCoord[ MAX_SHADOWS ];
	varying vec4 vWPosition[ MAX_SHADOWS ];
	uniform mat4 shadowMatrix[ MAX_SHADOWS ];
	uniform vec3 shadowLightPosition[ MAX_SHADOWS ];

#endif

+ 1 - 9
src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl

@@ -1,9 +1 @@
-#ifdef USE_SHADOWMAP
-
-	for( int i = 0; i < MAX_SHADOWS; i ++ ) {
-
-		vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;
-
-	}
-
-#endif
+#ifdef USE_SHADOWMAP

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

		vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;
		vWPosition[ i ] = worldPosition;

	}

#endif

+ 71 - 0
src/renderers/shaders/ShaderLib.js

@@ -835,6 +835,77 @@ THREE.ShaderLib = {
 
 		].join( "\n" )
 
+	},
+
+
+	'distanceRGBA': {
+
+		uniforms: {
+
+			"lightPos": { type: "v3", value: new THREE.Vector3(0,0,0) }
+
+		},
+
+		vertexShader: [
+
+			"varying vec4 vWorldPosition;",
+
+			THREE.ShaderChunk[ "common" ],
+			THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
+			THREE.ShaderChunk[ "skinning_pars_vertex" ],
+
+			"void main() {",
+
+			"#ifdef USE_SKINNING",
+
+			"	vWorldPosition = modelMatrix * skinned;",
+
+			"#else",
+
+			"	vWorldPosition = modelMatrix * vec4( position, 1.0 );",
+
+			"#endif",
+
+				THREE.ShaderChunk[ "skinbase_vertex" ],
+				THREE.ShaderChunk[ "begin_vertex" ],
+				THREE.ShaderChunk[ "morphtarget_vertex" ],
+				THREE.ShaderChunk[ "skinning_vertex" ],
+				THREE.ShaderChunk[ "project_vertex" ],
+
+			"}"
+
+		].join("\n"),
+
+		fragmentShader: [
+
+			"uniform vec3 lightPos;",
+			"varying vec4 vWorldPosition;",
+
+			THREE.ShaderChunk[ "common" ],
+
+			"vec4 pack1K (float depth) {",
+			"   depth /= 1000.0;",
+			"   const vec4 bitSh = vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);",
+  			"	const vec4 bitMsk = vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);",
+   			"	vec4 res = fract(depth * bitSh);",
+   			"	res -= res.xxyz * bitMsk;",
+   			"	return res; ",
+			"}",
+			
+			
+			"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);",
+			"	return dot(color, bitSh) * 1000.0;",
+			"}",
+
+
+			"void main() {",
+			"	gl_FragColor = pack1K( length(vWorldPosition.xyz - lightPos.xyz) );",
+
+			"}"
+
+		].join("\n")
+
 	}
 
 };

+ 5 - 1
src/renderers/shaders/UniformsLib.js

@@ -117,13 +117,17 @@ THREE.UniformsLib = {
 
 	shadowmap: {
 
+		"isShadowCube": { type: "iv1", value: [] },
+		"shadowCube": { type: "tv", value: [] },
 		"shadowMap": { type: "tv", value: [] },
+
 		"shadowMapSize": { type: "v2v", value: [] },
 
 		"shadowBias" : { type: "fv1", value: [] },
 		"shadowDarkness": { type: "fv1", value: [] },
 
-		"shadowMatrix" : { type: "m4v", value: [] }
+		"shadowMatrix" : { type: "m4v", value: [] },
+		"shadowLightPosition" : { type: "fv", value: [] }
 
 	}
 

+ 1 - 1
src/renderers/webgl/WebGLPrograms.js

@@ -98,7 +98,7 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) {
 
 			if ( ! light.castShadow ) continue;
 
-			if ( light instanceof THREE.SpotLight ) maxShadows ++;
+			if ( light instanceof THREE.SpotLight || light instanceof THREE.PointLight ) maxShadows ++;
 			if ( light instanceof THREE.DirectionalLight ) maxShadows ++;
 
 		}

+ 166 - 66
src/renderers/webgl/WebGLShadowMap.js

@@ -13,36 +13,48 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 	_min = new THREE.Vector3(),
 	_max = new THREE.Vector3(),
 
-	_matrixPosition = new THREE.Vector3(),
+	_lookTarget = new THREE.Vector3(),
+	_lightPosition = new THREE.Vector3(),
 
 	_renderList = [];
 
+	var _depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin,
+	_distanceMaterial, _distanceMaterialMorph, _distanceMaterialSkin, _distanceMaterialMorphSkin;
+
+	var cubeDirections = [new THREE.Vector3(1,0,0), new THREE.Vector3(-1,0,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)];
+
+	var cubeUps = [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,-1,0)];
+
+    var _vector4 = new THREE.Vector4();
+
 	// init
 
 	var depthShader = THREE.ShaderLib[ "depthRGBA" ];
 	var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
 
-	var _depthMaterial = new THREE.ShaderMaterial( {
+	_depthMaterial = new THREE.ShaderMaterial( {
 		uniforms: depthUniforms,
 		vertexShader: depthShader.vertexShader,
 		fragmentShader: depthShader.fragmentShader
 	 } );
 
-	var _depthMaterialMorph = new THREE.ShaderMaterial( {
+	_depthMaterialMorph = new THREE.ShaderMaterial( {
 		uniforms: depthUniforms,
 		vertexShader: depthShader.vertexShader,
 		fragmentShader: depthShader.fragmentShader,
 		morphTargets: true
 	} );
 
-	var _depthMaterialSkin = new THREE.ShaderMaterial( {
+	_depthMaterialSkin = new THREE.ShaderMaterial( {
 		uniforms: depthUniforms,
 		vertexShader: depthShader.vertexShader,
 		fragmentShader: depthShader.fragmentShader,
 		skinning: true
 	} );
 
-	var _depthMaterialMorphSkin = new THREE.ShaderMaterial( {
+	_depthMaterialMorphSkin = new THREE.ShaderMaterial( {
 		uniforms: depthUniforms,
 		vertexShader: depthShader.vertexShader,
 		fragmentShader: depthShader.fragmentShader,
@@ -55,6 +67,43 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 	_depthMaterialSkin._shadowPass = true;
 	_depthMaterialMorphSkin._shadowPass = true;
 
+
+	var distanceShader = THREE.ShaderLib[ "distanceRGBA" ];
+	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;
+
 	//
 
 	var scope = this;
@@ -69,6 +118,8 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 	this.render = function ( scene ) {
 
+		var faceCount, isCube;
+
 		if ( scope.enabled === false ) return;
 		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
 
@@ -98,6 +149,14 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 			var light = _lights[ i ];
 
+			if ( light instanceof THREE.PointLight ) {
+				faceCount = 6;
+				isCube = true;
+			} else {
+				faceCount = 1;
+				isCube = false;
+			}
+
 			if ( ! light.castShadow ) continue;
 
 			if ( ! light.shadowMap ) {
@@ -112,8 +171,13 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 				var pars = { minFilter: shadowFilter, magFilter: shadowFilter, format: THREE.RGBAFormat };
 
-				light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
-				light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );
+				if ( isCube ) {
+					light.shadowMap = new THREE.WebGLRenderTargetCube( light.shadowMapWidth, light.shadowMapWidth, pars );
+					light.shadowMapSize = new  THREE.Vector2( light.shadowMapWidth, light.shadowMapWidth );
+				} else {
+					light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
+					light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );
+				}	
 
 				light.shadowMatrix = new THREE.Matrix4();
 
@@ -131,8 +195,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 				} else {
 
-					console.error( "THREE.ShadowMapPlugin: Unsupported light type for shadow", light );
-					continue;
+					light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, light.shadowMapWidth / light.shadowMapHeight, light.shadowCameraNear, light.shadowCameraFar );
 
 				}
 
@@ -153,83 +216,97 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 			var shadowMatrix = light.shadowMatrix;
 			var shadowCamera = light.shadowCamera;
 
-			//
+			_lightPosition.setFromMatrixPosition( light.matrixWorld );
+			shadowCamera.position.copy(_lightPosition);
+
+			// render shadow map for each cube face (if omni-directional) or
+			// run a single pass if not
 
-			shadowCamera.position.setFromMatrixPosition( light.matrixWorld );
-			_matrixPosition.setFromMatrixPosition( light.target.matrixWorld );
-			shadowCamera.lookAt( _matrixPosition );
-			shadowCamera.updateMatrixWorld();
+			for(var face = 0; face < faceCount; face ++){				
+		
+				if( isCube){
+					_lookTarget.copy(shadowCamera.position);
+					_lookTarget.add(cubeDirections[face]);
+					shadowCamera.up.copy(cubeUps[face]);
+					shadowCamera.lookAt(_lookTarget);				
+				} else {
+					_lookTarget.setFromMatrixPosition( light.target.matrixWorld );
+					shadowCamera.lookAt( _lookTarget);
+				}	
 
-			shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
+				shadowCamera.updateMatrixWorld();
+				shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
 
-			//
+				if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
+				if ( light.shadowCameraVisible ) light.cameraHelper.update();
 
-			if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
-			if ( light.shadowCameraVisible ) light.cameraHelper.update();
+				// compute shadow matrix
 
-			// 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.multiply( shadowCamera.projectionMatrix );
+				shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
 
-			shadowMatrix.multiply( shadowCamera.projectionMatrix );
-			shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
+				// update camera matrices and frustum
 
-			// update camera matrices and frustum
+				_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
+				_frustum.setFromMatrix( _projScreenMatrix );
 
-			_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
-			_frustum.setFromMatrix( _projScreenMatrix );
+				// render shadow map
 
-			// render shadow map
+				if(isCube){
+					shadowMap.activeCubeFace = face;
+				}	
 
-			_renderer.setRenderTarget( shadowMap );
-			_renderer.clear();
+				_renderer.setRenderTarget( shadowMap );
+				_renderer.clear();
 
-			// set object matrices & frustum culling
+				// set object matrices & frustum culling
 
-			_renderList.length = 0;
+				_renderList.length = 0;
 
-			projectObject( scene, shadowCamera );
+				projectObject( scene, shadowCamera );
 
+				// render regular objects
 
-			// render regular objects
+				for ( var j = 0, jl = _renderList.length; j < jl; j ++ ) {
 
-			for ( var j = 0, jl = _renderList.length; j < jl; j ++ ) {
+					var object = _renderList[ j ];
+					var geometry = _objects.update( object );
+					var material = object.material;
 
-				var object = _renderList[ j ];
-				var geometry = _objects.update( object );
-				var material = object.material;
+					if ( material instanceof THREE.MeshFaceMaterial ) {
 
-				if ( material instanceof THREE.MeshFaceMaterial ) {
+						var groups = geometry.groups;
+						var materials = material.materials;
 
-					var groups = geometry.groups;
-					var materials = material.materials;
+						for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
 
-					for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
+							var group = groups[ k ];
+							var groupMaterial = materials[ group.materialIndex ];
 
-						var group = groups[ k ];
-						var groupMaterial = materials[ group.materialIndex ];
+							if ( groupMaterial.visible === true ) {
 
-						if ( groupMaterial.visible === true ) {
+								var depthMaterial = getDepthMaterial( object, groupMaterial, isCube, _lightPosition);
+								_renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial , object, group );
 
-							_renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, getDepthMaterial( object, groupMaterial ), object, group );
+							}
 
 						}
 
+					} else {
+						var depthMaterial = getDepthMaterial( object, material, isCube, _lightPosition);						
+						_renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial, object, null );
 					}
 
-				} else {
-
-					_renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, getDepthMaterial( object, material ), object, null );
-
 				}
 
 			}
-
 		}
 
 		// restore GL state
@@ -252,43 +329,67 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 	};
 
-	function getDepthMaterial( object, material ) {
+	function getDepthMaterial( object, material, isCube, lightPosition) {
 
 		var geometry = object.geometry;
 
 		var useMorphing = geometry.morphTargets !== undefined && geometry.morphTargets.length > 0 && material.morphTargets;
 		var useSkinning = object instanceof THREE.SkinnedMesh && material.skinning;
 
-		var depthMaterial;
+		var newMaterial;
+
+		var depthMaterial = _depthMaterial;
+		var depthMaterialMorph = _depthMaterialMorph; 
+		var depthMaterialSkin = _depthMaterialSkin; 
+		var depthMaterialMorphSkin = _depthMaterialMorphSkin;
 
-		if ( object.customDepthMaterial ) {
+		if ( isCube ){
+			depthMaterial = _distanceMaterial;
+			depthMaterialMorph = _distanceMaterialMorph; 
+			depthMaterialSkin = _distanceMaterialSkin; 
+			depthMaterialMorphSkin = _distanceMaterialMorphSkin;
+		}
 
-			depthMaterial = object.customDepthMaterial;
+		if ( object.customDepthMaterial || object.customDistanceMaterial) {
+
+			if( isCube ){
+				newMaterial = object.customDistanceMaterial;
+			} else {
+				newMaterial = object.customDepthMaterial;
+			}
 
 		} else if ( useSkinning ) {
 
-			depthMaterial = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;
+			newMaterial = useMorphing ? depthMaterialMorphSkin : depthMaterialSkin;
 
 		} else if ( useMorphing ) {
 
-			depthMaterial = _depthMaterialMorph;
+			newMaterial = depthMaterialMorph;
 
 		} else {
 
-			depthMaterial = _depthMaterial;
+			newMaterial = depthMaterial;
 
 		}
 
-		depthMaterial.visible = material.visible;
-		depthMaterial.wireframe = material.wireframe;
-		depthMaterial.wireframeLinewidth = material.wireframeLinewidth;
+		newMaterial.visible = material.visible;
+		newMaterial.wireframe = material.wireframe;
+		newMaterial.wireframeLinewidth = material.wireframeLinewidth;
 
-		return depthMaterial;
+		if ( isCube ){
+			if(newMaterial.uniforms.lightPos)
+			{
+				newMaterial.uniforms.lightPos.value.copy(lightPosition);
+			}
+		}
+
+		return newMaterial;
 
 	}
 
 	function projectObject( object, camera ) {
 
+
 		if ( object.visible === false ) return;
 
 		if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) {
@@ -298,7 +399,6 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 				var material = object.material;
 
 				if ( material.visible === true ) {
-
 					object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
 					_renderList.push( object );
 

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