Browse Source

Use InstancedMesh in interleaved instancing example.

Don McCurdy 5 years ago
parent
commit
dbfdeac855
1 changed files with 59 additions and 116 deletions
  1. 59 116
      examples/webgl_buffergeometry_instancing_interleaved.html

+ 59 - 116
examples/webgl_buffergeometry_instancing_interleaved_dynamic.html → examples/webgl_buffergeometry_instancing_interleaved.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 <head>
-	<title>three.js webgl - indexed instancing (single box), interleaved buffers, dynamic updates</title>
+	<title>three.js webgl - indexed instancing (single box), interleaved buffers</title>
 	<meta charset="utf-8">
 	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 	<link type="text/css" rel="stylesheet" href="main.css">
@@ -22,68 +22,29 @@
 
 	<div id="container"></div>
 	<div id="info">
-		<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - indexed instancing (single box)<br/>interleaved buffers, dynamic updates
+		<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - indexed instancing (single box), interleaved buffers
 		<div id="notSupported" style="display:none">Sorry your graphics card + browser does not support hardware instancing</div>
 	</div>
 
-	<script id="vertexShader" type="x-shader/x-vertex">
-		precision highp float;
-
-		uniform mat4 modelViewMatrix;
-		uniform mat4 projectionMatrix;
-
-		attribute vec3 position;
-		attribute vec3 offset;
-		attribute vec2 uv;
-		attribute vec4 orientation;
-
-		varying vec2 vUv;
-
-		// http://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/
-
-		vec3 applyQuaternionToVector( vec4 q, vec3 v ){
-
-			return v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );
-
-		}
-
-		void main() {
-
-			vec3 vPosition = applyQuaternionToVector( orientation, position );
-
-			vUv = uv;
-
-			gl_Position = projectionMatrix * modelViewMatrix * vec4( offset + vPosition, 1.0 );
-
-		}
-
-	</script>
-
-	<script id="fragmentShader" type="x-shader/x-fragment">
-		precision highp float;
-
-		uniform sampler2D map;
-
-		varying vec2 vUv;
-
-		void main() {
-
-			gl_FragColor = texture2D(map, vUv);
-
-		}
-
-	</script>
-
 	<script type="module">
 		import * as THREE from '../build/three.module.js';
 
 		import Stats from './jsm/libs/stats.module.js';
 
 		var container, stats;
+		var camera, scene, renderer, mesh;
+		var offsetAttribute, orientationAttribute;
+
+		var instances = 5000;
+		var lastTime = 0;
 
-		var camera, scene, renderer;
-		var orientations, instanceBuffer;
+		var moveQ = new THREE.Quaternion( 0.5, 0.5, 0.5, 0.0 ).normalize();
+		var tmpQ = new THREE.Quaternion();
+		var tmpM = new THREE.Matrix4();
+		var currentM = new THREE.Matrix4();
 
+		init();
+		animate();
 
 		function init() {
 
@@ -94,12 +55,8 @@
 			scene = new THREE.Scene();
 			scene.background = new THREE.Color( 0x101010 );
 
-			renderer = new THREE.WebGLRenderer();
-
 			// geometry
 
-			var instances = 5000;
-
 			var geometry = new THREE.InstancedBufferGeometry();
 
 			// per mesh data x,y,z,w,u,v,s,t for 4-element alignment
@@ -161,69 +118,63 @@
 
 			geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
 
-			// per instance data
-			instanceBuffer = new THREE.InstancedInterleavedBuffer( new Float32Array( instances * 8 ), 8, 1 ).setUsage( THREE.DynamicDrawUsage );
-			var offsets = new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 0 );
+			// material
 
-			var vector = new THREE.Vector4();
-			for ( var i = 0, ul = offsets.count; i < ul; i ++ ) {
+			var material = new THREE.MeshBasicMaterial();
+			material.map = new THREE.TextureLoader().load( 'textures/crate.gif' );
+			material.side = THREE.DoubleSide;
 
-				var x = Math.random() * 100 - 50;
-				var y = Math.random() * 100 - 50;
-				var z = Math.random() * 100 - 50;
-				vector.set( x, y, z, 0 ).normalize();
-				// move out at least 5 units from center in current direction
-				offsets.setXYZ( i, x + vector.x * 5, y + vector.y * 5, z + vector.z * 5 );
+			// per instance data
 
-			}
+			var matrix = new THREE.Matrix4();
+			var offset = new THREE.Vector3();
+			var orientation = new THREE.Quaternion();
+			var scale = new THREE.Vector3( 1, 1, 1 );
+			var x, y, z, w;
 
-			geometry.setAttribute( 'offset', offsets ); // per mesh translation
+			mesh = new THREE.InstancedMesh( geometry, material, instances );
 
-			orientations = new THREE.InterleavedBufferAttribute( instanceBuffer, 4, 4 );
+			for ( var i = 0; i < instances; i ++ ) {
 
-			for ( var i = 0, ul = orientations.count; i < ul; i ++ ) {
+				// offsets
 
-				vector.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
-				vector.normalize();
+				x = Math.random() * 100 - 50;
+				y = Math.random() * 100 - 50;
+				z = Math.random() * 100 - 50;
 
-				orientations.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
+				offset.set( x, y, z ).normalize();
+				offset.multiplyScalar( 5 ); // move out at least 5 units from center in current direction
+				offset.set( x + offset.x, y + offset.y, z + offset.z );
 
-			}
+				// orientations
 
-			geometry.setAttribute( 'orientation', orientations ); // per mesh orientation
+				x = Math.random() * 2 - 1;
+				y = Math.random() * 2 - 1;
+				z = Math.random() * 2 - 1;
+				w = Math.random() * 2 - 1;
 
-			// material
-			var texture = new THREE.TextureLoader().load( 'textures/crate.gif' );
-			texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
+				orientation.set( x, y, z, w ).normalize();
 
-			var material = new THREE.RawShaderMaterial( {
+				matrix.compose( offset, orientation, scale );
 
-				uniforms: {
-					map: { value: texture }
-				},
-				vertexShader: document.getElementById( 'vertexShader' ).textContent,
-				fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
-				side: THREE.DoubleSide,
-				transparent: false
+				mesh.setMatrixAt( i, matrix );
 
-			} );
+			}
 
-			var mesh = new THREE.Mesh( geometry, material );
-			mesh.frustumCulled = false;
 			scene.add( mesh );
 
+			renderer = new THREE.WebGLRenderer();
+			renderer.setPixelRatio( window.devicePixelRatio );
+			renderer.setSize( window.innerWidth, window.innerHeight );
+			container.appendChild( renderer.domElement );
 
 			if ( renderer.extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
 
-				document.getElementById( "notSupported" ).style.display = "";
+				document.getElementById( 'notSupported' ).style.display = '';
 				return;
 
 			}
 
-			renderer.setPixelRatio( window.devicePixelRatio );
-			renderer.setSize( window.innerWidth, window.innerHeight );
-			container.appendChild( renderer.domElement );
-
 			stats = new Stats();
 			container.appendChild( stats.dom );
 
@@ -251,44 +202,36 @@
 
 		}
 
-		var lastTime = 0;
-
-		var moveQ = ( new THREE.Quaternion( .5, .5, .5, 0.0 ) ).normalize();
-		var tmpQ = new THREE.Quaternion();
-		var currentQ = new THREE.Quaternion();
 		function render() {
 
 			var time = performance.now();
 
-
-			var object = scene.children[ 0 ];
-
-			object.rotation.y = time * 0.00005;
-
-			renderer.render( scene, camera );
+			mesh.rotation.y = time * 0.00005;
 
 			var delta = ( time - lastTime ) / 5000;
 			tmpQ.set( moveQ.x * delta, moveQ.y * delta, moveQ.z * delta, 1 ).normalize();
+			tmpM.makeRotationFromQuaternion( tmpQ );
 
-			for ( var i = 0, ul = orientations.count; i < ul; i ++ ) {
+			for ( var i = 0, il = instances; i < il; i ++ ) {
 
-				var index = i * instanceBuffer.stride + orientations.offset;
-				currentQ.set( instanceBuffer.array[ index ], instanceBuffer.array[ index + 1 ], instanceBuffer.array[ index + 2 ], instanceBuffer.array[ index + 3 ] );
-				currentQ.multiply( tmpQ );
-
-				orientations.setXYZW( i, currentQ.x, currentQ.y, currentQ.z, currentQ.w );
+				mesh.getMatrixAt( i, currentM );
+				currentM.multiply( tmpM );
+				mesh.setMatrixAt( i, currentM );
 
 			}
-			instanceBuffer.needsUpdate = true;
+
+			mesh.instanceMatrix.needsUpdate = true;
+
 			lastTime = time;
 
-		}
+			renderer.render( scene, camera );
 
-		init();
-		animate();
+		}
 
 	</script>
 
 </body>
 
+
+
 </html>