Browse Source

ParticleBasicMaterial with a map attached are back on CanvasRenderer.
Added a simple example for that.

Mr.doob 14 years ago
parent
commit
14eb44a279
3 changed files with 244 additions and 79 deletions
  1. 53 57
      examples/lights_test.html
  2. 168 0
      examples/particles_sprites.html
  3. 23 22
      src/renderers/CanvasRenderer.js

+ 53 - 57
examples/lights_test.html

@@ -1,9 +1,10 @@
 <!DOCTYPE HTML>
 <!DOCTYPE HTML>
 <html lang="en">
 <html lang="en">
 	<head>
 	<head>
-		<title>three.js - Lights test</title>
+		<title>three.js - lights test</title>
 		<meta charset="utf-8">
 		<meta charset="utf-8">
 		<style type="text/css">
 		<style type="text/css">
+
 			body {
 			body {
 				background:#fff;
 				background:#fff;
 				padding:0;
 				padding:0;
@@ -19,27 +20,25 @@
 			#d { text-align:center; margin:1em 0 -15.7em 0; z-index:0; position:relative; display:block }
 			#d { text-align:center; margin:1em 0 -15.7em 0; z-index:0; position:relative; display:block }
 			.button { background:#000; color:#fff; padding:0.2em 0.5em; cursor:pointer }
 			.button { background:#000; color:#fff; padding:0.2em 0.5em; cursor:pointer }
 			.inactive { background:#999; color:#eee }
 			.inactive { background:#999; color:#eee }
+
 		</style>
 		</style>
 	</head>
 	</head>
-	
+
 	<body>
 	<body>
 		<div id="d">
 		<div id="d">
-			<h1>Lights test</h1>
+			<h1>lights test</h1>
 
 
 			<span id="rcanvas" class="button inactive">2d canvas renderer</span>
 			<span id="rcanvas" class="button inactive">2d canvas renderer</span>
 			<span id="rwebgl" class="button">WebGL renderer</span>
 			<span id="rwebgl" class="button">WebGL renderer</span>
 			<br/>
 			<br/>
-			
-			<p>Using a modified version of <a href="http://github.com/alteredq/three.js">Three.js</a> by mrdoob.
-			
-			<br/>
+
 			<p>Best viewed in Chrome 8/9 or Firefox 4 using WebGL renderer.
 			<p>Best viewed in Chrome 8/9 or Firefox 4 using WebGL renderer.
 			<p>Canvas renderer is very slow on anything other than Chrome.
 			<p>Canvas renderer is very slow on anything other than Chrome.
 		</div>
 		</div>
-		
+
 		<pre id="log"></pre>
 		<pre id="log"></pre>
 
 
-		<script type="text/javascript" src="../build/Three.js"></script> 
+		<script type="text/javascript" src="../build/Three.js"></script>
 
 
 		<script type="text/javascript" src="../src/extras/io/Loader.js"></script>
 		<script type="text/javascript" src="../src/extras/io/Loader.js"></script>
 		<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script>
 		<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script>
@@ -53,41 +52,37 @@
 			var SCREEN_HEIGHT = window.innerHeight;
 			var SCREEN_HEIGHT = window.innerHeight;
 			var FLOOR = -250;
 			var FLOOR = -250;
 
 
-			var container;
-			var stats;
+			var container, stats;
 
 
-			var camera;
-			var scene;
-			var canvasRenderer, webglRenderer;
+			var camera, scene, canvasRenderer, webglRenderer;
 
 
 			var mesh, zmesh, lightMesh, geometry;
 			var mesh, zmesh, lightMesh, geometry;
 
 
 			var directionalLight, pointLight;
 			var directionalLight, pointLight;
 
 
-			var mouseX = 0;
-			var mouseY = 0;
+			var mouseX = 0, mouseY = 0;
 
 
-			var windowHalfX = window.innerWidth >> 1;
-			var windowHalfY = window.innerHeight >> 1;
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
 
 
 			var render_canvas = 1, render_gl = 1;
 			var render_canvas = 1, render_gl = 1;
 			var has_gl = 0;
 			var has_gl = 0;
-			
-			var bcanvas = document.getElementById("rcanvas");
-			var bwebgl = document.getElementById("rwebgl");
-			
+
+			var bcanvas = document.getElementById( 'rcanvas' );
+			var bwebgl = document.getElementById( 'rwebgl' );
+
 			document.addEventListener('mousemove', onDocumentMouseMove, false);
 			document.addEventListener('mousemove', onDocumentMouseMove, false);
 
 
 			init();
 			init();
-			
+
 			loop();
 			loop();
-			
+
 			//render_canvas = !has_gl;
 			//render_canvas = !has_gl;
-			bwebgl.style.display = has_gl ? "inline" : "none";
-			bcanvas.className = render_canvas ? "button" : "button inactive";
-			
+			bwebgl.style.display = has_gl ? 'inline' : 'none';
+			bcanvas.className = render_canvas ? 'button' : 'button inactive';
+
 			setInterval(loop, 1000/60);
 			setInterval(loop, 1000/60);
-			
+
 			function init() {
 			function init() {
 
 
 				container = document.createElement('div');
 				container = document.createElement('div');
@@ -98,10 +93,10 @@
 				camera.updateMatrix();
 				camera.updateMatrix();
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
-				
-				
+
+
 				// SPHERES
 				// SPHERES
-				
+
 				sphere = new Sphere( 100, 16, 8 );
 				sphere = new Sphere( 100, 16, 8 );
 				for (var i=0; i<30; i++) {
 				for (var i=0; i<30; i++) {
 					mesh = new THREE.Mesh( sphere, new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading } ) );
 					mesh = new THREE.Mesh( sphere, new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading } ) );
@@ -113,7 +108,7 @@
 					mesh.updateMatrix();
 					mesh.updateMatrix();
 					scene.addObject(mesh);
 					scene.addObject(mesh);
 				}
 				}
-				
+
 
 
 				// LIGHTS
 				// LIGHTS
 
 
@@ -164,7 +159,7 @@
 				stats.domElement.style.top = '0px';
 				stats.domElement.style.top = '0px';
 				stats.domElement.style.zIndex = 100;
 				stats.domElement.style.zIndex = 100;
 				container.appendChild( stats.domElement );
 				container.appendChild( stats.domElement );
-				
+
 				bcanvas.addEventListener("click", toggleCanvas, false);
 				bcanvas.addEventListener("click", toggleCanvas, false);
 				bwebgl.addEventListener("click", toggleWebGL, false);
 				bwebgl.addEventListener("click", toggleWebGL, false);
 
 
@@ -176,7 +171,7 @@
 			}
 			}
 
 
 			function createScene( geometry ) {
 			function createScene( geometry ) {
-				
+
 				zmesh = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0xffffff } ) );
 				zmesh = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0xffffff } ) );
 				zmesh.position.x = 0;
 				zmesh.position.x = 0;
 				zmesh.position.z = 0;
 				zmesh.position.z = 0;
@@ -185,10 +180,10 @@
 				zmesh.overdraw = true;
 				zmesh.overdraw = true;
 				zmesh.updateMatrix();
 				zmesh.updateMatrix();
 				scene.addObject(zmesh);
 				scene.addObject(zmesh);
-				
+
 			}
 			}
 
 
-			
+
 			function onDocumentMouseMove(event) {
 			function onDocumentMouseMove(event) {
 
 
 				mouseX = ( event.clientX - windowHalfX );
 				mouseX = ( event.clientX - windowHalfX );
@@ -197,14 +192,14 @@
 			}
 			}
 
 
 			var r = 0;
 			var r = 0;
-			
+
 			function loop() {
 			function loop() {
 
 
 				camera.position.x += ( mouseX - camera.position.x ) * .05;
 				camera.position.x += ( mouseX - camera.position.x ) * .05;
 				camera.position.y += ( - mouseY - camera.position.y ) * .05;
 				camera.position.y += ( - mouseY - camera.position.y ) * .05;
 				camera.updateMatrix();
 				camera.updateMatrix();
-				
-				
+
+
 				for(var i=0; i<scene.objects.length; ++i) {
 				for(var i=0; i<scene.objects.length; ++i) {
 					if ( i%3 == 1 )
 					if ( i%3 == 1 )
 						scene.objects[i].rotation.x += 0.05;
 						scene.objects[i].rotation.x += 0.05;
@@ -212,17 +207,17 @@
 						scene.objects[i].rotation.y += 0.05;
 						scene.objects[i].rotation.y += 0.05;
 					else if ( i%3 == 0 )
 					else if ( i%3 == 0 )
 						scene.objects[i].rotation.z += 0.05;
 						scene.objects[i].rotation.z += 0.05;
-						
+
 					scene.objects[i].updateMatrix();
 					scene.objects[i].updateMatrix();
 				}
 				}
-				
-				
+
+
 				lightMesh.position.x = 200*Math.cos(r);
 				lightMesh.position.x = 200*Math.cos(r);
 				lightMesh.position.z = 200*Math.sin(r);
 				lightMesh.position.z = 200*Math.sin(r);
 				lightMesh.updateMatrix();
 				lightMesh.updateMatrix();
 
 
 				r += 0.1;
 				r += 0.1;
-				
+
 				if ( render_canvas ) canvasRenderer.render( scene, camera );
 				if ( render_canvas ) canvasRenderer.render( scene, camera );
 				if ( render_gl && has_gl ) webglRenderer.render( scene, camera );
 				if ( render_gl && has_gl ) webglRenderer.render( scene, camera );
 
 
@@ -231,41 +226,42 @@
 			}
 			}
 
 
 			function log(text) {
 			function log(text) {
-			
+
 				var e = document.getElementById("log");
 				var e = document.getElementById("log");
 				e.innerHTML = text + "<br/>" + e.innerHTML;
 				e.innerHTML = text + "<br/>" + e.innerHTML;
-				
+
 			}
 			}
-			
+
 			function toggleCanvas() {
 			function toggleCanvas() {
-			
+
 				render_canvas = !render_canvas;
 				render_canvas = !render_canvas;
 				bcanvas.className = render_canvas ? "button" : "button inactive";
 				bcanvas.className = render_canvas ? "button" : "button inactive";
-				
+
 				render_gl = !render_canvas;
 				render_gl = !render_canvas;
 				bwebgl.className = render_gl ? "button" : "button inactive";
 				bwebgl.className = render_gl ? "button" : "button inactive";
-				
+
 				if( has_gl )
 				if( has_gl )
 					webglRenderer.domElement.style.display = render_gl ? "block" : "none";
 					webglRenderer.domElement.style.display = render_gl ? "block" : "none";
-				
+
 				canvasRenderer.domElement.style.display = render_canvas ? "block" : "none";
 				canvasRenderer.domElement.style.display = render_canvas ? "block" : "none";
-				
+
 			}
 			}
-			
+
 			function toggleWebGL() {
 			function toggleWebGL() {
-			
+
 				render_gl = !render_gl;
 				render_gl = !render_gl;
 				bwebgl.className = render_gl ? "button" : "button inactive";
 				bwebgl.className = render_gl ? "button" : "button inactive";
-				
+
 				render_canvas = !render_gl;
 				render_canvas = !render_gl;
 				bcanvas.className = render_canvas ? "button" : "button inactive";
 				bcanvas.className = render_canvas ? "button" : "button inactive";
-				
+
 				if( has_gl )
 				if( has_gl )
 					webglRenderer.domElement.style.display = render_gl ? "block" : "none";
 					webglRenderer.domElement.style.display = render_gl ? "block" : "none";
-					
+
 				canvasRenderer.domElement.style.display = render_canvas ? "block" : "none";
 				canvasRenderer.domElement.style.display = render_canvas ? "block" : "none";
-				
+
 			}
 			}
+
 		</script>
 		</script>
 
 
 	</body>
 	</body>

+ 168 - 0
examples/particles_sprites.html

@@ -0,0 +1,168 @@
+<!DOCTYPE HTML>
+<html lang="en">
+	<head>
+		<title>three.js - particles - sprites</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
+		<style type="text/css">
+			body {
+				background-color: #000000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			a {
+				color:#0078ff;
+			}
+		</style>
+	</head>
+	<body>
+
+		<script type="text/javascript" src="../build/Three.js"></script>
+		<script type="text/javascript" src="js/Tween.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
+
+		<script type="text/javascript">
+
+			var container, stats;
+			var camera, scene, renderer, particle;
+			var mouseX = 0, mouseY = 0;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+
+			init();
+			setInterval( loop, 1000 / 60 );
+
+			function init() {
+
+				container = document.createElement('div');
+				document.body.appendChild(container);
+
+				camera = new THREE.Camera( 75, window.innerWidth / window.innerHeight, 1, 5000 );
+				camera.position.z = 1000;
+
+				scene = new THREE.Scene();
+
+				renderer = new THREE.CanvasRenderer();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				var material = new THREE.ParticleBasicMaterial( { map: createSprite(), blending: THREE.AdditiveBlending } );
+
+				for ( var i = 0; i < 1000; i++ ) {
+
+					particle = new THREE.Particle( material );
+
+					initParticle( particle, i * 10 );
+
+					scene.addObject( particle );
+				}
+
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
+			}
+
+
+			function createSprite() {
+
+				var canvas = document.createElement( 'canvas' );
+				canvas.width = 16;
+				canvas.height = 16;
+
+				var context = canvas.getContext( '2d' );
+				var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 );
+				gradient.addColorStop( 0, 'rgba(255,255,255,1)' );
+				gradient.addColorStop( 0.2, 'rgba(0,255,255,1)' );
+				gradient.addColorStop( 0.4, 'rgba(0,0,64,1)' );
+				gradient.addColorStop( 1, 'rgba(0,0,0,1)' );
+
+				context.fillStyle = gradient;
+				context.fillRect( 0, 0, canvas.width, canvas.height );
+
+				return canvas;
+
+			}
+
+			function initParticle( particle, delay ) {
+
+				var particle = this instanceof THREE.Particle ? this : particle;
+				var delay = delay !== undefined ? delay : 0;
+
+				particle.position.x = 0;
+				particle.position.y = 0;
+				particle.position.z = 0;
+				particle.scale.x = particle.scale.y = Math.random() * 3 + 1;
+
+				new TWEEN.Tween( particle )
+					.delay( delay )
+					.to( {}, 10000 )
+					.onComplete( initParticle )
+					.start();
+
+				new TWEEN.Tween( particle.position )
+					.delay( delay )
+					.to( { x: Math.random() * 4000 - 2000, y: Math.random() * 1000 - 500, z: Math.random() * 4000 - 2000 }, 10000 )
+					.start();
+
+				new TWEEN.Tween( particle.scale )
+					.delay( delay )
+					.to( { x: 0, y: 0 }, 10000 )
+					.start();
+
+			}
+
+			//
+
+			function onDocumentMouseMove( event ) {
+
+				mouseX = event.clientX - windowHalfX;
+				mouseY = event.clientY - windowHalfY;
+			}
+
+			function onDocumentTouchStart( event ) {
+
+				if ( event.touches.length == 1 ) {
+
+					event.preventDefault();
+
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
+				}
+			}
+
+			function onDocumentTouchMove( event ) {
+
+				if ( event.touches.length == 1 ) {
+
+					event.preventDefault();
+
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
+				}
+			}
+
+			//
+
+			function loop() {
+
+				TWEEN.update();
+
+				camera.position.x += ( mouseX - camera.position.x ) * 0.05;
+				camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
+
+				renderer.render( scene, camera );
+
+				stats.update();
+			}
+
+		</script>
+	</body>
+</html>

+ 23 - 22
src/renderers/CanvasRenderer.js

@@ -393,43 +393,44 @@ THREE.CanvasRenderer = function () {
 		setOpacity( material.opacity );
 		setOpacity( material.opacity );
 		setBlending( material.blending );
 		setBlending( material.blending );
 
 
-		var width, height, scaleX, scaleY, offsetX, offsetY,
+		var width, height, scaleX, scaleY,
 		bitmap, bitmapWidth, bitmapHeight;
 		bitmap, bitmapWidth, bitmapHeight;
 
 
 		if ( material instanceof THREE.ParticleBasicMaterial ) {
 		if ( material instanceof THREE.ParticleBasicMaterial ) {
 
 
-			bitmap = material.bitmap;
-			bitmapWidth = bitmap.width / 2;
-			bitmapHeight = bitmap.height / 2;
+			if ( material.map ) {
 
 
-			scaleX = element.scale.x * _canvasWidthHalf;
-			scaleY = element.scale.y * _canvasHeightHalf;
+				bitmap = material.map;
+				bitmapWidth = bitmap.width >> 1;
+				bitmapHeight = bitmap.height >> 1;
 
 
-			width = scaleX * bitmapWidth;
-			height = scaleY * bitmapHeight;
+				scaleX = element.scale.x * _canvasWidthHalf;
+				scaleY = element.scale.y * _canvasHeightHalf;
 
 
-			offsetX = material.offset.x * scaleX;
-			offsetY = material.offset.y * scaleY;
+				width = scaleX * bitmapWidth;
+				height = scaleY * bitmapHeight;
 
 
-			// TODO: Rotations break this...
+				// TODO: Rotations break this...
 
 
-			_bboxRect.set( v1.x + offsetX - width, v1.y + offsetY - height, v1.x + offsetX + width, v1.y + offsetY + height );
+				_bboxRect.set( v1.x - width, v1.y - height, v1.x  + width, v1.y + height );
 
 
-			if ( !_clipRect.instersects( _bboxRect ) ) {
+				if ( !_clipRect.instersects( _bboxRect ) ) {
 
 
-				return;
+					return;
 
 
-			}
+				}
 
 
-			_context.save();
-			_context.translate( v1.x, v1.y );
-			_context.rotate( - element.rotation );
-			_context.scale( scaleX, - scaleY );
-			_context.translate( - bitmapWidth + material.offset.x, - bitmapHeight - material.offset.y );
+				_context.save();
+				_context.translate( v1.x, v1.y );
+				_context.rotate( - element.rotation );
+				_context.scale( scaleX, - scaleY );
+				_context.translate( - bitmapWidth, - bitmapHeight );
 
 
-			_context.drawImage( bitmap, 0, 0 );
+				_context.drawImage( bitmap, 0, 0 );
 
 
-			_context.restore();
+				_context.restore();
+
+			}
 
 
 			/* DEBUG
 			/* DEBUG
 			_context.beginPath();
 			_context.beginPath();