Browse Source

CanvasRenderer: Match WebGLRenderer's handling of Offset/Repeat for Sprites

WestLangley 11 years ago
parent
commit
f16ea15bb2
2 changed files with 145 additions and 48 deletions
  1. 88 25
      examples/misc_ubiquity_test2.html
  2. 57 23
      src/renderers/CanvasRenderer.js

+ 88 - 25
examples/misc_ubiquity_test2.html

@@ -6,7 +6,7 @@
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
 		<style>
 			body {
 			body {
-				background-color: #ffffff;
+				background-color: #000;
 				margin: 0px;
 				margin: 0px;
 				overflow: hidden;
 				overflow: hidden;
 			}
 			}
@@ -17,6 +17,9 @@
 		<script src="../build/three.min.js"></script>
 		<script src="../build/three.min.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 
+		<div id='container1' style='float: left '></div>
+		<div id='container2' style='float: right'></div>
+
 		<script>
 		<script>
 
 
 			var stats;
 			var stats;
@@ -24,73 +27,132 @@
 			var camera, scene;
 			var camera, scene;
 			var canvasRenderer, webglRenderer;
 			var canvasRenderer, webglRenderer;
 
 
-			var texture, mesh;
-			var texture2;
+			var mesh;
+			var texture, texture1, texture2, texture3;
 
 
 			init();
 			init();
 			animate();
 			animate();
 
 
 			function init() {
 			function init() {
 
 
-				var width = window.innerWidth / 2;
+				var width = window.innerWidth / 2 - 2;
 				var height = window.innerHeight;
 				var height = window.innerHeight;
 
 
-				camera = new THREE.PerspectiveCamera( 70, width / height, 1, 2000 );
-				camera.position.z = 400;
+				camera = new THREE.PerspectiveCamera( 70, width / height, 1, 4000 );
+				camera.position.z = 2000;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 
 
-				var geometry = new THREE.CubeGeometry( 200, 200, 200, 4, 4, 4 );
+
+				// MESH - Repeat Pattern
 
 
 				texture = THREE.ImageUtils.loadTexture( 'textures/UV_Grid_Sm.jpg' );
 				texture = THREE.ImageUtils.loadTexture( 'textures/UV_Grid_Sm.jpg' );
 				texture.wrapS = THREE.RepeatWrapping;
 				texture.wrapS = THREE.RepeatWrapping;
 				texture.wrapT = THREE.RepeatWrapping;
 				texture.wrapT = THREE.RepeatWrapping;
 
 
-				var material = new THREE.MeshBasicMaterial( { map: texture } );
+				var geometry = new THREE.CubeGeometry( 150, 150, 150, 4, 4, 4 );
+				var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
 
 
 				mesh = new THREE.Mesh( geometry, material );
 				mesh = new THREE.Mesh( geometry, material );
 				scene.add( mesh );
 				scene.add( mesh );
 
 
-				// SPRITES
 
 
-				texture2 = THREE.ImageUtils.loadTexture( 'textures/sprite.png' );
+				// SPRITES - from Sprite Sheet
+
+				texture1 = THREE.ImageUtils.loadTexture( 'textures/UV_Grid_Sm.jpg', undefined, function() {
+
+					texture1.wrapS = THREE.ClampToEdgeWrapping;
+					texture1.wrapT = THREE.ClampToEdgeWrapping;
+
+					for ( var i = 0; i < 20; i ++ ) {
+
+						var tex = texture1.clone();
+
+						tex.needsUpdate = true; // cloning does not set this
+
+						tex.offset.x = 0.1 * THREE.Math.randInt( 0, 7 );
+						tex.offset.y = 0.1 * THREE.Math.randInt( 0, 7 );
+						tex.repeat.x = 0.1 * THREE.Math.randInt( 1, 3 );
+						tex.repeat.y = 0.1 * THREE.Math.randInt( 1, 3 );
+
+						var material = new THREE.SpriteMaterial( { map: tex } );
+						var sprite = new THREE.Sprite( material );
+
+						sprite.material.rotation = 0.5 * Math.PI * ( Math.random() - 0.5 );
+
+						sprite.position.x = Math.random() * 1000 - 500;
+						sprite.position.y = Math.random() * 1000 - 500;
+						sprite.position.z = Math.random() * 1000 - 500;
+
+						sprite.scale.set( 96, 96, 1 );
+
+						scene.add( sprite );
+
+					}
+
+				} );
+
+
+				// SPRITES - Repeat Pattern
+
+				texture2 = THREE.ImageUtils.loadTexture( 'textures/sprite0.jpg' );
 				texture2.wrapS = THREE.RepeatWrapping;
 				texture2.wrapS = THREE.RepeatWrapping;
 				texture2.wrapT = THREE.RepeatWrapping;
 				texture2.wrapT = THREE.RepeatWrapping;
-				var material = new THREE.SpriteMaterial( { map: texture2 } );
 
 
-				for ( var i = 0; i < 50; i ++ ) {
+				for ( var i = 0; i < 20; i ++ ) {
 
 
+					var material = new THREE.SpriteMaterial( { map: texture2, opacity: 0.7 } );
 					var sprite = new THREE.Sprite( material );
 					var sprite = new THREE.Sprite( material );
+
+					//sprite.material.rotation = Math.random(); // rotation is not supported by CanvasRenderer when repeating textures
+
 					sprite.position.x = Math.random() * 1000 - 500;
 					sprite.position.x = Math.random() * 1000 - 500;
 					sprite.position.y = Math.random() * 1000 - 500;
 					sprite.position.y = Math.random() * 1000 - 500;
 					sprite.position.z = Math.random() * 1000 - 500;
 					sprite.position.z = Math.random() * 1000 - 500;
+
 					sprite.scale.set( 64, 64, 1 );
 					sprite.scale.set( 64, 64, 1 );
+
 					scene.add( sprite );
 					scene.add( sprite );
 
 
 				}
 				}
 
 
-				for ( var i = 0; i < 50; i ++ ) {
 
 
-					var material = new THREE.SpriteMaterial( { color: Math.random() * 0xffffff } );
+				// SPRITES - PNG
+
+				for ( var i = 0; i < 20; i ++ ) {
+
+					texture3 = THREE.ImageUtils.loadTexture( 'textures/sprite1.png' );
+					texture3.wrapS = THREE.ClampToEdgeWrapping;
+					texture3.wrapT = THREE.ClampToEdgeWrapping;
+
+					var material = new THREE.SpriteMaterial( { map: texture3 } );
 					var sprite = new THREE.Sprite( material );
 					var sprite = new THREE.Sprite( material );
+
+					sprite.material.rotation = 2 * Math.PI * ( Math.random() - 0.5 );
+
 					sprite.position.x = Math.random() * 1000 - 500;
 					sprite.position.x = Math.random() * 1000 - 500;
 					sprite.position.y = Math.random() * 1000 - 500;
 					sprite.position.y = Math.random() * 1000 - 500;
 					sprite.position.z = Math.random() * 1000 - 500;
 					sprite.position.z = Math.random() * 1000 - 500;
+
 					sprite.scale.set( 64, 64, 1 );
 					sprite.scale.set( 64, 64, 1 );
+
 					scene.add( sprite );
 					scene.add( sprite );
 
 
 				}
 				}
 
 
+				//
 
 
 				canvasRenderer = new THREE.CanvasRenderer();
 				canvasRenderer = new THREE.CanvasRenderer();
 				canvasRenderer.setClearColor( 0xf0f0f0 );
 				canvasRenderer.setClearColor( 0xf0f0f0 );
 				canvasRenderer.setSize( width, height );
 				canvasRenderer.setSize( width, height );
-				document.body.appendChild( canvasRenderer.domElement );
+				var container1 = document.getElementById( 'container1' );
+				container1.appendChild( canvasRenderer.domElement );
 
 
 				webglRenderer = new THREE.WebGLRenderer( { antialias: true } );
 				webglRenderer = new THREE.WebGLRenderer( { antialias: true } );
 				webglRenderer.setClearColor( 0xf0f0f0 );
 				webglRenderer.setClearColor( 0xf0f0f0 );
 				webglRenderer.setSize( width, height );
 				webglRenderer.setSize( width, height );
-				document.body.appendChild( webglRenderer.domElement );
+				var container2 = document.getElementById( 'container2' );
+				container2.appendChild( webglRenderer.domElement );
 
 
 				stats = new Stats();
 				stats = new Stats();
 				stats.domElement.style.position = 'absolute';
 				stats.domElement.style.position = 'absolute';
@@ -105,7 +167,7 @@
 
 
 			function onWindowResize() {
 			function onWindowResize() {
 
 
-				var width = window.innerWidth / 2;
+				var width = window.innerWidth / 2 - 2;
 				var height = window.innerHeight;
 				var height = window.innerHeight;
 
 
 				camera.aspect = width / height;
 				camera.aspect = width / height;
@@ -135,27 +197,27 @@
 				camera.position.z = Math.cos( time ) * 500;
 				camera.position.z = Math.cos( time ) * 500;
 				camera.lookAt( scene.position );
 				camera.lookAt( scene.position );
 
 
-				texture.repeat.x = Math.sin( time ) * 0.5 + 0.5;
-				texture.repeat.y = Math.cos( time ) * 0.5 + 0.5;
+				//
+
+				texture.repeat.x = Math.sin( time ) * 0.5 + 1.0;
+				texture.repeat.y = Math.cos( time ) * 0.5 + 1.0;
 
 
-				texture.offset.x = Math.sin( time );
-				texture.offset.y = Math.cos( time );
+				texture.offset.x = Math.sin( time ) * 0.5 + 0.5;
+				texture.offset.y = Math.cos( time ) * 0.5 + 0.5;
 
 
 				mesh.rotation.x = time * 2;
 				mesh.rotation.x = time * 2;
 				mesh.rotation.y = time * 4;
 				mesh.rotation.y = time * 4;
 
 
 				//
 				//
 
 
-				texture2.repeat.x = Math.sin( time ) * 0.5 + 0.5;
-				texture2.repeat.y = Math.cos( time ) * 0.5 + 0.5;
+				texture2.repeat.x = Math.sin( time ) + 2.0;
+				texture2.repeat.y = Math.sin( time ) + 2.0;
 
 
 				texture2.offset.x = Math.sin( time );
 				texture2.offset.x = Math.sin( time );
 				texture2.offset.y = Math.cos( time );
 				texture2.offset.y = Math.cos( time );
 
 
 				//
 				//
 
 
-				scene.updateMatrixWorld();
-
 				canvasRenderer.render( scene, camera );
 				canvasRenderer.render( scene, camera );
 				webglRenderer.render( scene, camera );
 				webglRenderer.render( scene, camera );
 
 
@@ -164,4 +226,5 @@
 		</script>
 		</script>
 
 
 	</body>
 	</body>
+
 </html>
 </html>

+ 57 - 23
src/renderers/CanvasRenderer.js

@@ -488,36 +488,70 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 				}
 				}
 
 
-				var pattern = _patterns[ texture.id ];
+				//
 
 
-				if ( pattern !== undefined ) {
+				if ( texture.repeat.x <= 1 && texture.repeat.y <= 1 ) { // rotation supported
 
 
-					setFillStyle( pattern );
+					var bitmap = texture.image;
 
 
-				} else {
+					var ox = bitmap.width * texture.offset.x;
+					var oy = bitmap.height * ( 1 - texture.offset.y - texture.repeat.y );
 
 
-					setFillStyle( 'rgba(0,0,0,1)' );
+					var sx = bitmap.width * texture.repeat.x;
+					var sy = bitmap.height * texture.repeat.y;
 
 
-				}
+					_context.save();
 
 
-				_context.save();
-				_context.translate( v1.x, v1.y );
-				if ( material.rotation !== 0 ) _context.rotate( material.rotation );
-				_context.scale( scaleX, - scaleY );
-				_context.beginPath();
-				_context.moveTo( - 0.5, - 0.5 );
-				_context.lineTo(   0.5, - 0.5 );
-				_context.lineTo(   0.5,   0.5 );
-				_context.lineTo( - 0.5,   0.5 );
-				_context.closePath();
-				_context.translate( - 0.5, 0.5 );
-				_context.translate( - texture.offset.x, texture.offset.y );
-				_context.scale( 1 / texture.image.width, - 1 / texture.image.height );
-				_context.scale( 1 / texture.repeat.x, 1 / texture.repeat.y );
-				_context.fill();
-				_context.restore();
+					_context.translate( v1.x, v1.y );
 
 
-			} else {
+					if ( material.rotation ) _context.rotate( material.rotation );
+
+					_context.scale( scaleX, - scaleY );
+
+					_context.drawImage( bitmap, ox, oy, sx, sy, - 0.5, - 0.5, 1, 1 );
+
+					_context.restore();
+
+				} else { // repeat.x or repeat.y > 1 // rotation not supported
+
+					var bitmap = texture.image;
+
+					var ox = bitmap.width * texture.offset.x;
+					var oy = bitmap.height * texture.offset.y;
+
+					var sx = bitmap.width * texture.repeat.x;
+					var sy = bitmap.height * texture.repeat.y;
+
+					var cx = sx / scaleX;
+					var cy = sy / scaleY;
+
+					var pattern = _patterns[ texture.id ];
+
+					if ( pattern !== undefined ) {
+
+						setFillStyle( pattern );
+
+					} else {
+
+						setFillStyle( 'rgba( 0, 0, 0, 1 )' );
+
+					}
+
+					_context.save();
+
+					_context.scale( 1 / cx, 1 / cy );
+
+					_context.translate( v1.x * cx - 0.5 * sx - ox, v1.y * cy - 0.5 * sy - oy );
+
+					//if ( material.rotation ) _context.rotate( material.rotation ); // rotation not supported when using patterns (origin is offset)
+
+					_context.fillRect( ox, oy, sx, sy );
+
+					_context.restore();
+
+				}
+
+			} else { // no texture
 
 
 				setFillStyle( material.color.getStyle() );
 				setFillStyle( material.color.getStyle() );