浏览代码

Merge pull request #18033 from donmccurdy/examples-buffergeometry-instancedmesh

Examples: Update or remove some InstancedBufferGeometry examples
Mr.doob 5 年之前
父节点
当前提交
14dcd30cb4

+ 1 - 3
examples/files.js

@@ -278,10 +278,8 @@ var files = {
 		"webgl_buffergeometry_drawrange",
 		"webgl_buffergeometry_indexed",
 		"webgl_buffergeometry_instancing",
-		"webgl_buffergeometry_instancing2",
 		"webgl_buffergeometry_instancing_billboards",
-		"webgl_buffergeometry_instancing_dynamic",
-		"webgl_buffergeometry_instancing_interleaved_dynamic",
+		"webgl_buffergeometry_instancing_interleaved",
 		"webgl_buffergeometry_instancing_lambert",
 		"webgl_buffergeometry_lines",
 		"webgl_buffergeometry_lines_indexed",

+ 0 - 232
examples/webgl_buffergeometry_instancing2.html

@@ -1,232 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-	<title>three.js webgl - instancing test (meshes)</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">
-	<style>
-		a {
-			color: #08f;
-		}
-		#notSupported {
-			width: 50%;
-			margin: auto;
-			background-color: #f00;
-			margin-top: 20px;
-			padding: 10px;
-		}
-	</style>
-</head>
-<body>
-
-	<div id="container"></div>
-	<div id="info">
-		<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - instancing test (meshes)
-		<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;
-
-		attribute vec3 instancePosition;
-		attribute vec4 instanceQuaternion;
-		attribute vec3 instanceScale;
-
-		varying vec3 vColor;
-
-		vec3 applyTRS( vec3 position, vec3 translation, vec4 quaternion, vec3 scale ) {
-
-			position *= scale;
-			position += 2.0 * cross( quaternion.xyz, cross( quaternion.xyz, position ) + quaternion.w * position );
-			return position + translation;
-
-		}
-
-		void main(){
-
-			vColor = color;
-
-			vec3 transformed = applyTRS( position.xyz, instancePosition, instanceQuaternion, instanceScale );
-
-			gl_Position = projectionMatrix * modelViewMatrix * vec4( transformed, 1.0 );
-
-		}
-
-	</script>
-
-	<script id="fragmentShader" type="x-shader/x-fragment">
-
-		precision highp float;
-		varying vec3 vColor;
-
-		void main() {
-
-			gl_FragColor = vec4( vColor, 1.0 );
-
-		}
-
-	</script>
-
-	<script type="module">
-		import * as THREE from '../build/three.module.js';
-
-		import Stats from './jsm/libs/stats.module.js';
-
-		import { TrackballControls } from './jsm/controls/TrackballControls.js';
-
-		var container, stats;
-
-		var camera, scene, renderer;
-
-		var controls;
-
-		init();
-		animate();
-
-		function init() {
-
-			container = document.getElementById( 'container' );
-
-			camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.01, 100 );
-			camera.position.z = 4;
-
-			scene = new THREE.Scene();
-
-			//
-
-			var geometry = new THREE.IcosahedronBufferGeometry( 0.1, 1 );
-
-			var colors = [];
-
-			for ( var i = 0, l = geometry.attributes.position.count; i < l; i ++ ) {
-
-				colors.push( Math.random(), Math.random(), Math.random() );
-
-			}
-
-			geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
-
-			var material = new THREE.MeshBasicMaterial( { color: 0xff0000, vertexColors: THREE.VertexColors } );
-
-			//
-
-			var instances = 100;
-
-			var instancePositions = [];
-			var instanceQuaternions = [];
-			var instanceScales = [];
-
-			// we create for each mesh a counterpart in our instanced geometry data
-
-			for ( var i = 0; i < instances; i ++ ) {
-
-				// the red meshes are drawn with separate draw calls
-
-				var mesh = new THREE.Mesh( geometry, material );
-				scene.add( mesh );
-
-				var position = mesh.position;
-				var quaternion = mesh.quaternion;
-				var scale = mesh.scale;
-
-				position.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
-
-				quaternion.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
-				quaternion.normalize();
-
-				scale.set( Math.random() * 2, Math.random() * 2, Math.random() * 2 );
-
-				// instanced attribute data
-
-				instancePositions.push( position.x, position.y, position.z );
-				instanceQuaternions.push( quaternion.x, quaternion.y, quaternion.z, quaternion.w );
-				instanceScales.push( scale.x, scale.y, scale.z );
-
-			}
-
-			var instancedGeometry = new THREE.InstancedBufferGeometry();
-			instancedGeometry.attributes.position = geometry.attributes.position;
-			instancedGeometry.attributes.color = geometry.attributes.color;
-
-			instancedGeometry.setAttribute( 'instancePosition', new THREE.InstancedBufferAttribute( new Float32Array( instancePositions ), 3 ) );
-			instancedGeometry.setAttribute( 'instanceQuaternion', new THREE.InstancedBufferAttribute( new Float32Array( instanceQuaternions ), 4 ) );
-			instancedGeometry.setAttribute( 'instanceScale', new THREE.InstancedBufferAttribute( new Float32Array( instanceScales ), 3 ) );
-
-			//
-
-			var shaderMaterial = new THREE.ShaderMaterial( {
-
-				uniforms: {},
-				vertexShader: document.getElementById( 'vertexShader' ).textContent,
-				fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
-				vertexColors: true
-
-			} );
-
-			// counterparts are drawn all at once with a single draw call (via instanced rendering)
-
-			var instancedMesh = new THREE.Mesh( instancedGeometry, shaderMaterial );
-			instancedMesh.position.x = 0.1;
-			scene.add( instancedMesh );
-
-			//
-
-			renderer = new THREE.WebGLRenderer();
-			renderer.setPixelRatio( window.devicePixelRatio );
-			renderer.setSize( window.innerWidth, window.innerHeight );
-			container.appendChild( renderer.domElement );
-
-			controls = new TrackballControls( camera, renderer.domElement );
-
-			if ( renderer.extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
-
-				document.getElementById( 'notSupported' ).style.display = '';
-				return;
-
-			}
-
-			//
-
-			stats = new Stats();
-			container.appendChild( stats.dom );
-
-			//
-
-			window.addEventListener( 'resize', onWindowResize, false );
-
-		}
-
-		function onWindowResize() {
-
-			camera.aspect = window.innerWidth / window.innerHeight;
-			camera.updateProjectionMatrix();
-
-			renderer.setSize( window.innerWidth, window.innerHeight );
-
-		}
-
-		//
-
-		function animate() {
-
-			requestAnimationFrame( animate );
-
-			render();
-			stats.update();
-
-		}
-
-		function render() {
-
-			controls.update();
-
-			renderer.render( scene, camera );
-
-		}
-
-	</script>
-
-</body>
-
-</html>

+ 0 - 240
examples/webgl_buffergeometry_instancing_dynamic.html

@@ -1,240 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-	<title>three.js webgl - indexed instancing (single box), dynamic updates</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">
-	<style>
-		a {
-			color: #08f;
-		}
-		#notSupported {
-			width: 50%;
-			margin: auto;
-			background-color: #f00;
-			margin-top: 20px;
-			padding: 10px;
-		}
-	</style>
-</head>
-<body>
-
-	<div id="container"></div>
-	<div id="info">
-		<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - indexed instancing (single box), dynamic updates
-		<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 lastTime = 0;
-
-		var moveQ = new THREE.Quaternion( 0.5, 0.5, 0.5, 0.0 ).normalize();
-		var tmpQ = new THREE.Quaternion();
-		var currentQ = new THREE.Quaternion();
-
-		init();
-		animate();
-
-		function init() {
-
-			container = document.getElementById( 'container' );
-
-			camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
-
-			scene = new THREE.Scene();
-			scene.background = new THREE.Color( 0x101010 );
-
-			// geometry
-
-			var instances = 5000;
-
-			var bufferGeometry = new THREE.BoxBufferGeometry( 2, 2, 2 );
-
-			// copying data from a simple box geometry, but you can specify a custom geometry if you want
-
-			var geometry = new THREE.InstancedBufferGeometry();
-			geometry.index = bufferGeometry.index;
-			geometry.attributes.position = bufferGeometry.attributes.position;
-			geometry.attributes.uv = bufferGeometry.attributes.uv;
-
-			// per instance data
-
-			var offsets = [];
-			var orientations = [];
-
-			var vector = new THREE.Vector4();
-			var x, y, z, w;
-
-			for ( var i = 0; i < instances; i ++ ) {
-
-				// offsets
-
-				x = Math.random() * 100 - 50;
-				y = Math.random() * 100 - 50;
-				z = Math.random() * 100 - 50;
-
-				vector.set( x, y, z, 0 ).normalize();
-				vector.multiplyScalar( 5 ); // move out at least 5 units from center in current direction
-
-				offsets.push( x + vector.x, y + vector.y, z + vector.z );
-
-				// orientations
-
-				x = Math.random() * 2 - 1;
-				y = Math.random() * 2 - 1;
-				z = Math.random() * 2 - 1;
-				w = Math.random() * 2 - 1;
-
-				vector.set( x, y, z, w ).normalize();
-
-				orientations.push( vector.x, vector.y, vector.z, vector.w );
-
-			}
-
-			offsetAttribute = new THREE.InstancedBufferAttribute( new Float32Array( offsets ), 3 );
-			orientationAttribute = new THREE.InstancedBufferAttribute( new Float32Array( orientations ), 4 ).setUsage( THREE.DynamicDrawUsage );
-
-			geometry.setAttribute( 'offset', offsetAttribute );
-			geometry.setAttribute( 'orientation', orientationAttribute );
-
-			// material
-
-			var material = new THREE.RawShaderMaterial( {
-
-				uniforms: {
-					map: { value: new THREE.TextureLoader().load( 'textures/crate.gif' ) }
-				},
-				vertexShader: document.getElementById( 'vertexShader' ).textContent,
-				fragmentShader: document.getElementById( 'fragmentShader' ).textContent
-
-			} );
-
-			mesh = new THREE.Mesh( geometry, material );
-			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 = '';
-				return;
-
-			}
-
-			stats = new Stats();
-			container.appendChild( stats.dom );
-
-			window.addEventListener( 'resize', onWindowResize, false );
-
-		}
-
-		function onWindowResize() {
-
-			camera.aspect = window.innerWidth / window.innerHeight;
-			camera.updateProjectionMatrix();
-
-			renderer.setSize( window.innerWidth, window.innerHeight );
-
-		}
-
-		//
-
-		function animate() {
-
-			requestAnimationFrame( animate );
-
-			render();
-			stats.update();
-
-		}
-
-		function render() {
-
-			var time = performance.now();
-
-			mesh.rotation.y = time * 0.00005;
-
-			var delta = ( time - lastTime ) / 5000;
-			tmpQ.set( moveQ.x * delta, moveQ.y * delta, moveQ.z * delta, 1 ).normalize();
-
-			for ( var i = 0, il = orientationAttribute.count; i < il; i ++ ) {
-
-				currentQ.fromArray( orientationAttribute.array, ( i * 4 ) );
-				currentQ.multiply( tmpQ );
-
-				orientationAttribute.setXYZW( i, currentQ.x, currentQ.y, currentQ.z, currentQ.w );
-
-			}
-
-			orientationAttribute.needsUpdate = true;
-			lastTime = time;
-
-			renderer.render( scene, camera );
-
-		}
-
-	</script>
-
-</body>
-
-
-
-</html>

+ 57 - 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,41 +202,31 @@
 
 		}
 
-		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>