Forráskód Böngészése

Updated cubeToUV() to a reduced-instruction version with minimal branching, and updated near plane values for shadow map cameras to be at least 1.

mkkellogg 9 éve
szülő
commit
a7eed9d638

+ 281 - 280
examples/webgl_shadowmap_omnidirectional.html

@@ -1,280 +1,281 @@
-
-<!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 = 1;
-				pointLight.shadowCameraFar = 30;
-				pointLight.shadowDarkness = 0.5;
-				pointLight.shadowCameraVisible = true;
-				pointLight.shadowMapWidth = 2048;
-				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.set( -1, 3, -4 );
-				torusKnot.castShadow = true;
-				torusKnot.receiveShadow = true;
-				scene.add( torusKnot );
-			
-				wallMaterial = new THREE.MeshPhongMaterial( {
-					color: 0xa0adaf,
-					shininess: 10,
-					specular: 0x111111,
-					shading: THREE.SmoothShading
-				} );				
-
-				var wallGeometry = new THREE.BoxGeometry( 10, 0.15, 10 );
-				ground = new THREE.Mesh( wallGeometry, 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( wallGeometry, 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( wallGeometry, wallMaterial );
-				wall.name = "left wall";
-				wall.scale.multiplyScalar( 3 );
-				wall.castShadow = false;
-				wall.receiveShadow = true;				
-				scene.add( wall );
-				wall.position.set( -14, 10, 0 );
-				wall.rotation.z = Math.PI / 2;
-
-				wall = new THREE.Mesh( wallGeometry, wallMaterial );
-				wall.name = "right wall";
-				wall.scale.multiplyScalar( 3 );
-				wall.castShadow = false;
-				wall.receiveShadow = true;				
-				scene.add( wall );
-				wall.position.set(14,10,0);
-				wall.rotation.z = Math.PI / 2;
-
-				wall = new THREE.Mesh( wallGeometry, wallMaterial );
-				wall.name = "back wall";
-				wall.scale.multiplyScalar( 3 );
-				wall.castShadow = false;
-				wall.receiveShadow = true;				
-				scene.add( wall );
-				wall.position.set( 0, 10, -14 );
-				wall.rotation.y = Math.PI / 2;
-				wall.rotation.z = Math.PI / 2;
-
-				/*wall = new THREE.Mesh( wallGeometry, wallMaterial );
-				wall.name = "front wall";
-				wall.scale.multiplyScalar( 3 );
-				wall.castShadow = false;
-				wall.receiveShadow = true;				
-				scene.add( wall );
-				wall.position.set( 0, 10, 14 );
-				wall.rotation.y = Math.PI / 2;
-				wall.rotation.z = Math.PI / 2;*/
-
-				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 );	
-
-			}
-
-			function initMisc() {
-
-				renderer = new THREE.WebGLRenderer();
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.setClearColor( 0x000000 );				
-				renderer.shadowMap.enabled = true;
-				renderer.shadowMap.type = THREE.PCFShadowMap;
-
-				// 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 );
-			}
-
-			function render() {
-
-				var delta = clock.getDelta();
-
-				pointLightParent.rotation.y += delta * 2;
-				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;
-
-			}
-
-		</script>
-	</body>
-</html>
+
+<!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, 1, 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 = 1;
+				pointLight.shadowCameraFar = 30;
+				pointLight.shadowDarkness = 0.5;
+				pointLight.shadowCameraVisible = true;
+				pointLight.shadowMapWidth = 2048;
+				pointLight.shadowMapHeight = 1024;
+				pointLight.shadowBias = 0.1;
+				pointLight.name = 'Point Light';
+				scene.add( pointLight );
+
+				/*dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
+				dirLight.position.set( 0, 50, 0 );
+				dirLight.castShadow = true;
+				dirLight.shadowCameraNear = 1;
+				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.set( -1, 3, -4 );
+				torusKnot.castShadow = true;
+				torusKnot.receiveShadow = true;
+				scene.add( torusKnot );
+			
+				wallMaterial = new THREE.MeshPhongMaterial( {
+					color: 0xa0adaf,
+					shininess: 10,
+					specular: 0x111111,
+					shading: THREE.SmoothShading
+				} );				
+
+				var wallGeometry = new THREE.BoxGeometry( 10, 0.15, 10 );
+				ground = new THREE.Mesh( wallGeometry, 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( wallGeometry, 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( wallGeometry, wallMaterial );
+				wall.name = "left wall";
+				wall.scale.multiplyScalar( 3 );
+				wall.castShadow = false;
+				wall.receiveShadow = true;				
+				scene.add( wall );
+				wall.position.set( -14, 10, 0 );
+				wall.rotation.z = Math.PI / 2;
+
+				wall = new THREE.Mesh( wallGeometry, wallMaterial );
+				wall.name = "right wall";
+				wall.scale.multiplyScalar( 3 );
+				wall.castShadow = false;
+				wall.receiveShadow = true;				
+				scene.add( wall );
+				wall.position.set(14,10,0);
+				wall.rotation.z = Math.PI / 2;
+
+				wall = new THREE.Mesh( wallGeometry, wallMaterial );
+				wall.name = "back wall";
+				wall.scale.multiplyScalar( 3 );
+				wall.castShadow = false;
+				wall.receiveShadow = true;				
+				scene.add( wall );
+				wall.position.set( 0, 10, -14 );
+				wall.rotation.y = Math.PI / 2;
+				wall.rotation.z = Math.PI / 2;
+
+				/*wall = new THREE.Mesh( wallGeometry, wallMaterial );
+				wall.name = "front wall";
+				wall.scale.multiplyScalar( 3 );
+				wall.castShadow = false;
+				wall.receiveShadow = true;				
+				scene.add( wall );
+				wall.position.set( 0, 10, 14 );
+				wall.rotation.y = Math.PI / 2;
+				wall.rotation.z = Math.PI / 2;*/
+
+				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 );	
+
+			}
+
+			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 );
+			}
+
+			function render() {
+
+				var delta = clock.getDelta();
+
+				pointLightParent.rotation.y += delta * 2;
+				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;
+
+			}
+
+		</script>
+	</body>
+</html>

+ 2 - 2
examples/webgl_shadowmap_viewer.html

@@ -65,7 +65,7 @@
 
 			function initScene() {
 
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.01, 1000 );
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
 				camera.position.set( 0, 15, 35 );
 
 				scene = new THREE.Scene();
@@ -89,7 +89,7 @@
 				dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
 				dirLight.position.set( 0, 10, 0 );
 				dirLight.castShadow = true;
-				dirLight.shadowCameraNear = 0.01;
+				dirLight.shadowCameraNear = 1;
 				dirLight.shadowCameraFar = 10;
 				dirLight.shadowCameraRight = 15;
 				dirLight.shadowCameraLeft = -15;

+ 2 - 2
src/lights/PointLight.js

@@ -18,8 +18,8 @@ THREE.PointLight = function ( color, intensity, distance, decay ) {
 
 	//
 
-	this.shadowCameraNear = 0;
-	this.shadowCameraFar = 5000;
+	this.shadowCameraNear = 1;
+	this.shadowCameraFar = 500;
 	this.shadowCameraFov = 90;
 
 	this.shadowCameraVisible = false;

+ 36 - 48
src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl

@@ -28,10 +28,10 @@
 		/**
 		*  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:
-		*
-		*  Y y
+		*  2D texture:		
+		*  
 		*  xzXZ
+		*   y Y
 		*
 		*  Y - Positive y direction
 		*  y - Negative y direction
@@ -40,73 +40,61 @@
 		*  Z - Positive z direction
 		*  z - Negative z direction
 		*
-		*  Alternate code for different layouts, more compact code arrangement, and seam
-		*  skipping can be found here: https://gist.github.com/tschw/da10c43c467ce8afd0c4
+		*  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 ) {
 
-			// Horizontal cross layout:
-			const vec2 Squares = vec2( 4.0, 2.0 );
-			const vec2 Center = vec2( 1.0, 0.0 );
+			// Number of texels to avoid at the edge of each square
 
-			// Size of a square in UV space:
-			const vec2 TexSquareSize = 1.0 / Squares;
+			vec3 absV = abs( v );
 
-			// UV space offset of the center of the center square of the cross:
-			const vec2 TexCoordOffs = TexSquareSize * ( 0.5 + Center );
+			// Intersect unit cube
 
-			// Factors to scale square space (-1..+1 per square) to UV space:
-			const vec2 TexSquareScale = TexSquareSize * 0.5;
+			float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );
+			absV *= scaleToCube;
 
-			// Just less than a texel in square space when divided by resolution:
-			const float TexEps = 1.5; // = min(Squares.x, Squares.y) - 0.5;
+			// Apply scale to avoid seams
 
-			vec3 absV = abs( v );
-			vec3 sgnV = sign( v );
+			// two texels less per square (one texel will do for NEAREST)
+			v *= scaleToCube * ( 1.0 - 4.0 * texelSizeY );
 
-			// Intersect unit cube
+			// Unwrap
 
-			float scale = 1.0 / max( absV.x, max( absV.y, absV.z ) );
+			// space: -1 ... 1 range for each square
+			//
+			// #X##		dim    := ( 4 , 2 )
+			//  # #		center := ( 1 , 1 )
 
-			v *= scale; 
-			absV *= scale;
+			vec2 planar = v.xy;
 
-			// Determine gate factors
+			float almostATexel = 1.5 * texelSizeY;
+			float almostOne = 1.0 - almostATexel;
 
-			// gate.? is one when on left / right, bottom / top, back
-			float eps = TexEps * texelSizeY;
-			vec3 gate = step( 1.0 - eps, vec3( absV.xy, v.z ) );
+			if ( absV.z >= almostOne ) {
 
-			// prefer any square over bottom / top
-			float notX = 1. - gate.x;
-			float notZ = 1. - gate.z;
-			gate.y *= notX * notZ;
-			// prefer back over side
-			gate.x *= notZ;
+				if ( v.z > 0.0 )
+					planar.x = 4.0 - v.x;
 
-			// Unwrap
+			} else if ( absV.x >= almostOne ) {
 
-			// start with xy coordinates
-			vec2 planar = v.xy;
+				float signX = sign( v.x );
+				planar.x = v.z * signX + 2.0 * signX;
 
-			// stop at the last texel (can use a factor of 1.0 for NEAREST)
-			float yTexelSize = 2.0 * Squares.y * texelSizeY;
-			float yAdjusted = planar.y * ( 1.0 - yTexelSize );
-			planar.y = yAdjusted;
-			planar.y -= gate.y * yAdjusted;
+			} else if ( absV.y >= almostOne ) {
 
-			// unwrap left / right, top / bottom
-			planar.x += gate.x * ( sgnV.x + v.z * sgnV.x );
+				float signY = sign( v.y );
+				planar.x = v.x + 2.0 * signY + 2.0;
+				planar.y = v.z * signY - 2.0;
 
-			planar.x += gate.y * ( -sgnV.y * 2.0 );
-			planar.y += gate.y * ( 2.0  + ( v.z * sgnV.y ) );
+			}
 
-			// unwrap back
-			planar.x += gate.z * ( 4.0 - 2.0 * planar.x );
+			// Transform to UV space
 
-			// adjust to UV space
-			return TexCoordOffs + planar * TexSquareScale; 
+			// scale := 0.5 / dim
+			// translate := ( center + 0.5 ) / dim
+			return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );
 			
 		}
 

+ 24 - 7
src/renderers/webgl/WebGLShadowMap.js

@@ -160,18 +160,35 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 				var vpWidth = light.shadowMapWidth / 4.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
+				*
+				*/
+
 				// positive X
-				cube2DViewPorts[ 0 ].set( vpWidth * 2, 0, vpWidth, vpHeight );
+				cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
 				// negative X
-				cube2DViewPorts[ 1 ].set( 0, 0, vpWidth, vpHeight );
+				cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
 				// positive Z
-				cube2DViewPorts[ 2 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
+				cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
 				// negative Z
-				cube2DViewPorts[ 3 ].set( vpWidth, 0, vpWidth, vpHeight );
+				cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
 				// positive Y
-				cube2DViewPorts[ 4 ].set( 0, vpHeight, vpWidth, vpHeight );
+				cube2DViewPorts[ 4 ].set(  vpWidth * 3, 0, vpWidth, vpHeight );
 				// negative Y
-				cube2DViewPorts[ 5 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
+				cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
 
 			} else {
 
@@ -186,7 +203,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 				var shadowFilter = THREE.LinearFilter;
 
-				if ( scope.type === THREE.PCFSoftShadowMap || light instanceof THREE.PointLight ) {
+				if ( scope.type === THREE.PCFSoftShadowMap) {
 
 					shadowFilter = THREE.NearestFilter;