Browse Source

Implemented material blendings (THREE.NormalBlending, THREE.AdditiveBlending, THREE.SubtractiveBlending) in CanvasRenderer
Added MeshNormalMaterial (per face)

Mr.doob 14 years ago
parent
commit
4d209ac433

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


File diff suppressed because it is too large
+ 0 - 0
build/ThreeDebug.js


+ 85 - 0
examples/materials_normal.html

@@ -0,0 +1,85 @@
+<!DOCTYPE HTML>
+<html lang="en">
+	<head>
+		<title>three.js - normal material</title>
+		<meta charset="utf-8">
+		<style type="text/css">
+			body {
+				background-color: #000000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px; width: 100%;
+				color: #808080;
+				padding: 5px;
+				font-family: Monospace;
+				font-size: 13px;
+				text-align: center;
+			}
+
+			a {
+				color: #ffffff;
+				text-decoration: none;
+			}
+
+			a:hover {
+				color: #0080ff;
+			}
+		</style>
+	</head>
+	<body>
+
+		<div id="container"></div>
+		<div id="info">
+			<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - normal material.<br />
+			Walt Disney head by <a href="http://www.davidoreilly.com/2009/01/walt-disneys-head-on-a-plate" target="_blank">David OReilly</a>
+		</div>
+
+		<script type="text/javascript" src="../build/Three.js"></script> 
+		<script type="text/javascript" src="geometry/WaltHead.js"></script>
+
+		<script type="text/javascript">
+
+			var camera, scene, renderer,
+			object;
+
+			init();
+			setInterval( loop, 1000 / 60 );
+
+			function init() {
+
+				var container = document.getElementById( 'container' );
+
+				camera = new THREE.Camera( 50, window.innerWidth / window.innerHeight, 1, 2000 );
+				camera.position.z = 1000;
+
+				scene = new THREE.Scene();
+
+				object = new THREE.Mesh( new WaltHead(), new THREE.MeshNormalMaterial() );
+				object.overdraw = true;
+				object.scale.x = object.scale.y = object.scale.z = 10;
+				scene.addObject( object );
+
+				renderer = new THREE.CanvasRenderer();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				container.appendChild( renderer.domElement );
+
+			}
+
+			function loop() {
+
+				var time = new Date().getTime() * 0.0005;
+
+				object.rotation.x -= 0.005;
+				object.rotation.y -= 0.01;
+
+				renderer.render(scene, camera);
+
+			}
+
+		</script>
+	</body>
+</html>

+ 1 - 1
examples/particles_random.html

@@ -59,7 +59,7 @@
 				renderer = new THREE.CanvasRenderer();
 				renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
 
-				for (var i = 0; i < 1000; i++) {
+				for ( var i = 0; i < 1000; i++ ) {
 
 					particle = new THREE.Particle( new THREE.ParticleCircleMaterial( { color: Math.random() * 0x808008 + 0x808080, opacity: 1 } ) );
 					particle.position.x = Math.random() * 2000 - 1000;

+ 4 - 1
src/materials/MeshDepthMaterial.js

@@ -4,7 +4,8 @@
  * parameters = {
  *  near: <float>,
  *  far: <float>,
- *  opacity: <float>
+ *  opacity: <float>,
+ *  blending: THREE.NormalBlending
  * } 
  */
 
@@ -13,12 +14,14 @@ THREE.MeshDepthMaterial = function ( parameters ) {
 	this.near = 1;
 	this.far = 1000;
 	this.opacity = 1;
+	this.blending = THREE.NormalBlending;
 
 	if ( parameters ) {
 
 		if ( parameters.near !== undefined ) this.near = parameters.near;
 		if ( parameters.far !== undefined ) this.far = parameters.far;
 		if ( parameters.opacity !== undefined ) this.opacity  = parameters.opacity;
+		if ( parameters.blending !== undefined ) this.blending = parameters.blending;
 
 	}
 

+ 29 - 0
src/materials/MeshNormalMaterial.js

@@ -0,0 +1,29 @@
+/**
+ * @author mr.doob / http://mrdoob.com/
+ *
+ * parameters = {
+ *  opacity: <float>,
+ *  blending: THREE.NormalBlending
+ * } 
+ */
+
+THREE.MeshNormalMaterial = function ( parameters ) {
+
+	this.opacity = 1;
+	this.blending = THREE.NormalBlending;
+
+
+	if ( parameters ) {
+
+		if ( parameters.opacity !== undefined ) this.opacity  = parameters.opacity;
+		if ( parameters.blending !== undefined ) this.blending = parameters.blending;
+
+	}
+
+	this.toString = function () {
+
+		return 'THREE.MeshNormalMaterial';
+
+	};
+
+}

+ 91 - 42
src/renderers/CanvasRenderer.js

@@ -12,6 +12,7 @@ THREE.CanvasRenderer = function () {
 	_context = _canvas.getContext( '2d' ),
 
 	_contextGlobalAlpha = 1,
+	_contextGlobalCompositeOperation = 0,
 	_contextStrokeStyle = '#000000',
 	_contextFillStyle = '#000000',
 	_contextLineWidth = 1,
@@ -28,7 +29,7 @@ THREE.CanvasRenderer = function () {
 	_light = new THREE.Color( 0xffffffff ),
 	_ambientLight = new THREE.Color( 0xff000000 ),
 
-	_pi2 = Math.PI * 2, _w, // z-buffer to w-buffer
+	_pi2 = Math.PI * 2,
 	_vector3 = new THREE.Vector3(), // Needed for PointLight
 	_uv1 = new THREE.UV(), _uv2 = new THREE.UV(), _uv3 = new THREE.UV(), _uv4 = new THREE.UV(),
 
@@ -287,6 +288,26 @@ THREE.CanvasRenderer = function () {
 
 	};
 
+	function setBlending( blending ) {
+
+		switch( blending ) {
+
+			case 0: // THREE.NormalBlending
+				_context.globalCompositeOperation = "source-over";
+				break;
+			case 1: // THREE.AdditiveBlending
+				_context.globalCompositeOperation = "lighter";
+				break;
+			case 2: // THREE.SubtractiveBlending
+				_context.globalCompositeOperation = "darker";
+				break;
+
+		}
+
+		_contextGlobalCompositeOperation = blending;
+
+	}
+
 	function calculateAmbientLight( scene, color ) {
 
 		var l, ll, light, lightColor,
@@ -389,12 +410,18 @@ THREE.CanvasRenderer = function () {
 		var width, height, scaleX, scaleY, offsetX, offsetY,
 		bitmap, bitmapWidth, bitmapHeight;
 
-		if ( _contextGlobalAlpha != material.opacity ) {
+		if ( material.opacity != _contextGlobalAlpha ) {
 
 			_context.globalAlpha = _contextGlobalAlpha = material.opacity;
 
 		}
 
+		if ( material.blending != _contextGlobalCompositeOperation ) {
+
+			setBlending( material.blending );
+
+		}
+
 		if ( material instanceof THREE.ParticleBasicMaterial ) {
 
 			bitmap = material.bitmap;
@@ -432,10 +459,10 @@ THREE.CanvasRenderer = function () {
 
 			/* DEBUG
 			_context.beginPath();
-			_context.moveTo( v1x - 10, v1y );
-			_context.lineTo( v1x + 10, v1y );
-			_context.moveTo( v1x, v1y - 10 );
-			_context.lineTo( v1x, v1y + 10 );
+			_context.moveTo( v1.x - 10, v1.y );
+			_context.lineTo( v1.x + 10, v1.y );
+			_context.moveTo( v1.x, v1.y - 10 );
+			_context.lineTo( v1.x, v1.y + 10 );
 			_context.closePath();
 			_context.strokeStyle = 'rgb(255,255,0)';
 			_context.stroke();
@@ -489,12 +516,18 @@ THREE.CanvasRenderer = function () {
 
 	function renderLine( v1, v2, element, material, scene ) {
 
-		if ( _contextGlobalAlpha != material.opacity ) {
+		if ( material.opacity != _contextGlobalAlpha ) {
 
 			_context.globalAlpha = _contextGlobalAlpha = material.opacity;
 
 		}
 
+		if ( material.blending != _contextGlobalCompositeOperation ) {
+
+			setBlending( material.blending );
+
+		}
+
 		if ( material instanceof THREE.LineBasicMaterial ) {
 
 			_context.beginPath();
@@ -528,12 +561,18 @@ THREE.CanvasRenderer = function () {
 
 		var bitmap, bitmapWidth, bitmapHeight;
 
-		if ( _contextGlobalAlpha != material.opacity ) {
+		if ( material.opacity != _contextGlobalAlpha ) {
 
 			_context.globalAlpha = _contextGlobalAlpha = material.opacity;
 
 		}
 
+		if ( material.blending != _contextGlobalCompositeOperation ) {
+
+			setBlending( material.blending );
+
+		}
+
 		if ( material.map ) {
 
 			bitmap = material.map.image;
@@ -553,17 +592,12 @@ THREE.CanvasRenderer = function () {
 		if ( material instanceof THREE.MeshDepthMaterial ) {
 
 			bitmap = _depthMap;
-			bitmapWidth = bitmap.width - 1;
-			bitmapHeight = bitmap.height - 1;
-
-			_w = material.__2near / (material.__farPlusNear - v1.positionScreen.z * material.__farMinusNear );
-			_uv1.u = _w * bitmapWidth; _uv1.v = 0;
 
-			_w = material.__2near / (material.__farPlusNear - v2.positionScreen.z * material.__farMinusNear );
-			_uv2.u = _w * bitmapWidth; _uv2.v = 1;
+			_uv1.u = ( material.__2near / (material.__farPlusNear - v1.positionScreen.z * material.__farMinusNear ) ) * 255;
+			_uv2.u = ( material.__2near / (material.__farPlusNear - v2.positionScreen.z * material.__farMinusNear ) ) * 255;
+			_uv3.u = ( material.__2near / (material.__farPlusNear - v3.positionScreen.z * material.__farMinusNear ) ) * 255;
 
-			_w = material.__2near / (material.__farPlusNear - v3.positionScreen.z * material.__farMinusNear );
-			_uv3.u = _w * bitmapWidth; _uv3.v = 2;
+			_uv1.v = 0; _uv2.v = 1; _uv3.v = 2;
 
 			drawTexturedTriangle( bitmap, v1.positionScreen.x, v1.positionScreen.y, v2.positionScreen.x, v2.positionScreen.y, v3.positionScreen.x, v3.positionScreen.y, _uv1.u, _uv1.v, _uv2.u, _uv2.v, _uv3.u, _uv3.v );
 
@@ -582,13 +616,6 @@ THREE.CanvasRenderer = function () {
 
 			_color.__styleString = material.color.__styleString;
 
-		} else if ( material instanceof THREE.MeshDepthMaterial ) {
-
-			/*
-			_w = 1 - ( material.__2near / (material.__farPlusNear - element.z * material.__farMinusNear ) );
-			_color.setRGBA( _w, _w, _w, 1 );
-			*/
-
 		} else if ( material instanceof THREE.MeshLambertMaterial ) {
 
 			if ( _enableLighting ) {
@@ -606,6 +633,16 @@ THREE.CanvasRenderer = function () {
 
 			}
 
+		}/* else if ( material instanceof THREE.MeshDepthMaterial ) {
+
+			_w = 1 - ( material.__2near / (material.__farPlusNear - element.z * material.__farMinusNear ) );
+			_color.setRGBA( _w, _w, _w, 1 );
+
+
+		}*/ else if ( material instanceof THREE.MeshNormalMaterial ) {
+
+			_color.setRGBA( normalToComponent( element.normalWorld.x ), normalToComponent( element.normalWorld.y ), normalToComponent( element.normalWorld.z ), 1 );
+
 		}
 
 		if ( material.wireframe ) {
@@ -644,12 +681,18 @@ THREE.CanvasRenderer = function () {
 
 		var bitmap, bitmapWidth, bitmapHeight;
 
-		if ( _contextGlobalAlpha != material.opacity ) {
+		if ( material.opacity != _contextGlobalAlpha ) {
 
 			_context.globalAlpha = _contextGlobalAlpha = material.opacity;
 
 		}
 
+		if ( material.blending != _contextGlobalCompositeOperation ) {
+
+			setBlending( material.blending );
+
+		}
+
 		if ( material.map ) {
 
 			bitmap = material.map.image;
@@ -676,20 +719,13 @@ THREE.CanvasRenderer = function () {
 		if ( material instanceof THREE.MeshDepthMaterial ) {
 
 			bitmap = _depthMap;
-			bitmapWidth = bitmap.width - 1;
-			bitmapHeight = bitmap.height - 1;
 
-			_w = material.__2near / (material.__farPlusNear - v1.positionScreen.z * material.__farMinusNear );
-			_uv1.u = _w * bitmapWidth; _uv1.v = 0;
+			_uv1.u = ( material.__2near / (material.__farPlusNear - v1.positionScreen.z * material.__farMinusNear ) ) * 255;
+			_uv2.u = ( material.__2near / (material.__farPlusNear - v2.positionScreen.z * material.__farMinusNear ) ) * 255;
+			_uv3.u = ( material.__2near / (material.__farPlusNear - v3.positionScreen.z * material.__farMinusNear ) ) * 255;
+			_uv4.u = ( material.__2near / (material.__farPlusNear - v4.positionScreen.z * material.__farMinusNear ) ) * 255;
 
-			_w = material.__2near / (material.__farPlusNear - v2.positionScreen.z * material.__farMinusNear );
-			_uv2.u = _w * bitmapWidth; _uv2.v = 1;
-
-			_w = material.__2near / (material.__farPlusNear - v3.positionScreen.z * material.__farMinusNear );
-			_uv3.u = _w * bitmapWidth; _uv3.v = 2;
-
-			_w = material.__2near / (material.__farPlusNear - v4.positionScreen.z * material.__farMinusNear );
-			_uv4.u = _w * bitmapWidth; _uv4.v = 3;
+			_uv1.v = 0; _uv2.v = 1; _uv3.v = 2; _uv4.v = 3;
 
 			drawTexturedTriangle( bitmap, v1.positionScreen.x, v1.positionScreen.y, v2.positionScreen.x, v2.positionScreen.y, v4.positionScreen.x, v4.positionScreen.y, _uv1.u, _uv1.v, _uv2.u, _uv2.v, _uv4.u, _uv4.v );
 			drawTexturedTriangle( bitmap, v5.positionScreen.x, v5.positionScreen.y, v3.positionScreen.x, v3.positionScreen.y, v6.positionScreen.x, v6.positionScreen.y, _uv2.u, _uv2.v, _uv3.u, _uv3.v, _uv4.u, _uv4.v );
@@ -710,11 +746,6 @@ THREE.CanvasRenderer = function () {
 
 			_color.__styleString = material.color.__styleString;
 
-		} else if ( material instanceof THREE.MeshDepthMaterial ) {
-
-			_w = 1 - ( material.__2near / (material.__farPlusNear - element.z * material.__farMinusNear ) );
-			_color.setRGBA( _w, _w, _w, 1 );
-
 		} else if ( material instanceof THREE.MeshLambertMaterial ) {
 
 			if ( _enableLighting ) {
@@ -732,6 +763,16 @@ THREE.CanvasRenderer = function () {
 
 			}
 
+		}/* else if ( material instanceof THREE.MeshDepthMaterial ) {
+
+			_w = 1 - ( material.__2near / (material.__farPlusNear - element.z * material.__farMinusNear ) );
+			_color.setRGBA( _w, _w, _w, 1 );
+
+
+		}*/ else if ( material instanceof THREE.MeshNormalMaterial ) {
+
+			_color.setRGBA( normalToComponent( element.normalWorld.x ), normalToComponent( element.normalWorld.y ), normalToComponent( element.normalWorld.z ), 1 );
+
 		}
 
 		if ( material.wireframe ) {
@@ -799,6 +840,14 @@ THREE.CanvasRenderer = function () {
 		_context.restore();
 	}
 
+	function normalToComponent( normal ) {
+
+		// https://gist.github.com/665829
+
+		return normal < 0 ? Math.min( 1 + normal, 0.5 ) : 0.5 + Math.min( normal, 0.5 );
+
+	}
+
 	// Hide anti-alias gaps
 
 	function expand( v1, v2 ) {

+ 8 - 4
utils/build.py

@@ -111,9 +111,10 @@ def buildFull(debug):
 		'materials/Material.js',
 		'materials/LineBasicMaterial.js',
 		'materials/MeshBasicMaterial.js',
-		'materials/MeshDepthMaterial.js',
 		'materials/MeshLambertMaterial.js',
 		'materials/MeshPhongMaterial.js',
+		'materials/MeshDepthMaterial.js',
+		'materials/MeshNormalMaterial.js',
 		'materials/MeshFaceMaterial.js',
 		'materials/ParticleBasicMaterial.js',
 		'materials/ParticleCircleMaterial.js',
@@ -164,9 +165,10 @@ def buildCanvas(debug):
 		'materials/Material.js',
 		'materials/LineBasicMaterial.js',
 		'materials/MeshBasicMaterial.js',
-		'materials/MeshDepthMaterial.js',
 		'materials/MeshLambertMaterial.js',
 		'materials/MeshPhongMaterial.js',
+		'materials/MeshDepthMaterial.js',
+		'materials/MeshNormalMaterial.js',
 		'materials/MeshFaceMaterial.js',
 		'materials/ParticleBasicMaterial.js',
 		'materials/ParticleCircleMaterial.js',
@@ -213,9 +215,10 @@ def buildWebGL(debug):
 		'materials/Material.js',
 		'materials/LineBasicMaterial.js',
 		'materials/MeshBasicMaterial.js',
-		'materials/MeshDepthMaterial.js',
 		'materials/MeshLambertMaterial.js',
 		'materials/MeshPhongMaterial.js',
+		'materials/MeshDepthMaterial.js',
+		'materials/MeshNormalMaterial.js',
 		'materials/MeshFaceMaterial.js',
 		'materials/ParticleBasicMaterial.js',
 		'materials/ParticleCircleMaterial.js',
@@ -257,9 +260,10 @@ def buildSVG(debug):
 		'materials/Material.js',
 		'materials/LineBasicMaterial.js',
 		'materials/MeshBasicMaterial.js',
-		'materials/MeshDepthMaterial.js',
 		'materials/MeshLambertMaterial.js',
 		'materials/MeshPhongMaterial.js',
+		'materials/MeshDepthMaterial.js',
+		'materials/MeshNormalMaterial.js',
 		'materials/MeshFaceMaterial.js',
 		'materials/ParticleBasicMaterial.js',
 		'materials/ParticleCircleMaterial.js',

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