瀏覽代碼

CanvasRenderer & co finally renders MeshNormalMaterial properly.

Mr.doob 12 年之前
父節點
當前提交
ba2efcd53f

+ 93 - 69
build/three.js

@@ -5990,9 +5990,16 @@ THREE.Projector = function() {
 	_vector3 = new THREE.Vector3(),
 	_vector4 = new THREE.Vector4(),
 
+	_viewMatrix = new THREE.Matrix4(),
 	_viewProjectionMatrix = new THREE.Matrix4(),
+
+	_modelMatrix,
 	_modelViewProjectionMatrix = new THREE.Matrix4(),
+
 	_normalMatrix = new THREE.Matrix3(),
+	_normalViewMatrix = new THREE.Matrix3(),
+
+	_centroid = new THREE.Vector3(),
 
 	_frustum = new THREE.Frustum(),
 
@@ -6141,10 +6148,10 @@ THREE.Projector = function() {
 	this.projectScene = function ( scene, camera, sortObjects, sortElements ) {
 
 		var near = camera.near, far = camera.far, visible = false,
-		o, ol, v, vl, f, fl, n, nl, c, cl, u, ul, object, modelMatrix,
+		o, ol, v, vl, f, fl, n, nl, c, cl, u, ul, object,
 		geometry, vertices, vertex, vertexPositionScreen,
-		faces, face, faceVertexNormals, normal, faceVertexUvs, uvs,
-		v1, v2, v3, v4, isFaceMaterial, objectMaterials, material, side;
+		faces, face, faceVertexNormals, faceVertexUvs, uvs,
+		v1, v2, v3, v4, isFaceMaterial, objectMaterials;
 
 		_face3Count = 0;
 		_face4Count = 0;
@@ -6157,9 +6164,11 @@ THREE.Projector = function() {
 
 		if ( camera.parent === undefined ) camera.updateMatrixWorld();
 
-		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
+		_viewMatrix.getInverse( camera.matrixWorld );
+		_viewProjectionMatrix.multiply( camera.projectionMatrix, _viewMatrix );
 
-		_viewProjectionMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
+		_normalViewMatrix.getInverse( _viewMatrix );
+		_normalViewMatrix.transpose();
 
 		_frustum.setFromMatrix( _viewProjectionMatrix );
 
@@ -6169,7 +6178,7 @@ THREE.Projector = function() {
 
 			object = _renderData.objects[ o ].object;
 
-			modelMatrix = object.matrixWorld;
+			_modelMatrix = object.matrixWorld;
 
 			_vertexCount = 0;
 
@@ -6181,20 +6190,18 @@ THREE.Projector = function() {
 				faces = geometry.faces;
 				faceVertexUvs = geometry.faceVertexUvs;
 
-				_normalMatrix.getInverse( modelMatrix );
+				_normalMatrix.getInverse( _modelMatrix );
 				_normalMatrix.transpose();
 
 				isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
 				objectMaterials = isFaceMaterial === true ? object.material : null;
 
-				side = object.material.side;
-
 				for ( v = 0, vl = vertices.length; v < vl; v ++ ) {
 
 					_vertex = getNextVertexInPool();
 					_vertex.positionWorld.copy( vertices[ v ] );
 
-					modelMatrix.multiplyVector3( _vertex.positionWorld );
+					_modelMatrix.multiplyVector3( _vertex.positionWorld );
 
 					_vertex.positionScreen.copy( _vertex.positionWorld );
 					_viewProjectionMatrix.multiplyVector4( _vertex.positionScreen );
@@ -6210,11 +6217,13 @@ THREE.Projector = function() {
 
 					face = faces[ f ];
 
-					material = isFaceMaterial === true ? objectMaterials.materials[ face.materialIndex ] : object.material;
+					var material = isFaceMaterial === true
+						? objectMaterials.materials[ face.materialIndex ]
+						: object.material;
 
 					if ( material === undefined ) continue;
 
-					side = material.side;
+					var side = material.side;
 
 					if ( face instanceof THREE.Face3 ) {
 
@@ -6285,27 +6294,42 @@ THREE.Projector = function() {
 
 					}
 
-					_face.normalWorld.copy( face.normal );
+					_face.normalModel.copy( face.normal );
 
-					if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) _face.normalWorld.negate();
-					_normalMatrix.multiplyVector3( _face.normalWorld ).normalize();
+					if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
 
-					_face.centroidWorld.copy( face.centroid );
-					modelMatrix.multiplyVector3( _face.centroidWorld );
+						_face.normalModel.negate();
 
-					_face.centroidScreen.copy( _face.centroidWorld );
-					_viewProjectionMatrix.multiplyVector3( _face.centroidScreen );
+					}
+
+					_normalMatrix.multiplyVector3( _face.normalModel );
+					_face.normalModel.normalize();
+
+					_face.normalModelView.copy( _face.normalModel );
+					_normalViewMatrix.multiplyVector3( _face.normalModelView );
+
+					_face.centroidModel.copy( face.centroid );
+					_modelMatrix.multiplyVector3( _face.centroidModel );
 
 					faceVertexNormals = face.vertexNormals;
 
 					for ( n = 0, nl = faceVertexNormals.length; n < nl; n ++ ) {
 
-						normal = _face.vertexNormalsWorld[ n ];
-						normal.copy( faceVertexNormals[ n ] );
+						var normalModel = _face.vertexNormalsModel[ n ];
+						normalModel.copy( faceVertexNormals[ n ] );
+
+						if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
+
+							normalModel.negate();
+
+						}
 
-						if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) normal.negate();
+						_normalMatrix.multiplyVector3( normalModel )
+						normalModel.normalize();
 
-						_normalMatrix.multiplyVector3( normal ).normalize();
+						var normalModelView = _face.vertexNormalsModelView[ n ];
+						normalModelView.copy( normalModel );
+						_normalViewMatrix.multiplyVector3( normalModelView )
 
 					}
 
@@ -6328,7 +6352,10 @@ THREE.Projector = function() {
 					_face.color = face.color;
 					_face.material = material;
 
-					_face.z = _face.centroidScreen.z;
+					_centroid.copy( _face.centroidModel )
+					_viewProjectionMatrix.multiplyVector3( _centroid );
+
+					_face.z = _centroid.z;
 
 					_renderData.elements.push( _face );
 
@@ -6336,12 +6363,13 @@ THREE.Projector = function() {
 
 			} else if ( object instanceof THREE.Line ) {
 
-				_modelViewProjectionMatrix.multiply( _viewProjectionMatrix, modelMatrix );
+				_modelViewProjectionMatrix.multiply( _viewProjectionMatrix, _modelMatrix );
 
 				vertices = object.geometry.vertices;
 
 				v1 = getNextVertexInPool();
 				v1.positionScreen.copy( vertices[ 0 ] );
+
 				_modelViewProjectionMatrix.multiplyVector4( v1.positionScreen );
 
 				// Handle LineStrip and LinePieces
@@ -6351,6 +6379,7 @@ THREE.Projector = function() {
 
 					v1 = getNextVertexInPool();
 					v1.positionScreen.copy( vertices[ v ] );
+
 					_modelViewProjectionMatrix.multiplyVector4( v1.positionScreen );
 
 					if ( ( v + 1 ) % step > 0 ) continue;
@@ -6388,11 +6417,11 @@ THREE.Projector = function() {
 
 			object = _renderData.sprites[ o ].object;
 
-			modelMatrix = object.matrixWorld;
+			_modelMatrix = object.matrixWorld;
 
 			if ( object instanceof THREE.Particle ) {
 
-				_vector4.set( modelMatrix.elements[12], modelMatrix.elements[13], modelMatrix.elements[14], 1 );
+				_vector4.set( _modelMatrix.elements[12], _modelMatrix.elements[13], _modelMatrix.elements[14], 1 );
 				_viewProjectionMatrix.multiplyVector4( _vector4 );
 
 				_vector4.z /= _vector4.w;
@@ -14062,9 +14091,9 @@ THREE.CanvasRenderer = function ( parameters ) {
 						_color1.g = _color2.g = _color3.g = _ambientLight.g;
 						_color1.b = _color2.b = _color3.b = _ambientLight.b;
 
-						calculateLight( element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 );
-						calculateLight( element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 );
-						calculateLight( element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color3 );
+						calculateLight( element.v1.positionWorld, element.vertexNormalsModel[ 0 ], _color1 );
+						calculateLight( element.v2.positionWorld, element.vertexNormalsModel[ 1 ], _color2 );
+						calculateLight( element.v3.positionWorld, element.vertexNormalsModel[ 2 ], _color3 );
 
 						_color1.r = _color1.r * _diffuseColor.r + _emissiveColor.r;
 						_color1.g = _color1.g * _diffuseColor.g + _emissiveColor.g;
@@ -14092,7 +14121,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 						_color.g = _ambientLight.g;
 						_color.b = _ambientLight.b;
 
-						calculateLight( element.centroidWorld, element.normalWorld, _color );
+						calculateLight( element.centroidModel, element.normalModel, _color );
 
 						_color.r = _color.r * _diffuseColor.r + _emissiveColor.r;
 						_color.g = _color.g * _diffuseColor.g + _emissiveColor.g;
@@ -14128,19 +14157,17 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 					if ( material.envMap.mapping instanceof THREE.SphericalReflectionMapping ) {
 
-						var cameraMatrix = camera.matrixWorldInverse;
+						_vector3.copy( element.vertexNormalsModelView[ uv1 ] );
+						_uv1x = 0.5 * _vector3.x + 0.5;
+						_uv1y = 0.5 * _vector3.y + 0.5;
 
-						_vector3.copy( element.vertexNormalsWorld[ uv1 ] );
-						_uv1x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
-						_uv1y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
+						_vector3.copy( element.vertexNormalsModelView[ uv2 ] );
+						_uv2x = 0.5 * _vector3.x + 0.5;
+						_uv2y = 0.5 * _vector3.y + 0.5;
 
-						_vector3.copy( element.vertexNormalsWorld[ uv2 ] );
-						_uv2x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
-						_uv2y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
-
-						_vector3.copy( element.vertexNormalsWorld[ uv3 ] );
-						_uv3x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
-						_uv3y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
+						_vector3.copy( element.vertexNormalsModelView[ uv3 ] );
+						_uv3x = 0.5 * _vector3.x + 0.5;
+						_uv3y = 0.5 * _vector3.y + 0.5;
 
 						patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
 
@@ -14188,9 +14215,9 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 			} else if ( material instanceof THREE.MeshNormalMaterial ) {
 
-				_color.r = normalToComponent( element.normalWorld.x );
-				_color.g = normalToComponent( element.normalWorld.y );
-				_color.b = normalToComponent( element.normalWorld.z );
+				_color.r = 0.5 * element.normalModelView.x + 0.5;
+				_color.g = 0.5 * element.normalModelView.y + 0.5;
+				_color.b = 0.5 * element.normalModelView.z + 0.5;
 
 				material.wireframe === true
 					? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
@@ -14247,10 +14274,10 @@ THREE.CanvasRenderer = function ( parameters ) {
 						_color1.g = _color2.g = _color3.g = _color4.g = _ambientLight.g;
 						_color1.b = _color2.b = _color3.b = _color4.b = _ambientLight.b;
 
-						calculateLight( element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 );
-						calculateLight( element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 );
-						calculateLight( element.v4.positionWorld, element.vertexNormalsWorld[ 3 ], _color3 );
-						calculateLight( element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color4 );
+						calculateLight( element.v1.positionWorld, element.vertexNormalsModel[ 0 ], _color1 );
+						calculateLight( element.v2.positionWorld, element.vertexNormalsModel[ 1 ], _color2 );
+						calculateLight( element.v4.positionWorld, element.vertexNormalsModel[ 3 ], _color3 );
+						calculateLight( element.v3.positionWorld, element.vertexNormalsModel[ 2 ], _color4 );
 
 						_color1.r = _color1.r * _diffuseColor.r + _emissiveColor.r;
 						_color1.g = _color1.g * _diffuseColor.g + _emissiveColor.g;
@@ -14284,7 +14311,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 						_color.g = _ambientLight.g;
 						_color.b = _ambientLight.b;
 
-						calculateLight( element.centroidWorld, element.normalWorld, _color );
+						calculateLight( element.centroidModel, element.normalModel, _color );
 
 						_color.r = _color.r * _diffuseColor.r + _emissiveColor.r;
 						_color.g = _color.g * _diffuseColor.g + _emissiveColor.g;
@@ -14332,9 +14359,9 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 			} else if ( material instanceof THREE.MeshNormalMaterial ) {
 
-				_color.r = normalToComponent( element.normalWorld.x );
-				_color.g = normalToComponent( element.normalWorld.y );
-				_color.b = normalToComponent( element.normalWorld.z );
+				_color.r = 0.5 * element.normalModelView.x + 0.5;
+				_color.g = 0.5 * element.normalModelView.y + 0.5;
+				_color.b = 0.5 * element.normalModelView.z + 0.5;
 
 				drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
 
@@ -14575,13 +14602,6 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 		}
 
-		function normalToComponent( normal ) {
-
-			var component = ( normal + 1 ) * 0.5;
-			return component < 0 ? 0 : ( component > 1 ? 1 : component );
-
-		}
-
 		// Hide anti-alias gaps
 
 		function expand( v1, v2 ) {
@@ -24754,7 +24774,7 @@ THREE.RenderableVertex.prototype.copy = function ( vertex ) {
 	this.positionWorld.copy( vertex.positionWorld );
 	this.positionScreen.copy( vertex.positionScreen );
 
-}
+};
 /**
  * @author mrdoob / http://mrdoob.com/
  */
@@ -24765,12 +24785,14 @@ THREE.RenderableFace3 = function () {
 	this.v2 = new THREE.RenderableVertex();
 	this.v3 = new THREE.RenderableVertex();
 
-	this.centroidWorld = new THREE.Vector3();
-	this.centroidScreen = new THREE.Vector3();
+	this.centroidModel = new THREE.Vector3();
+
+	this.normalModel = new THREE.Vector3();
+	this.normalModelView = new THREE.Vector3();
 
-	this.normalWorld = new THREE.Vector3();
-	this.vertexNormalsWorld = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 	this.vertexNormalsLength = 0;
+	this.vertexNormalsModel = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
+	this.vertexNormalsModelView = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 
 	this.color = null;
 	this.material = null;
@@ -24790,12 +24812,14 @@ THREE.RenderableFace4 = function () {
 	this.v3 = new THREE.RenderableVertex();
 	this.v4 = new THREE.RenderableVertex();
 
-	this.centroidWorld = new THREE.Vector3();
-	this.centroidScreen = new THREE.Vector3();
+	this.centroidModel = new THREE.Vector3();
+
+	this.normalModel = new THREE.Vector3();
+	this.normalModelView = new THREE.Vector3();
 
-	this.normalWorld = new THREE.Vector3();
-	this.vertexNormalsWorld = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 	this.vertexNormalsLength = 0;
+	this.vertexNormalsModel = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
+	this.vertexNormalsModelView = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 
 	this.color = null;
 	this.material = null;

文件差異過大導致無法顯示
+ 195 - 196
build/three.min.js


+ 0 - 2
examples/canvas_materials.html

@@ -135,9 +135,7 @@
 				scene.add( pointLight );
 
 				renderer = new THREE.CanvasRenderer();
-				// renderer = new THREE.WebGLRenderer();
 				renderer.setSize( window.innerWidth, window.innerHeight );
-
 				container.appendChild( renderer.domElement );
 
 				var debugCanvas = document.createElement( 'canvas' );

+ 4 - 11
examples/js/renderers/SVGRenderer.js

@@ -364,7 +364,7 @@ THREE.SVGRenderer = function () {
 				_color.g = _ambientLight.g;
 				_color.b = _ambientLight.b;
 
-				calculateLight( _lights, element.centroidWorld, element.normalWorld, _color );
+				calculateLight( _lights, element.centroidModel, element.normalModel, _color );
 
 				_color.r = _color.r * _diffuseColor.r + _emissiveColor.r;
 				_color.g = _color.g * _diffuseColor.g + _emissiveColor.g;
@@ -383,7 +383,7 @@ THREE.SVGRenderer = function () {
 
 		} else if ( material instanceof THREE.MeshNormalMaterial ) {
 
-			_color.setRGB( normalToComponent( element.normalWorld.x ), normalToComponent( element.normalWorld.y ), normalToComponent( element.normalWorld.z ) );
+			_color.setRGB( 0.5 * element.normalModelView.x + 0.5, 0.5 * element.normalModelView.y + 0.5, 0.5 * element.normalModelView.z + 0.5 );
 
 		}
 
@@ -440,7 +440,7 @@ THREE.SVGRenderer = function () {
 				_color.g = _ambientLight.g;
 				_color.b = _ambientLight.b;
 
-				calculateLight( _lights, element.centroidWorld, element.normalWorld, _color );
+				calculateLight( _lights, element.centroidModel, element.normalModel, _color );
 
 				_color.r = _color.r * _diffuseColor.r + _emissiveColor.r;
 				_color.g = _color.g * _diffuseColor.g + _emissiveColor.g;
@@ -459,7 +459,7 @@ THREE.SVGRenderer = function () {
 
 		} else if ( material instanceof THREE.MeshNormalMaterial ) {
 
-			_color.setRGB( normalToComponent( element.normalWorld.x ), normalToComponent( element.normalWorld.y ), normalToComponent( element.normalWorld.z ) );
+			_color.setRGB( 0.5 * element.normalModelView.x + 0.5, 0.5 * element.normalModelView.y + 0.5, 0.5 * element.normalModelView.z + 0.5 );
 
 		}
 
@@ -537,13 +537,6 @@ THREE.SVGRenderer = function () {
 
 	}
 
-	function normalToComponent( normal ) {
-
-		var component = ( normal + 1 ) * 0.5;
-		return component < 0 ? 0 : ( component > 1 ? 1 : component );
-
-	}
-
 	function pad( str ) {
 
 		while ( str.length < 6 ) str = '0' + str;

+ 219 - 173
examples/js/renderers/SoftwareRenderer.js

@@ -1,5 +1,6 @@
 /**
  * @author mrdoob / http://mrdoob.com/
+ * @author mraleph / http://mrale.ph/
  */
 
 THREE.SoftwareRenderer = function () {
@@ -9,17 +10,27 @@ THREE.SoftwareRenderer = function () {
 	var canvas = document.createElement( 'canvas' );
 	var context = canvas.getContext( '2d' );
 
-	var imagedata = context.getImageData( 0, 0, canvas.width, canvas.height );
-	var data = imagedata.data;
-
 	var canvasWidth = canvas.width;
 	var canvasHeight = canvas.height;
 
 	var canvasWidthHalf = canvasWidth / 2;
 	var canvasHeightHalf = canvasHeight / 2;
 
-	var edges = [ new Edge(), new Edge(), new Edge() ];
-	var span = new Span();
+	var imagedata = context.getImageData( 0, 0, canvas.width, canvas.height );
+	var data = imagedata.data;
+
+	var blocksize = 8;
+
+	var canvasWBlocks = Math.floor( ( canvasWidth + blocksize - 1 ) / blocksize );
+	var canvasHBlocks = Math.floor( ( canvasHeight + blocksize - 1 ) / blocksize );
+
+	var block_full = new Uint8Array( canvasWBlocks * canvasHBlocks );
+
+	var rectx1 = Infinity, recty1 = Infinity;
+	var rectx2 = 0, recty2 = 0;
+
+	var prevrectx1 = Infinity, prevrecty1 = Infinity;
+	var prevrectx2 = 0, prevrecty2 = 0;
 
 	var projector = new THREE.Projector();
 
@@ -41,13 +52,22 @@ THREE.SoftwareRenderer = function () {
 		imagedata = context.getImageData( 0, 0, width, height );
 		data = imagedata.data;
 
+		canvasWBlocks = Math.floor( ( canvasWidth + blocksize - 1 ) / blocksize );
+		canvasHBlocks = Math.floor( ( canvasHeight + blocksize - 1 ) / blocksize );
+
+		console.log( canvasWBlocks, canvasHBlocks );
+
+		block_full = new Uint8Array( canvasWBlocks * canvasHBlocks )
+
 	};
 
 	this.clear = function () {
 
-		for ( var i = 3, l = data.length; i < l; i += 4 ) {
+		clearRectangle( prevrectx1, prevrecty1, prevrectx2, prevrecty2 );
+
+		for ( var i = 0, l = block_full.length; i < l; i ++ ) {
 
-			data[ i ] = 0;
+			block_full[ i ] = 0;
 
 		}
 
@@ -55,14 +75,17 @@ THREE.SoftwareRenderer = function () {
 
 	this.render = function ( scene, camera ) {
 
-		var m, ml, element, material, dom, v1x, v1y;
+		rectx1 = Infinity;
+		recty1 = Infinity;
+		rectx2 = 0;
+		recty2 = 0;
 
 		if ( this.autoClear ) this.clear();
 
 		var renderData = projector.projectScene( scene, camera );
 		var elements = renderData.elements;
 
-		elements.sort( function painterSort( a, b ) { return a.z - b.z; } );
+		elements.sort( numericalSort );
 
 		for ( var e = 0, el = elements.length; e < el; e ++ ) {
 
@@ -77,13 +100,13 @@ THREE.SoftwareRenderer = function () {
 				drawTriangle(
 					v1.x * canvasWidthHalf + canvasWidthHalf,
 					- v1.y * canvasHeightHalf + canvasHeightHalf,
-					0xff0000,
 					v2.x * canvasWidthHalf + canvasWidthHalf,
 					- v2.y * canvasHeightHalf + canvasHeightHalf,
-					0x00ff00,
 					v3.x * canvasWidthHalf + canvasWidthHalf,
 					- v3.y * canvasHeightHalf + canvasHeightHalf,
-					0x0000ff
+					0.5 * element.normalModelView.x + 0.5,
+					0.5 * element.normalModelView.y + 0.5,
+					0.5 * element.normalModelView.z + 0.5
 				)
 
 			} else if ( element instanceof THREE.RenderableFace4 ) {
@@ -96,42 +119,53 @@ THREE.SoftwareRenderer = function () {
 				drawTriangle(
 					v1.x * canvasWidthHalf + canvasWidthHalf,
 					- v1.y * canvasHeightHalf + canvasHeightHalf,
-					0xff0000,
 					v2.x * canvasWidthHalf + canvasWidthHalf,
 					- v2.y * canvasHeightHalf + canvasHeightHalf,
-					0x00ff00,
 					v3.x * canvasWidthHalf + canvasWidthHalf,
 					- v3.y * canvasHeightHalf + canvasHeightHalf,
-					0x0000ff
+					0.5 * element.normalModelView.x + 0.5,
+					0.5 * element.normalModelView.y + 0.5,
+					0.5 * element.normalModelView.z + 0.5
 				);
 
 				drawTriangle(
 					v3.x * canvasWidthHalf + canvasWidthHalf,
 					- v3.y * canvasHeightHalf + canvasHeightHalf,
-					0x0000ff,
 					v4.x * canvasWidthHalf + canvasWidthHalf,
 					- v4.y * canvasHeightHalf + canvasHeightHalf,
-					0xff00ff,
 					v1.x * canvasWidthHalf + canvasWidthHalf,
 					- v1.y * canvasHeightHalf + canvasHeightHalf,
-					0xff0000
+					0.5 * element.normalModelView.x + 0.5,
+					0.5 * element.normalModelView.y + 0.5,
+					0.5 * element.normalModelView.z + 0.5
 				);
 
 			}
 
 		}
 
-		context.putImageData( imagedata, 0, 0 );
+		var x = Math.min( rectx1, prevrectx1 );
+		var y = Math.min( recty1, prevrecty1 );
+		var width = Math.max( rectx2, prevrectx2 ) - x;
+		var height = Math.max( recty2, prevrecty2 ) - y;
+
+		context.putImageData( imagedata, 0, 0, x, y, width, height );
+
+		prevrectx1 = rectx1; prevrecty1 = recty1;
+		prevrectx2 = rectx2; prevrecty2 = recty2;
 
 	};
 
+	function numericalSort( a, b ) {
+
+		return a.z - b.z;
+
+	}
+
 	function drawPixel( x, y, r, g, b ) {
 
 		var offset = ( x + y * canvasWidth ) * 4;
 
-		if ( x < 0 || y < 0 ) return;
-		if ( x > canvasWidth || y > canvasHeight ) return;
-
 		if ( data[ offset + 3 ] ) return;
 
 		data[ offset ] = r;
@@ -141,232 +175,244 @@ THREE.SoftwareRenderer = function () {
 
 	}
 
-	/*
-	function drawRectangle( x1, y1, x2, y2, color ) {
+	function clearRectangle( x1, y1, x2, y2 ) {
 
-		var r = color >> 16 & 255;
-		var g = color >> 8 & 255;
-		var b = color & 255;
+		var xmin = Math.max( Math.min( x1, x2 ), 0 );
+		var xmax = Math.min( Math.max( x1, x2 ), canvasWidth );
+		var ymin = Math.max( Math.min( y1, y2 ), 0 );
+		var ymax = Math.min( Math.max( y1, y2 ), canvasHeight );
 
-		var xmin = Math.min( x1, x2 ) >> 0;
-		var xmax = Math.max( x1, x2 ) >> 0;
-		var ymin = Math.min( y1, y2 ) >> 0;
-		var ymax = Math.max( y1, y2 ) >> 0;
+		var offset = ( xmin + ymin * canvasWidth - 1 ) * 4 + 3;
+		var linestep = ( canvasWidth - ( xmax - xmin ) ) * 4;
 
 		for ( var y = ymin; y < ymax; y ++ ) {
 
 			for ( var x = xmin; x < xmax; x ++ ) {
 
-				drawPixel( x, y, r, g, b );
+				data[ offset += 4 ] = 0;
 
 			}
 
+			offset += linestep;
+
 		}
 
 	}
-	*/
-
-	function drawTriangle( x1, y1, color1, x2, y2, color2, x3, y3, color3 ) {
-
-		// http://joshbeam.com/articles/triangle_rasterization/
 
-		edges[ 0 ].set( x1, y1, color1, x2, y2, color2 );
-		edges[ 1 ].set( x2, y2, color2, x3, y3, color3 );
-		edges[ 2 ].set( x3, y3, color3, x1, y1, color1 );
+	function drawTriangle( x1, y1, x2, y2, x3, y3, r, g, b ) {
 
-		var maxLength = 0;
-		var longEdge = 0;
+		// https://gist.github.com/2486101
+		// explanation: ttp://pouet.net/topic.php?which=8760&page=1
 
-		// find edge with the greatest length in the y axis
+		// 28.4 fixed-point coordinates
 
-		for ( var i = 0; i < 3; i ++ ) {
+		var x1 = (16 * x1) | 0;
+		var x2 = (16 * x2) | 0;
+		var x3 = (16 * x3) | 0;
 
-			var length = ( edges[ i ].y2 - edges[ i ].y1 );
+		var y1 = (16 * y1) | 0;
+		var y2 = (16 * y2) | 0;
+		var y3 = (16 * y3) | 0;
 
-			if ( length > maxLength ) {
+		// Deltas
 
-				maxLength = length;
-				longEdge = i;
+		var dx12 = x1 - x2, dy12 = y2 - y1;
+		var dx23 = x2 - x3, dy23 = y3 - y2;
+		var dx31 = x3 - x1, dy31 = y1 - y3;
 
-			}
-		}
+		// Bounding rectangle
 
-		var shortEdge1 = ( longEdge + 1 ) % 3;
-		var shortEdge2 = ( longEdge + 2 ) % 3;
+		var minx = Math.max( ( Math.min( x1, x2, x3 ) + 0xf ) >> 4, 0 );
+		var maxx = Math.min( ( Math.max( x1, x2, x3 ) + 0xf ) >> 4, canvasWidth );
+		var miny = Math.max( ( Math.min( y1, y2, y3 ) + 0xf ) >> 4, 0 );
+		var maxy = Math.min( ( Math.max( y1, y2, y3 ) + 0xf ) >> 4, canvasHeight );
 
-		drawSpans( edges[ longEdge ], edges[ shortEdge1 ] );
-		drawSpans( edges[ longEdge ], edges[ shortEdge2 ] );
+		rectx1 = Math.min( minx, rectx1 );
+		rectx2 = Math.max( maxx, rectx2 );
+		recty1 = Math.min( miny, recty1 );
+		recty2 = Math.max( maxy, recty2 );
 
-	}
+		// Block size, standard 8x8 (must be power of two)
 
-	function drawSpans( e1, e2 ) {
+		var q = blocksize;
 
-		var e1ydiff = e1.y2 - e1.y1;
-		if ( e1ydiff === 0 ) return;
+		// Start in corner of 8x8 block
 
-		var e2ydiff = e2.y2 - e2.y1;
-		if ( e2ydiff === 0 ) return;
+		minx &= ~(q - 1);
+		miny &= ~(q - 1);
 
-		var e1xdiff = e1.x2 - e1.x1;
-		var e2xdiff = e2.x2 - e2.x1;
+		// Constant part of half-edge functions
 
-		var e1colordiffr = e1.r2 - e1.r1;
-		var e1colordiffg = e1.g2 - e1.g1;
-		var e1colordiffb = e1.b2 - e1.b1;
+		var c1 = dy12 * ((minx << 4) - x1) + dx12 * ((miny << 4) - y1);
+		var c2 = dy23 * ((minx << 4) - x2) + dx23 * ((miny << 4) - y2);
+		var c3 = dy31 * ((minx << 4) - x3) + dx31 * ((miny << 4) - y3);
 
-		var e2colordiffr = e2.r2 - e2.r1;
-		var e2colordiffg = e2.g2 - e2.g1;
-		var e2colordiffb = e2.b2 - e2.b1;
+		// Correct for fill convention
 
-		var factor1 = ( e2.y1 - e1.y1 ) / e1ydiff;
-		var factorStep1 = 1 / e1ydiff;
-		var factor2 = 0;
-		var factorStep2 = 1 / e2ydiff;
+		if ( dy12 > 0 || ( dy12 == 0 && dx12 > 0 ) ) c1 ++;
+		if ( dy23 > 0 || ( dy23 == 0 && dx23 > 0 ) ) c2 ++;
+		if ( dy31 > 0 || ( dy31 == 0 && dx31 > 0 ) ) c3 ++;
 
+		// Note this doesn't kill subpixel precision, but only because we test for >=0 (not >0).
+		// It's a bit subtle. :)
+		c1 = (c1 - 1) >> 4;
+		c2 = (c2 - 1) >> 4;
+		c3 = (c3 - 1) >> 4;
 
-		for ( var y = e2.y1; y < e2.y2; y ++ ) {
+		// Set up min/max corners
+		var qm1 = q - 1; // for convenience
+		var nmin1 = 0, nmax1 = 0;
+		var nmin2 = 0, nmax2 = 0;
+		var nmin3 = 0, nmax3 = 0;
+		if (dx12 >= 0) nmax1 -= qm1*dx12; else nmin1 -= qm1*dx12;
+		if (dy12 >= 0) nmax1 -= qm1*dy12; else nmin1 -= qm1*dy12;
+		if (dx23 >= 0) nmax2 -= qm1*dx23; else nmin2 -= qm1*dx23;
+		if (dy23 >= 0) nmax2 -= qm1*dy23; else nmin2 -= qm1*dy23;
+		if (dx31 >= 0) nmax3 -= qm1*dx31; else nmin3 -= qm1*dx31;
+		if (dy31 >= 0) nmax3 -= qm1*dy31; else nmin3 -= qm1*dy31;
 
-			span.set(
-				e1.x1 + ( e1xdiff * factor1 ),
-				e1.r1 + e1colordiffr * factor1,
-				e1.g1 + e1colordiffg * factor1,
-				e1.b1 + e1colordiffb * factor1,
+		// Loop through blocks
+		var linestep = (canvasWidth - q) * 4;
+		var scale = 255.0 / (c1 + c2 + c3);
 
-				e2.x1 + ( e2xdiff * factor2 ),
-				e2.r1 + e2colordiffr * factor2,
-				e2.g1 + e2colordiffg * factor2,
-				e2.b1 + e2colordiffb * factor2
-			);
+		var cb1 = c1;
+		var cb2 = c2;
+		var cb3 = c3;
+		var qstep = -q;
+		var e1x = qstep * dy12;
+		var e2x = qstep * dy23;
+		var e3x = qstep * dy31;
+		var x0 = minx;
 
-			var xdiff = span.x2 - span.x1;
-			if ( xdiff > 0 ) {
+		for (var y0 = miny; y0 < maxy; y0 += q) {
 
-				var colordiffr = span.r2 - span.r1;
-				var colordiffg = span.g2 - span.g1;
-				var colordiffb = span.b2 - span.b1;
+			// New block line - keep hunting for tri outer edge in old block line dir
+			while (x0 >= minx && x0 < maxx && cb1 >= nmax1 && cb2 >= nmax2 && cb3 >= nmax3) {
 
-				var factor = 0;
-				var factorStep = 1 / xdiff;
-
-				for ( var x = span.x1; x < span.x2; x ++ ) {
-
-					var r = span.r1 + colordiffr * factor;
-					var g = span.g1 + colordiffg * factor;
-					var b = span.b1 + colordiffb * factor;
-
-					drawPixel( x, y, r, g, b );
-					factor += factorStep;
-
-				}
+				x0 += qstep;
+				cb1 += e1x;
+				cb2 += e2x;
+				cb3 += e3x;
 
 			}
 
-			factor1 += factorStep1;
-			factor2 += factorStep2;
+			// Okay, we're now in a block we know is outside. Reverse direction and go into main loop.
+			qstep = -qstep;
+			e1x = -e1x;
+			e2x = -e2x;
+			e3x = -e3x;
 
-		}
-
-	}
-
-	function Edge() {
-
-		this.x1 = 0;
-		this.y1 = 0;
+			while (1) {
 
-		this.x2 = 0;
-		this.y2 = 0;
+				// Step everything
+				x0 += qstep;
+				cb1 += e1x;
+				cb2 += e2x;
+				cb3 += e3x;
 
-		this.r1 = 0;
-		this.g1 = 0;
-		this.b1 = 0;
+				// We're done with this block line when at least one edge completely out
+				// If an edge function is too small and decreasing in the current traversal
+				// dir, we're done with this line.
+				if (x0 < minx || x0 >= maxx) break;
+				if (cb1 < nmax1) if (e1x < 0) break; else continue;
+				if (cb2 < nmax2) if (e2x < 0) break; else continue;
+				if (cb3 < nmax3) if (e3x < 0) break; else continue;
 
-		this.r2 = 0;
-		this.g2 = 0;
-		this.b2 = 0;
+				// We can skip this block if it's already fully covered
+				var blockX = (x0 / q) | 0;
+				var blockY = (y0 / q) | 0;
+				var blockInd = blockX + blockY * canvasWBlocks;
+				if (block_full[blockInd]) continue;
 
-		this.set = function ( x1, y1, color1, x2, y2, color2 ) {
+				// Offset at top-left corner
+				var offset = (x0 + y0 * canvasWidth) * 4;
 
-			if ( y1 < y2 ) {
+				// Accept whole block when fully covered
+				if (cb1 >= nmin1 && cb2 >= nmin2 && cb3 >= nmin3) {
 
-				this.x1 = x1 >> 0;
-				this.y1 = y1 >> 0;
+					var cy1 = cb1;
+					var cy2 = cb2;
 
-				this.x2 = x2 >> 0;
-				this.y2 = y2 >> 0;
+					for ( var iy = 0; iy < q; iy ++ ) {
 
-				this.r1 = color1 >> 16 & 255;
-				this.g1 = color1 >> 8 & 255;
-				this.b1 = color1 & 255;
+						var cx1 = cy1;
+						var cx2 = cy2;
 
-				this.r2 = color2 >> 16 & 255;
-				this.g2 = color2 >> 8 & 255;
-				this.b2 = color2 & 255;
+						for ( var ix = 0; ix < q; ix ++ ) {
 
-			} else {
+							if (!data[offset + 3]) {
 
-				this.x1 = x2 >> 0;
-				this.y1 = y2 >> 0;
+								var u = cx1 * scale; // 0-255!
+								var v = cx2 * scale; // 0-255!
+								data[offset] = u;
+								data[offset + 1] = v;
+								data[offset + 2] = 0;
+								data[offset + 3] = 255;
 
-				this.x2 = x1 >> 0;
-				this.y2 = y1 >> 0;
+							}
 
-				this.r1 = color2 >> 16 & 255;
-				this.g1 = color2 >> 8 & 255;
-				this.b1 = color2 & 255;
+							cx1 += dy12;
+							cx2 += dy23;
+							offset += 4;
 
-				this.r2 = color1 >> 16 & 255;
-				this.g2 = color1 >> 8 & 255;
-				this.b2 = color1 & 255;
+						}
 
-			}
+						cy1 += dx12;
+						cy2 += dx23;
+						offset += linestep;
 
-		}
+					}
 
-	}
+					block_full[blockInd] = 1;
 
-	function Span() {
+				} else { // Partially covered block
 
-		this.x1 = 0;
-		this.x2 = 0;
+					var cy1 = cb1;
+					var cy2 = cb2;
+					var cy3 = cb3;
 
-		this.r1 = 0;
-		this.g1 = 0;
-		this.b1 = 0;
+					for ( var iy = 0; iy < q; iy ++ ) {
 
-		this.r2 = 0;
-		this.g2 = 0;
-		this.b2 = 0;
+						var cx1 = cy1;
+						var cx2 = cy2;
+						var cx3 = cy3;
 
-		this.set = function ( x1, r1, g1, b1, x2, r2, g2, b2 ) {
+						for ( var ix = 0; ix < q; ix ++ ) {
 
-			if ( x1 < x2 ) {
+							if ( (cx1 | cx2 | cx3) >= 0 && !data[offset+3]) {
 
-				this.x1 = x1 >> 0;
-				this.x2 = x2 >> 0;
+								var u = cx1 * scale; // 0-255!
+								var v = cx2 * scale; // 0-255!
+								data[offset] = u;
+								data[offset + 1] = v;
+								data[offset + 2] = 0;
+								data[offset + 3] = 255;
 
-				this.r1 = r1;
-				this.g1 = g1;
-				this.b1 = b1;
+							}
 
-				this.r2 = r2;
-				this.g2 = g2;
-				this.b2 = b2;
+							cx1 += dy12;
+							cx2 += dy23;
+							cx3 += dy31;
+							offset += 4;
 
-			} else {
+						}
 
-				this.x1 = x2 >> 0;
-				this.x2 = x1 >> 0;
+						cy1 += dx12;
+						cy2 += dx23;
+						cy3 += dx31;
+						offset += linestep;
 
-				this.r1 = r2;
-				this.g1 = g2;
-				this.b1 = b2;
+					}
 
-				this.r2 = r1;
-				this.g2 = g1;
-				this.b2 = b1;
+				}
 
 			}
 
+			// Advance to next row of blocks
+			cb1 += q*dx12;
+			cb2 += q*dx23;
+			cb3 += q*dx31;
+
 		}
 
 	}

+ 0 - 409
examples/js/renderers/SoftwareRenderer2.js

@@ -1,409 +0,0 @@
-/**
- * @author mrdoob / http://mrdoob.com/
- */
-
-THREE.SoftwareRenderer2 = function () {
-
-	console.log( 'THREE.SoftwareRenderer', THREE.REVISION );
-
-	var canvas = document.createElement( 'canvas' );
-	var context = canvas.getContext( '2d' );
-
-	var imagedata = context.getImageData( 0, 0, canvas.width, canvas.height );
-	var data = imagedata.data;
-
-	var canvasWidth = canvas.width;
-	var canvasHeight = canvas.height;
-
-	var canvasWidthHalf = canvasWidth / 2;
-	var canvasHeightHalf = canvasHeight / 2;
-
-	var rectx1 = Infinity, recty1 = Infinity;
-	var rectx2 = 0, recty2 = 0;
-
-	var prevrectx1 = Infinity, prevrecty1 = Infinity;
-	var prevrectx2 = 0, prevrecty2 = 0;
-
-	var projector = new THREE.Projector();
-
-	this.domElement = canvas;
-
-	this.autoClear = true;
-
-	this.setSize = function ( width, height ) {
-
-		canvas.width = width;
-		canvas.height = height;
-
-		canvasWidth = canvas.width;
-		canvasHeight = canvas.height;
-
-		canvasWidthHalf = width / 2;
-		canvasHeightHalf = height / 2;
-
-		imagedata = context.getImageData( 0, 0, width, height );
-		data = imagedata.data;
-
-	};
-
-	this.clear = function () {
-
-		clearRectangle( prevrectx1, prevrecty1, prevrectx2, prevrecty2 );
-
-	};
-
-	this.render = function ( scene, camera ) {
-
-		rectx1 = Infinity;
-		recty1 = Infinity;
-		rectx2 = 0;
-		recty2 = 0;
-
-		if ( this.autoClear ) this.clear();
-
-		var renderData = projector.projectScene( scene, camera );
-		var elements = renderData.elements;
-
-		elements.sort( numericalSort );
-
-		for ( var e = 0, el = elements.length; e < el; e ++ ) {
-
-			var element = elements[ e ];
-
-			if ( element instanceof THREE.RenderableFace3 ) {
-
-				var v1 = element.v1.positionScreen;
-				var v2 = element.v2.positionScreen;
-				var v3 = element.v3.positionScreen;
-
-				drawTriangle(
-					v1.x * canvasWidthHalf + canvasWidthHalf,
-					- v1.y * canvasHeightHalf + canvasHeightHalf,
-					v2.x * canvasWidthHalf + canvasWidthHalf,
-					- v2.y * canvasHeightHalf + canvasHeightHalf,
-					v3.x * canvasWidthHalf + canvasWidthHalf,
-					- v3.y * canvasHeightHalf + canvasHeightHalf,
-					normalToComponent( element.normalWorld.x ),
-					normalToComponent( element.normalWorld.y ),
-					normalToComponent( element.normalWorld.z )
-				)
-
-			} else if ( element instanceof THREE.RenderableFace4 ) {
-
-				var v1 = element.v1.positionScreen;
-				var v2 = element.v2.positionScreen;
-				var v3 = element.v3.positionScreen;
-				var v4 = element.v4.positionScreen;
-
-				drawTriangle(
-					v1.x * canvasWidthHalf + canvasWidthHalf,
-					- v1.y * canvasHeightHalf + canvasHeightHalf,
-					v2.x * canvasWidthHalf + canvasWidthHalf,
-					- v2.y * canvasHeightHalf + canvasHeightHalf,
-					v3.x * canvasWidthHalf + canvasWidthHalf,
-					- v3.y * canvasHeightHalf + canvasHeightHalf,
-					normalToComponent( element.normalWorld.x ),
-					normalToComponent( element.normalWorld.y ),
-					normalToComponent( element.normalWorld.z )
-				);
-
-				drawTriangle(
-					v3.x * canvasWidthHalf + canvasWidthHalf,
-					- v3.y * canvasHeightHalf + canvasHeightHalf,
-					v4.x * canvasWidthHalf + canvasWidthHalf,
-					- v4.y * canvasHeightHalf + canvasHeightHalf,
-					v1.x * canvasWidthHalf + canvasWidthHalf,
-					- v1.y * canvasHeightHalf + canvasHeightHalf,
-					normalToComponent( element.normalWorld.x ),
-					normalToComponent( element.normalWorld.y ),
-					normalToComponent( element.normalWorld.z )
-				);
-
-			}
-
-		}
-
-		var x = Math.min( rectx1, prevrectx1 );
-		var y = Math.min( recty1, prevrecty1 );
-		var width = Math.max( rectx2, prevrectx2 ) - x;
-		var height = Math.max( recty2, prevrecty2 ) - y;
-
-		/*
-		console.log( rectx1, recty1, rectx2, recty2 );
-		console.log( prevrectx1, prevrecty1, prevrectx2, prevrecty2 );
-		console.log( x, y, width, height );
-		console.log( canvasWidth, canvasHeight );
-		*/
-
-		context.putImageData( imagedata, 0, 0, x, y, width, height );
-
-		prevrectx1 = rectx1; prevrecty1 = recty1;
-		prevrectx2 = rectx2; prevrecty2 = recty2;
-
-	};
-
-	function numericalSort( a, b ) {
-
-		return a.z - b.z;
-
-	}
-
-	function drawPixel( x, y, r, g, b ) {
-
-		var offset = ( x + y * canvasWidth ) * 4;
-
-		if ( data[ offset + 3 ] ) return;
-
-		data[ offset ] = r;
-		data[ offset + 1 ] = g;
-		data[ offset + 2 ] = b;
-		data[ offset + 3 ] = 255;
-
-	}
-
-	function clearRectangle( x1, y1, x2, y2 ) {
-
-		var xmin = Math.max( Math.min( x1, x2 ), 0 );
-		var xmax = Math.min( Math.max( x1, x2 ), canvasWidth );
-		var ymin = Math.max( Math.min( y1, y2 ), 0 );
-		var ymax = Math.min( Math.max( y1, y2 ), canvasHeight );
-
-		var offset = ( xmin + ymin * canvasWidth ) * 4 + 3;
-		var linestep = ( canvasWidth - ( xmax - xmin ) ) * 4;
-
-		for ( var y = ymin; y < ymax; y ++ ) {
-
-			for ( var x = xmin; x < xmax; x ++ ) {
-
-				data[ offset ] = 0;
-				offset += 4;
-
-			}
-
-			offset += linestep;
-
-		}
-
-	}
-
-	function drawTriangle( x1, y1, x2, y2, x3, y3, r, g, b ) {
-
-		// http://devmaster.net/forums/topic/1145-advanced-rasterization/
-
-		// 28.4 fixed-point coordinates
-
-		var x1 = Math.round( 16 * x1 );
-		var x2 = Math.round( 16 * x2 );
-		var x3 = Math.round( 16 * x3 );
-
-		var y1 = Math.round( 16 * y1 );
-		var y2 = Math.round( 16 * y2 );
-		var y3 = Math.round( 16 * y3 );
-
-		// Deltas
-
-		var dx12 = x1 - x2;
-		var dx23 = x2 - x3;
-		var dx31 = x3 - x1;
-
-		var dy12 = y1 - y2;
-		var dy23 = y2 - y3;
-		var dy31 = y3 - y1;
-
-		// Fixed-point deltas
-
-		var fdx12 = dx12 << 4;
-		var fdx23 = dx23 << 4;
-		var fdx31 = dx31 << 4;
-
-		var fdy12 = dy12 << 4;
-		var fdy23 = dy23 << 4;
-		var fdy31 = dy31 << 4;
-
-		// Bounding rectangle
-
-		var xmin = Math.max( ( Math.min( x1, x2, x3 ) + 0xf ) >> 4, 0 );
-		var xmax = Math.min( ( Math.max( x1, x2, x3 ) + 0xf ) >> 4, canvasWidth );
-		var ymin = Math.max( ( Math.min( y1, y2, y3 ) + 0xf ) >> 4, 0 );
-		var ymax = Math.min( ( Math.max( y1, y2, y3 ) + 0xf ) >> 4, canvasHeight );
-
-		rectx1 = Math.min( xmin, rectx1 );
-		rectx2 = Math.max( xmax, rectx2 );
-		recty1 = Math.min( ymin, recty1 );
-		recty2 = Math.max( ymax, recty2 );
-
-		// Constant part of half-edge functions
-
-		var c1 = dy12 * x1 - dx12 * y1;
-		var c2 = dy23 * x2 - dx23 * y2;
-		var c3 = dy31 * x3 - dx31 * y3;
-
-		// Correct for fill convention
-
-		if ( dy12 < 0 || ( dy12 == 0 && dx12 > 0 ) ) c1 ++;
-		if ( dy23 < 0 || ( dy23 == 0 && dx23 > 0 ) ) c2 ++;
-		if ( dy31 < 0 || ( dy31 == 0 && dx31 > 0 ) ) c3++;
-
-		var cy1 = c1 + dx12 * ( ymin << 4 ) - dy12 * ( xmin << 4 );
-		var cy2 = c2 + dx23 * ( ymin << 4 ) - dy23 * ( xmin << 4 );
-		var cy3 = c3 + dx31 * ( ymin << 4 ) - dy31 * ( xmin << 4 );
-
-		// Scan through bounding rectangle
-
-		for ( var y = ymin; y < ymax; y ++ ) {
-
-			// Start value for horizontal scan
-
-			var cx1 = cy1;
-			var cx2 = cy2;
-			var cx3 = cy3;
-
-			for ( var x = xmin; x < xmax; x ++ ) {
-
-				if ( cx1 > 0 && cx2 > 0 && cx3 > 0 ) {
-
-					drawPixel( x, y, r, g, b );
-
-				}
-
-				cx1 -= fdy12;
-				cx2 -= fdy23;
-				cx3 -= fdy31;
-
-			}
-
-			cy1 += fdx12;
-			cy2 += fdx23;
-			cy3 += fdx31;
-
-		}
-
-	}
-
-	function drawTriangleColor3( x1, y1, x2, y2, x3, y3, color1, color2, color3 ) {
-
-		// http://devmaster.net/forums/topic/1145-advanced-rasterization/
-
-		var r1 = color1 >> 16 & 255;
-		var r2 = color2 >> 16 & 255;
-		var r3 = color3 >> 16 & 255;
-
-		var g1 = color1 >> 8 & 255;
-		var g2 = color2 >> 8 & 255;
-		var g3 = color3 >> 8 & 255;
-
-		var b1 = color1 & 255;
-		var b2 = color2 & 255;
-		var b3 = color3 & 255;
-
-		var deltasr = computeDelta( x1, y1, r1, x2, y2, r2, x3, y3, r3 );
-		var deltasg = computeDelta( x1, y1, g1, x2, y2, g2, x3, y3, g3 );
-		var deltasb = computeDelta( x1, y1, b1, x2, y2, b2, x3, y3, b3 );
-
-		// 28.4 fixed-point coordinates
-
-		var X1 = Math.round( 16 * x1 );
-		var X2 = Math.round( 16 * x2 );
-		var X3 = Math.round( 16 * x3 );
-
-		var Y1 = Math.round( 16 * y1 );
-		var Y2 = Math.round( 16 * y2 );
-		var Y3 = Math.round( 16 * y3 );
-
-		// Deltas
-
-		var dx12 = X1 - X2;
-		var dx23 = X2 - X3;
-		var dx31 = X3 - X1;
-
-		var dy12 = Y1 - Y2;
-		var dy23 = Y2 - Y3;
-		var dy31 = Y3 - Y1;
-
-		// Fixed-point deltas
-
-		var fdx = [ dx12 << 4, dx23 << 4, dx31 << 4 ];
-		var fdy = [ dy12 << 4, dy23 << 4, dy31 << 4 ];
-
-		// Bounding rectangle
-
-		var minx = Math.max( ( Math.min( X1, X2, X3 ) + 0xf ) >> 4, 0 );
-		var maxx = Math.min( ( Math.max( X1, X2, X3 ) + 0xf ) >> 4, canvasWidth );
-		var miny = Math.max( ( Math.min( Y1, Y2, Y3 ) + 0xf ) >> 4, 0 );
-		var maxy = Math.min( ( Math.max( Y1, Y2, Y3 ) + 0xf ) >> 4, canvasHeight );
-
-		// Constant part of half-edge functions
-
-		var c1 = dy12 * X1 - dx12 * Y1;
-		var c2 = dy23 * X2 - dx23 * Y2;
-		var c3 = dy31 * X3 - dx31 * Y3;
-
-		// Correct for fill convention
-
-		if ( dy12 < 0 || ( dy12 == 0 && dx12 > 0 ) ) c1 ++;
-		if ( dy23 < 0 || ( dy23 == 0 && dx23 > 0 ) ) c2 ++;
-		if ( dy31 < 0 || ( dy31 == 0 && dx31 > 0 ) ) c3 ++;
-
-		var cy1 = c1 + dx12 * ( miny << 4 ) - dy12 * ( minx << 4 );
-		var cy2 = c2 + dx23 * ( miny << 4 ) - dy23 * ( minx << 4 );
-		var cy3 = c3 + dx31 * ( miny << 4 ) - dy31 * ( minx << 4 );
-
-		// Scan through bounding rectangle
-
-		var minyx1 = ( minx - x1 );
-		var minyy1 = ( miny - y1 );
-
-		var ry = deltasr[ 1 ] * minyy1;
-		var gy = deltasg[ 1 ] * minyy1;
-		var by = deltasb[ 1 ] * minyy1;
-
-		for ( var y = miny; y < maxy; y ++ ) {
-
-			// Start value for horizontal scan
-
-			var cx1 = cy1;
-			var cx2 = cy2;
-			var cx3 = cy3;
-
-			var rx = deltasr[ 0 ] * minyx1 + ry;
-			var gx = deltasg[ 0 ] * minyx1 + gy;
-			var bx = deltasb[ 0 ] * minyx1 + by;
-
-			for ( var x = minx; x < maxx; x ++ ) {
-
-				if ( cx1 > 0 && cx2 > 0 && cx3 > 0 ) {
-
-					drawPixel( x, y, r1 + rx, g1 + gx, b1 + bx );
-
-				}
-
-				cx1 -= fdy[ 0 ];
-				cx2 -= fdy[ 1 ];
-				cx3 -= fdy[ 2 ];
-
-				rx += deltasr[ 0 ];
-				gx += deltasg[ 0 ];
-				bx += deltasb[ 0 ];
-
-			}
-
-			cy1 += fdx[ 0 ];
-			cy2 += fdx[ 1 ];
-			cy3 += fdx[ 2 ];
-
-			ry += deltasr[ 1 ];
-			gy += deltasg[ 1 ];
-			by += deltasb[ 1 ];
-
-		}
-
-	}
-
-	function normalToComponent( normal ) {
-
-		var component = ( normal + 1 ) * 127;
-		return component < 0 ? 0 : ( component > 255 ? 255 : component );
-
-	}
-
-};

+ 0 - 427
examples/js/renderers/SoftwareRenderer3.js

@@ -1,427 +0,0 @@
-/**
- * @author mrdoob / http://mrdoob.com/
- * @author mraleph / http://mrale.ph/
- */
-
-THREE.SoftwareRenderer3 = function () {
-
-	console.log( 'THREE.SoftwareRenderer', THREE.REVISION );
-
-	var canvas = document.createElement( 'canvas' );
-	var context = canvas.getContext( '2d' );
-
-	var canvasWidth = canvas.width;
-	var canvasHeight = canvas.height;
-
-	var canvasWidthHalf = canvasWidth / 2;
-	var canvasHeightHalf = canvasHeight / 2;
-
-	var imagedata = context.getImageData( 0, 0, canvas.width, canvas.height );
-	var data = imagedata.data;
-
-	var blocksize = 8;
-
-	var canvasWBlocks = Math.floor( ( canvasWidth + blocksize - 1 ) / blocksize );
-	var canvasHBlocks = Math.floor( ( canvasHeight + blocksize - 1 ) / blocksize );
-
-	var block_full = new Uint8Array( canvasWBlocks * canvasHBlocks );
-
-	var rectx1 = Infinity, recty1 = Infinity;
-	var rectx2 = 0, recty2 = 0;
-
-	var prevrectx1 = Infinity, prevrecty1 = Infinity;
-	var prevrectx2 = 0, prevrecty2 = 0;
-
-	var projector = new THREE.Projector();
-
-	this.domElement = canvas;
-
-	this.autoClear = true;
-
-	this.setSize = function ( width, height ) {
-
-		canvas.width = width;
-		canvas.height = height;
-
-		canvasWidth = canvas.width;
-		canvasHeight = canvas.height;
-
-		canvasWidthHalf = width / 2;
-		canvasHeightHalf = height / 2;
-
-		imagedata = context.getImageData( 0, 0, width, height );
-		data = imagedata.data;
-
-		canvasWBlocks = Math.floor( ( canvasWidth + blocksize - 1 ) / blocksize );
-		canvasHBlocks = Math.floor( ( canvasHeight + blocksize - 1 ) / blocksize );
-
-		console.log( canvasWBlocks, canvasHBlocks );
-
-		block_full = new Uint8Array( canvasWBlocks * canvasHBlocks )
-
-	};
-
-	this.clear = function () {
-
-		clearRectangle( prevrectx1, prevrecty1, prevrectx2, prevrecty2 );
-
-		for ( var i = 0, l = block_full.length; i < l; i ++ ) {
-
-			block_full[ i ] = 0;
-
-		}
-
-	};
-
-	this.render = function ( scene, camera ) {
-
-		rectx1 = Infinity;
-		recty1 = Infinity;
-		rectx2 = 0;
-		recty2 = 0;
-
-		if ( this.autoClear ) this.clear();
-
-		var renderData = projector.projectScene( scene, camera );
-		var elements = renderData.elements;
-
-		elements.sort( numericalSort );
-
-		for ( var e = 0, el = elements.length; e < el; e ++ ) {
-
-			var element = elements[ e ];
-
-			if ( element instanceof THREE.RenderableFace3 ) {
-
-				var v1 = element.v1.positionScreen;
-				var v2 = element.v2.positionScreen;
-				var v3 = element.v3.positionScreen;
-
-				drawTriangle(
-					v1.x * canvasWidthHalf + canvasWidthHalf,
-					- v1.y * canvasHeightHalf + canvasHeightHalf,
-					v2.x * canvasWidthHalf + canvasWidthHalf,
-					- v2.y * canvasHeightHalf + canvasHeightHalf,
-					v3.x * canvasWidthHalf + canvasWidthHalf,
-					- v3.y * canvasHeightHalf + canvasHeightHalf,
-					normalToComponent( element.normalWorld.x ),
-					normalToComponent( element.normalWorld.y ),
-					normalToComponent( element.normalWorld.z )
-				)
-
-			} else if ( element instanceof THREE.RenderableFace4 ) {
-
-				var v1 = element.v1.positionScreen;
-				var v2 = element.v2.positionScreen;
-				var v3 = element.v3.positionScreen;
-				var v4 = element.v4.positionScreen;
-
-				drawTriangle(
-					v1.x * canvasWidthHalf + canvasWidthHalf,
-					- v1.y * canvasHeightHalf + canvasHeightHalf,
-					v2.x * canvasWidthHalf + canvasWidthHalf,
-					- v2.y * canvasHeightHalf + canvasHeightHalf,
-					v3.x * canvasWidthHalf + canvasWidthHalf,
-					- v3.y * canvasHeightHalf + canvasHeightHalf,
-					normalToComponent( element.normalWorld.x ),
-					normalToComponent( element.normalWorld.y ),
-					normalToComponent( element.normalWorld.z )
-				);
-
-				drawTriangle(
-					v3.x * canvasWidthHalf + canvasWidthHalf,
-					- v3.y * canvasHeightHalf + canvasHeightHalf,
-					v4.x * canvasWidthHalf + canvasWidthHalf,
-					- v4.y * canvasHeightHalf + canvasHeightHalf,
-					v1.x * canvasWidthHalf + canvasWidthHalf,
-					- v1.y * canvasHeightHalf + canvasHeightHalf,
-					normalToComponent( element.normalWorld.x ),
-					normalToComponent( element.normalWorld.y ),
-					normalToComponent( element.normalWorld.z )
-				);
-
-			}
-
-		}
-
-		var x = Math.min( rectx1, prevrectx1 );
-		var y = Math.min( recty1, prevrecty1 );
-		var width = Math.max( rectx2, prevrectx2 ) - x;
-		var height = Math.max( recty2, prevrecty2 ) - y;
-
-		context.putImageData( imagedata, 0, 0, x, y, width, height );
-
-		prevrectx1 = rectx1; prevrecty1 = recty1;
-		prevrectx2 = rectx2; prevrecty2 = recty2;
-
-	};
-
-	function numericalSort( a, b ) {
-
-		return a.z - b.z;
-
-	}
-
-	function drawPixel( x, y, r, g, b ) {
-
-		var offset = ( x + y * canvasWidth ) * 4;
-
-		if ( data[ offset + 3 ] ) return;
-
-		data[ offset ] = r;
-		data[ offset + 1 ] = g;
-		data[ offset + 2 ] = b;
-		data[ offset + 3 ] = 255;
-
-	}
-
-	function clearRectangle( x1, y1, x2, y2 ) {
-
-		var xmin = Math.max( Math.min( x1, x2 ), 0 );
-		var xmax = Math.min( Math.max( x1, x2 ), canvasWidth );
-		var ymin = Math.max( Math.min( y1, y2 ), 0 );
-		var ymax = Math.min( Math.max( y1, y2 ), canvasHeight );
-
-		var offset = ( xmin + ymin * canvasWidth - 1 ) * 4 + 3;
-		var linestep = ( canvasWidth - ( xmax - xmin ) ) * 4;
-
-		for ( var y = ymin; y < ymax; y ++ ) {
-
-			for ( var x = xmin; x < xmax; x ++ ) {
-
-				data[ offset += 4 ] = 0;
-
-			}
-
-			offset += linestep;
-
-		}
-
-	}
-
-	function drawTriangle( x1, y1, x2, y2, x3, y3, r, g, b ) {
-
-		// https://gist.github.com/2486101
-		// explanation: ttp://pouet.net/topic.php?which=8760&page=1
-
-		// 28.4 fixed-point coordinates
-
-		var x1 = (16 * x1) | 0;
-		var x2 = (16 * x2) | 0;
-		var x3 = (16 * x3) | 0;
-
-		var y1 = (16 * y1) | 0;
-		var y2 = (16 * y2) | 0;
-		var y3 = (16 * y3) | 0;
-
-		// Deltas
-
-		var dx12 = x1 - x2, dy12 = y2 - y1;
-		var dx23 = x2 - x3, dy23 = y3 - y2;
-		var dx31 = x3 - x1, dy31 = y1 - y3;
-
-		// Bounding rectangle
-
-		var minx = Math.max( ( Math.min( x1, x2, x3 ) + 0xf ) >> 4, 0 );
-		var maxx = Math.min( ( Math.max( x1, x2, x3 ) + 0xf ) >> 4, canvasWidth );
-		var miny = Math.max( ( Math.min( y1, y2, y3 ) + 0xf ) >> 4, 0 );
-		var maxy = Math.min( ( Math.max( y1, y2, y3 ) + 0xf ) >> 4, canvasHeight );
-
-		rectx1 = Math.min( minx, rectx1 );
-		rectx2 = Math.max( maxx, rectx2 );
-		recty1 = Math.min( miny, recty1 );
-		recty2 = Math.max( maxy, recty2 );
-
-		// Block size, standard 8x8 (must be power of two)
-
-		var q = blocksize;
-
-		// Start in corner of 8x8 block
-
-		minx &= ~(q - 1);
-		miny &= ~(q - 1);
-
-		// Constant part of half-edge functions
-
-		var c1 = dy12 * ((minx << 4) - x1) + dx12 * ((miny << 4) - y1);
-		var c2 = dy23 * ((minx << 4) - x2) + dx23 * ((miny << 4) - y2);
-		var c3 = dy31 * ((minx << 4) - x3) + dx31 * ((miny << 4) - y3);
-
-		// Correct for fill convention
-
-		if ( dy12 > 0 || ( dy12 == 0 && dx12 > 0 ) ) c1 ++;
-		if ( dy23 > 0 || ( dy23 == 0 && dx23 > 0 ) ) c2 ++;
-		if ( dy31 > 0 || ( dy31 == 0 && dx31 > 0 ) ) c3 ++;
-
-		// Note this doesn't kill subpixel precision, but only because we test for >=0 (not >0).
-		// It's a bit subtle. :)
-		c1 = (c1 - 1) >> 4;
-		c2 = (c2 - 1) >> 4;
-		c3 = (c3 - 1) >> 4;
-
-		// Set up min/max corners
-		var qm1 = q - 1; // for convenience
-		var nmin1 = 0, nmax1 = 0;
-		var nmin2 = 0, nmax2 = 0;
-		var nmin3 = 0, nmax3 = 0;
-		if (dx12 >= 0) nmax1 -= qm1*dx12; else nmin1 -= qm1*dx12;
-		if (dy12 >= 0) nmax1 -= qm1*dy12; else nmin1 -= qm1*dy12;
-		if (dx23 >= 0) nmax2 -= qm1*dx23; else nmin2 -= qm1*dx23;
-		if (dy23 >= 0) nmax2 -= qm1*dy23; else nmin2 -= qm1*dy23;
-		if (dx31 >= 0) nmax3 -= qm1*dx31; else nmin3 -= qm1*dx31;
-		if (dy31 >= 0) nmax3 -= qm1*dy31; else nmin3 -= qm1*dy31;
-
-		// Loop through blocks
-		var linestep = (canvasWidth - q) * 4;
-		var scale = 255.0 / (c1 + c2 + c3);
-
-		var cb1 = c1;
-		var cb2 = c2;
-		var cb3 = c3;
-		var qstep = -q;
-		var e1x = qstep * dy12;
-		var e2x = qstep * dy23;
-		var e3x = qstep * dy31;
-		var x0 = minx;
-
-		for (var y0 = miny; y0 < maxy; y0 += q) {
-
-			// New block line - keep hunting for tri outer edge in old block line dir
-			while (x0 >= minx && x0 < maxx && cb1 >= nmax1 && cb2 >= nmax2 && cb3 >= nmax3) {
-
-				x0 += qstep;
-				cb1 += e1x;
-				cb2 += e2x;
-				cb3 += e3x;
-
-			}
-
-			// Okay, we're now in a block we know is outside. Reverse direction and go into main loop.
-			qstep = -qstep;
-			e1x = -e1x;
-			e2x = -e2x;
-			e3x = -e3x;
-
-			while (1) {
-
-				// Step everything
-				x0 += qstep;
-				cb1 += e1x;
-				cb2 += e2x;
-				cb3 += e3x;
-
-				// We're done with this block line when at least one edge completely out
-				// If an edge function is too small and decreasing in the current traversal
-				// dir, we're done with this line.
-				if (x0 < minx || x0 >= maxx) break;
-				if (cb1 < nmax1) if (e1x < 0) break; else continue;
-				if (cb2 < nmax2) if (e2x < 0) break; else continue;
-				if (cb3 < nmax3) if (e3x < 0) break; else continue;
-
-				// We can skip this block if it's already fully covered
-				var blockX = (x0 / q) | 0;
-				var blockY = (y0 / q) | 0;
-				var blockInd = blockX + blockY * canvasWBlocks;
-				if (block_full[blockInd]) continue;
-
-				// Offset at top-left corner
-				var offset = (x0 + y0 * canvasWidth) * 4;
-
-				// Accept whole block when fully covered
-				if (cb1 >= nmin1 && cb2 >= nmin2 && cb3 >= nmin3) {
-
-					var cy1 = cb1;
-					var cy2 = cb2;
-
-					for ( var iy = 0; iy < q; iy ++ ) {
-
-						var cx1 = cy1;
-						var cx2 = cy2;
-
-						for ( var ix = 0; ix < q; ix ++ ) {
-
-							if (!data[offset + 3]) {
-
-								var u = cx1 * scale; // 0-255!
-								var v = cx2 * scale; // 0-255!
-								data[offset] = u;
-								data[offset + 1] = v;
-								data[offset + 2] = 0;
-								data[offset + 3] = 255;
-
-							}
-
-							cx1 += dy12;
-							cx2 += dy23;
-							offset += 4;
-
-						}
-
-						cy1 += dx12;
-						cy2 += dx23;
-						offset += linestep;
-
-					}
-
-					block_full[blockInd] = 1;
-
-				} else { // Partially covered block
-
-					var cy1 = cb1;
-					var cy2 = cb2;
-					var cy3 = cb3;
-
-					for ( var iy = 0; iy < q; iy ++ ) {
-
-						var cx1 = cy1;
-						var cx2 = cy2;
-						var cx3 = cy3;
-
-						for ( var ix = 0; ix < q; ix ++ ) {
-
-							if ( (cx1 | cx2 | cx3) >= 0 && !data[offset+3]) {
-
-								var u = cx1 * scale; // 0-255!
-								var v = cx2 * scale; // 0-255!
-								data[offset] = u;
-								data[offset + 1] = v;
-								data[offset + 2] = 0;
-								data[offset + 3] = 255;
-
-							}
-
-							cx1 += dy12;
-							cx2 += dy23;
-							cx3 += dy31;
-							offset += 4;
-
-						}
-
-						cy1 += dx12;
-						cy2 += dx23;
-						cy3 += dx31;
-						offset += linestep;
-
-					}
-
-				}
-
-			}
-
-			// Advance to next row of blocks
-			cb1 += q*dx12;
-			cb2 += q*dx23;
-			cb3 += q*dx31;
-
-		}
-
-	}
-
-	function normalToComponent( normal ) {
-
-		var component = ( normal + 1 ) * 127;
-		return component < 0 ? 0 : ( component > 255 ? 255 : component );
-
-	}
-
-};

+ 1 - 3
examples/misc_software.html

@@ -20,8 +20,6 @@
 		<script src="js/controls/TrackballControls.js"></script>
 
 		<script src="js/renderers/SoftwareRenderer.js"></script>
-		<script src="js/renderers/SoftwareRenderer2.js"></script>
-		<script src="js/renderers/SoftwareRenderer3.js"></script>
 
 		<script src="js/libs/stats.min.js"></script>
 
@@ -70,7 +68,7 @@
 				plane.rotation.x = - Math.PI / 2;
 				scene.add( plane );
 
-				renderer = new THREE.SoftwareRenderer3();
+				renderer = new THREE.SoftwareRenderer();
 				renderer.setSize( window.innerWidth || 2, window.innerHeight || 2 );
 
 				container.appendChild( renderer.domElement );

+ 4 - 9
examples/misc_ubiquity_test.html

@@ -17,7 +17,7 @@
 		<script src="../build/three.min.js"></script>
 
 		<script src="js/renderers/SVGRenderer.js"></script>
-		<script src="js/renderers/SoftwareRenderer3.js"></script>
+		<script src="js/renderers/SoftwareRenderer.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 		<script src="obj/Qrcode.js"></script>
@@ -33,7 +33,7 @@
 			var camera, scene;
 			var canvasRenderer, svgRenderer, softwareRenderer, webglRenderer;
 
-			var mesh, group, qrcode;
+			var mesh, group;
 
 			var mouseX = 0, mouseY = 0;
 
@@ -55,7 +55,7 @@
 
 				// QRCODE
 
-				qrcode = mesh = new THREE.Mesh( new Qrcode(), new THREE.MeshLambertMaterial( { /*emissive: 0xff0000,*/ vertexColors: THREE.FaceColors } ) );
+				mesh = new THREE.Mesh( new Qrcode(), new THREE.MeshLambertMaterial( { /*emissive: 0xff0000,*/ vertexColors: THREE.FaceColors } ) );
 				mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
 				scene.add( mesh );
 
@@ -146,7 +146,7 @@
 				svgRenderer.setQuality( 'low' );
 				container.appendChild( svgRenderer.domElement );
 
-				softwareRenderer = new THREE.SoftwareRenderer3();
+				softwareRenderer = new THREE.SoftwareRenderer();
 				softwareRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				container.appendChild( softwareRenderer.domElement );
 
@@ -211,11 +211,6 @@
 
 				group.rotation.y += 0.01;
 
-				/*
-				qrcode.rotation.x += 0.01;
-				qrcode.rotation.z += 0.02;
-				*/
-
 				canvasRenderer.render( scene, camera );
 				svgRenderer.render( scene, camera );
 				softwareRenderer.render( scene, camera );

+ 56 - 27
src/core/Projector.js

@@ -18,9 +18,16 @@ THREE.Projector = function() {
 	_vector3 = new THREE.Vector3(),
 	_vector4 = new THREE.Vector4(),
 
+	_viewMatrix = new THREE.Matrix4(),
 	_viewProjectionMatrix = new THREE.Matrix4(),
+
+	_modelMatrix,
 	_modelViewProjectionMatrix = new THREE.Matrix4(),
+
 	_normalMatrix = new THREE.Matrix3(),
+	_normalViewMatrix = new THREE.Matrix3(),
+
+	_centroid = new THREE.Vector3(),
 
 	_frustum = new THREE.Frustum(),
 
@@ -169,10 +176,10 @@ THREE.Projector = function() {
 	this.projectScene = function ( scene, camera, sortObjects, sortElements ) {
 
 		var near = camera.near, far = camera.far, visible = false,
-		o, ol, v, vl, f, fl, n, nl, c, cl, u, ul, object, modelMatrix,
+		o, ol, v, vl, f, fl, n, nl, c, cl, u, ul, object,
 		geometry, vertices, vertex, vertexPositionScreen,
-		faces, face, faceVertexNormals, normal, faceVertexUvs, uvs,
-		v1, v2, v3, v4, isFaceMaterial, objectMaterials, material, side;
+		faces, face, faceVertexNormals, faceVertexUvs, uvs,
+		v1, v2, v3, v4, isFaceMaterial, objectMaterials;
 
 		_face3Count = 0;
 		_face4Count = 0;
@@ -185,9 +192,11 @@ THREE.Projector = function() {
 
 		if ( camera.parent === undefined ) camera.updateMatrixWorld();
 
-		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
+		_viewMatrix.getInverse( camera.matrixWorld );
+		_viewProjectionMatrix.multiply( camera.projectionMatrix, _viewMatrix );
 
-		_viewProjectionMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
+		_normalViewMatrix.getInverse( _viewMatrix );
+		_normalViewMatrix.transpose();
 
 		_frustum.setFromMatrix( _viewProjectionMatrix );
 
@@ -197,7 +206,7 @@ THREE.Projector = function() {
 
 			object = _renderData.objects[ o ].object;
 
-			modelMatrix = object.matrixWorld;
+			_modelMatrix = object.matrixWorld;
 
 			_vertexCount = 0;
 
@@ -209,20 +218,18 @@ THREE.Projector = function() {
 				faces = geometry.faces;
 				faceVertexUvs = geometry.faceVertexUvs;
 
-				_normalMatrix.getInverse( modelMatrix );
+				_normalMatrix.getInverse( _modelMatrix );
 				_normalMatrix.transpose();
 
 				isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
 				objectMaterials = isFaceMaterial === true ? object.material : null;
 
-				side = object.material.side;
-
 				for ( v = 0, vl = vertices.length; v < vl; v ++ ) {
 
 					_vertex = getNextVertexInPool();
 					_vertex.positionWorld.copy( vertices[ v ] );
 
-					modelMatrix.multiplyVector3( _vertex.positionWorld );
+					_modelMatrix.multiplyVector3( _vertex.positionWorld );
 
 					_vertex.positionScreen.copy( _vertex.positionWorld );
 					_viewProjectionMatrix.multiplyVector4( _vertex.positionScreen );
@@ -238,11 +245,13 @@ THREE.Projector = function() {
 
 					face = faces[ f ];
 
-					material = isFaceMaterial === true ? objectMaterials.materials[ face.materialIndex ] : object.material;
+					var material = isFaceMaterial === true
+						? objectMaterials.materials[ face.materialIndex ]
+						: object.material;
 
 					if ( material === undefined ) continue;
 
-					side = material.side;
+					var side = material.side;
 
 					if ( face instanceof THREE.Face3 ) {
 
@@ -313,27 +322,42 @@ THREE.Projector = function() {
 
 					}
 
-					_face.normalWorld.copy( face.normal );
+					_face.normalModel.copy( face.normal );
+
+					if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
 
-					if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) _face.normalWorld.negate();
-					_normalMatrix.multiplyVector3( _face.normalWorld ).normalize();
+						_face.normalModel.negate();
+
+					}
 
-					_face.centroidWorld.copy( face.centroid );
-					modelMatrix.multiplyVector3( _face.centroidWorld );
+					_normalMatrix.multiplyVector3( _face.normalModel );
+					_face.normalModel.normalize();
 
-					_face.centroidScreen.copy( _face.centroidWorld );
-					_viewProjectionMatrix.multiplyVector3( _face.centroidScreen );
+					_face.normalModelView.copy( _face.normalModel );
+					_normalViewMatrix.multiplyVector3( _face.normalModelView );
+
+					_face.centroidModel.copy( face.centroid );
+					_modelMatrix.multiplyVector3( _face.centroidModel );
 
 					faceVertexNormals = face.vertexNormals;
 
 					for ( n = 0, nl = faceVertexNormals.length; n < nl; n ++ ) {
 
-						normal = _face.vertexNormalsWorld[ n ];
-						normal.copy( faceVertexNormals[ n ] );
+						var normalModel = _face.vertexNormalsModel[ n ];
+						normalModel.copy( faceVertexNormals[ n ] );
+
+						if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
+
+							normalModel.negate();
+
+						}
 
-						if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) normal.negate();
+						_normalMatrix.multiplyVector3( normalModel )
+						normalModel.normalize();
 
-						_normalMatrix.multiplyVector3( normal ).normalize();
+						var normalModelView = _face.vertexNormalsModelView[ n ];
+						normalModelView.copy( normalModel );
+						_normalViewMatrix.multiplyVector3( normalModelView )
 
 					}
 
@@ -356,7 +380,10 @@ THREE.Projector = function() {
 					_face.color = face.color;
 					_face.material = material;
 
-					_face.z = _face.centroidScreen.z;
+					_centroid.copy( _face.centroidModel )
+					_viewProjectionMatrix.multiplyVector3( _centroid );
+
+					_face.z = _centroid.z;
 
 					_renderData.elements.push( _face );
 
@@ -364,12 +391,13 @@ THREE.Projector = function() {
 
 			} else if ( object instanceof THREE.Line ) {
 
-				_modelViewProjectionMatrix.multiply( _viewProjectionMatrix, modelMatrix );
+				_modelViewProjectionMatrix.multiply( _viewProjectionMatrix, _modelMatrix );
 
 				vertices = object.geometry.vertices;
 
 				v1 = getNextVertexInPool();
 				v1.positionScreen.copy( vertices[ 0 ] );
+
 				_modelViewProjectionMatrix.multiplyVector4( v1.positionScreen );
 
 				// Handle LineStrip and LinePieces
@@ -379,6 +407,7 @@ THREE.Projector = function() {
 
 					v1 = getNextVertexInPool();
 					v1.positionScreen.copy( vertices[ v ] );
+
 					_modelViewProjectionMatrix.multiplyVector4( v1.positionScreen );
 
 					if ( ( v + 1 ) % step > 0 ) continue;
@@ -416,11 +445,11 @@ THREE.Projector = function() {
 
 			object = _renderData.sprites[ o ].object;
 
-			modelMatrix = object.matrixWorld;
+			_modelMatrix = object.matrixWorld;
 
 			if ( object instanceof THREE.Particle ) {
 
-				_vector4.set( modelMatrix.elements[12], modelMatrix.elements[13], modelMatrix.elements[14], 1 );
+				_vector4.set( _modelMatrix.elements[12], _modelMatrix.elements[13], _modelMatrix.elements[14], 1 );
 				_viewProjectionMatrix.multiplyVector4( _vector4 );
 
 				_vector4.z /= _vector4.w;

+ 24 - 33
src/renderers/CanvasRenderer.js

@@ -600,9 +600,9 @@ THREE.CanvasRenderer = function ( parameters ) {
 						_color1.g = _color2.g = _color3.g = _ambientLight.g;
 						_color1.b = _color2.b = _color3.b = _ambientLight.b;
 
-						calculateLight( element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 );
-						calculateLight( element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 );
-						calculateLight( element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color3 );
+						calculateLight( element.v1.positionWorld, element.vertexNormalsModel[ 0 ], _color1 );
+						calculateLight( element.v2.positionWorld, element.vertexNormalsModel[ 1 ], _color2 );
+						calculateLight( element.v3.positionWorld, element.vertexNormalsModel[ 2 ], _color3 );
 
 						_color1.r = _color1.r * _diffuseColor.r + _emissiveColor.r;
 						_color1.g = _color1.g * _diffuseColor.g + _emissiveColor.g;
@@ -630,7 +630,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 						_color.g = _ambientLight.g;
 						_color.b = _ambientLight.b;
 
-						calculateLight( element.centroidWorld, element.normalWorld, _color );
+						calculateLight( element.centroidModel, element.normalModel, _color );
 
 						_color.r = _color.r * _diffuseColor.r + _emissiveColor.r;
 						_color.g = _color.g * _diffuseColor.g + _emissiveColor.g;
@@ -666,19 +666,17 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 					if ( material.envMap.mapping instanceof THREE.SphericalReflectionMapping ) {
 
-						var cameraMatrix = camera.matrixWorldInverse;
+						_vector3.copy( element.vertexNormalsModelView[ uv1 ] );
+						_uv1x = 0.5 * _vector3.x + 0.5;
+						_uv1y = 0.5 * _vector3.y + 0.5;
 
-						_vector3.copy( element.vertexNormalsWorld[ uv1 ] );
-						_uv1x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
-						_uv1y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
+						_vector3.copy( element.vertexNormalsModelView[ uv2 ] );
+						_uv2x = 0.5 * _vector3.x + 0.5;
+						_uv2y = 0.5 * _vector3.y + 0.5;
 
-						_vector3.copy( element.vertexNormalsWorld[ uv2 ] );
-						_uv2x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
-						_uv2y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
-
-						_vector3.copy( element.vertexNormalsWorld[ uv3 ] );
-						_uv3x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
-						_uv3y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
+						_vector3.copy( element.vertexNormalsModelView[ uv3 ] );
+						_uv3x = 0.5 * _vector3.x + 0.5;
+						_uv3y = 0.5 * _vector3.y + 0.5;
 
 						patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
 
@@ -726,9 +724,9 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 			} else if ( material instanceof THREE.MeshNormalMaterial ) {
 
-				_color.r = normalToComponent( element.normalWorld.x );
-				_color.g = normalToComponent( element.normalWorld.y );
-				_color.b = normalToComponent( element.normalWorld.z );
+				_color.r = 0.5 * element.normalModelView.x + 0.5;
+				_color.g = 0.5 * element.normalModelView.y + 0.5;
+				_color.b = 0.5 * element.normalModelView.z + 0.5;
 
 				material.wireframe === true
 					? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
@@ -785,10 +783,10 @@ THREE.CanvasRenderer = function ( parameters ) {
 						_color1.g = _color2.g = _color3.g = _color4.g = _ambientLight.g;
 						_color1.b = _color2.b = _color3.b = _color4.b = _ambientLight.b;
 
-						calculateLight( element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 );
-						calculateLight( element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 );
-						calculateLight( element.v4.positionWorld, element.vertexNormalsWorld[ 3 ], _color3 );
-						calculateLight( element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color4 );
+						calculateLight( element.v1.positionWorld, element.vertexNormalsModel[ 0 ], _color1 );
+						calculateLight( element.v2.positionWorld, element.vertexNormalsModel[ 1 ], _color2 );
+						calculateLight( element.v4.positionWorld, element.vertexNormalsModel[ 3 ], _color3 );
+						calculateLight( element.v3.positionWorld, element.vertexNormalsModel[ 2 ], _color4 );
 
 						_color1.r = _color1.r * _diffuseColor.r + _emissiveColor.r;
 						_color1.g = _color1.g * _diffuseColor.g + _emissiveColor.g;
@@ -822,7 +820,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 						_color.g = _ambientLight.g;
 						_color.b = _ambientLight.b;
 
-						calculateLight( element.centroidWorld, element.normalWorld, _color );
+						calculateLight( element.centroidModel, element.normalModel, _color );
 
 						_color.r = _color.r * _diffuseColor.r + _emissiveColor.r;
 						_color.g = _color.g * _diffuseColor.g + _emissiveColor.g;
@@ -870,9 +868,9 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 			} else if ( material instanceof THREE.MeshNormalMaterial ) {
 
-				_color.r = normalToComponent( element.normalWorld.x );
-				_color.g = normalToComponent( element.normalWorld.y );
-				_color.b = normalToComponent( element.normalWorld.z );
+				_color.r = 0.5 * element.normalModelView.x + 0.5;
+				_color.g = 0.5 * element.normalModelView.y + 0.5;
+				_color.b = 0.5 * element.normalModelView.z + 0.5;
 
 				drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
 
@@ -1113,13 +1111,6 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 		}
 
-		function normalToComponent( normal ) {
-
-			var component = ( normal + 1 ) * 0.5;
-			return component < 0 ? 0 : ( component > 1 ? 1 : component );
-
-		}
-
 		// Hide anti-alias gaps
 
 		function expand( v1, v2 ) {

+ 6 - 4
src/renderers/renderables/RenderableFace3.js

@@ -8,12 +8,14 @@ THREE.RenderableFace3 = function () {
 	this.v2 = new THREE.RenderableVertex();
 	this.v3 = new THREE.RenderableVertex();
 
-	this.centroidWorld = new THREE.Vector3();
-	this.centroidScreen = new THREE.Vector3();
+	this.centroidModel = new THREE.Vector3();
+
+	this.normalModel = new THREE.Vector3();
+	this.normalModelView = new THREE.Vector3();
 
-	this.normalWorld = new THREE.Vector3();
-	this.vertexNormalsWorld = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 	this.vertexNormalsLength = 0;
+	this.vertexNormalsModel = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
+	this.vertexNormalsModelView = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 
 	this.color = null;
 	this.material = null;

+ 6 - 4
src/renderers/renderables/RenderableFace4.js

@@ -9,12 +9,14 @@ THREE.RenderableFace4 = function () {
 	this.v3 = new THREE.RenderableVertex();
 	this.v4 = new THREE.RenderableVertex();
 
-	this.centroidWorld = new THREE.Vector3();
-	this.centroidScreen = new THREE.Vector3();
+	this.centroidModel = new THREE.Vector3();
+
+	this.normalModel = new THREE.Vector3();
+	this.normalModelView = new THREE.Vector3();
 
-	this.normalWorld = new THREE.Vector3();
-	this.vertexNormalsWorld = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 	this.vertexNormalsLength = 0;
+	this.vertexNormalsModel = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
+	this.vertexNormalsModelView = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 
 	this.color = null;
 	this.material = null;

+ 1 - 1
src/renderers/renderables/RenderableVertex.js

@@ -16,4 +16,4 @@ THREE.RenderableVertex.prototype.copy = function ( vertex ) {
 	this.positionWorld.copy( vertex.positionWorld );
 	this.positionScreen.copy( vertex.positionScreen );
 
-}
+};

部分文件因文件數量過多而無法顯示