Jelajahi Sumber

removed horses, use template strings, added page to examples

santi 5 tahun lalu
induk
melakukan
4326e85b28

+ 1 - 0
examples/files.js

@@ -298,6 +298,7 @@ var files = {
 		"webgl_custom_attributes_points3",
 		"webgl_custom_attributes_points3",
 		"webgl_fire",
 		"webgl_fire",
 		"webgl_gpgpu_birds",
 		"webgl_gpgpu_birds",
+		"webgl_gpgpu_birds_gltf",
 		"webgl_gpgpu_water",
 		"webgl_gpgpu_water",
 		"webgl_gpgpu_protoplanet",
 		"webgl_gpgpu_protoplanet",
 		"webgl_instancing_modified",
 		"webgl_instancing_modified",

+ 205 - 179
examples/webgl_gpgpu_birds.html

@@ -18,11 +18,16 @@
 	<body>
 	<body>
 
 
 		<div id="info">
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl gpgpu birds + GLTF mesh<br/>
-			Flamingo by <a href="http://mirada.com/">mirada</a> from <a href="http://ro.me">rome</a><br/>
-			Move mouse to disturb birds. 
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl gpgpu birds<br/>
+			Move mouse to disturb birds.
 		</div>
 		</div>
 
 
+		<!--
+		TODO: If you're reading this, you may wish to improve this example by
+			- Create a better shading for the birds?
+
+		-->
+
 		<!-- shader for bird's position -->
 		<!-- shader for bird's position -->
 		<script id="fragmentShaderPosition" type="x-shader/x-fragment">
 		<script id="fragmentShaderPosition" type="x-shader/x-fragment">
 
 
@@ -191,6 +196,8 @@
 
 
 				}
 				}
 
 
+
+
 				// this make tends to fly around than down or up
 				// this make tends to fly around than down or up
 				// if (velocity.y > 0.) velocity.y *= (1. - 0.2 * delta);
 				// if (velocity.y > 0.) velocity.y *= (1. - 0.2 * delta);
 
 
@@ -205,113 +212,191 @@
 
 
 		</script>
 		</script>
 
 
+		<script type="x-shader/x-vertex" id="birdVS">
+
+			attribute vec2 reference;
+			attribute float birdVertex;
+
+			attribute vec3 birdColor;
+
+			uniform sampler2D texturePosition;
+			uniform sampler2D textureVelocity;
+
+			varying vec4 vColor;
+			varying float z;
+
+			uniform float time;
+
+			void main() {
+
+				vec4 tmpPos = texture2D( texturePosition, reference );
+				vec3 pos = tmpPos.xyz;
+				vec3 velocity = normalize(texture2D( textureVelocity, reference ).xyz);
+
+				vec3 newPosition = position;
+
+				if ( birdVertex == 4.0 || birdVertex == 7.0 ) {
+					// flap wings
+					newPosition.y = sin( tmpPos.w ) * 5.;
+				}
+
+				newPosition = mat3( modelMatrix ) * newPosition;
+
+
+				velocity.z *= -1.;
+				float xz = length( velocity.xz );
+				float xyz = 1.;
+				float x = sqrt( 1. - velocity.y * velocity.y );
+
+				float cosry = velocity.x / xz;
+				float sinry = velocity.z / xz;
+
+				float cosrz = x / xyz;
+				float sinrz = velocity.y / xyz;
+
+				mat3 maty =  mat3(
+					cosry, 0, -sinry,
+					0    , 1, 0     ,
+					sinry, 0, cosry
+
+				);
+
+				mat3 matz =  mat3(
+					cosrz , sinrz, 0,
+					-sinrz, cosrz, 0,
+					0     , 0    , 1
+				);
+
+				newPosition =  maty * matz * newPosition;
+				newPosition += pos;
+
+				z = newPosition.z;
+
+				vColor = vec4( birdColor, 1.0 );
+				gl_Position = projectionMatrix *  viewMatrix  * vec4( newPosition, 1.0 );
+			}
+
+		</script>
+
+		<!-- bird geometry shader -->
+		<script type="x-shader/x-fragment" id="birdFS">
+
+			varying vec4 vColor;
+			varying float z;
+
+			uniform vec3 color;
+
+			void main() {
+				// Fake colors for now
+				float z2 = 0.2 + ( 1000. - z ) / 1000. * vColor.x;
+				gl_FragColor = vec4( z2, z2, z2, 1. );
+
+			}
+
+		</script>
+
 		<script type="module">
 		<script type="module">
 
 
 			import * as THREE from '../build/three.module.js';
 			import * as THREE from '../build/three.module.js';
+
 			import Stats from './jsm/libs/stats.module.js';
 			import Stats from './jsm/libs/stats.module.js';
 			import { GUI } from './jsm/libs/dat.gui.module.js';
 			import { GUI } from './jsm/libs/dat.gui.module.js';
-			import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
+
 			import { GPUComputationRenderer } from './jsm/misc/GPUComputationRenderer.js';
 			import { GPUComputationRenderer } from './jsm/misc/GPUComputationRenderer.js';
 
 
 			/* TEXTURE WIDTH FOR SIMULATION */
 			/* TEXTURE WIDTH FOR SIMULATION */
-			var WIDTH = 64
+			var WIDTH = 32;
+
 			var BIRDS = WIDTH * WIDTH;
 			var BIRDS = WIDTH * WIDTH;
-			
-			/* BAKE ANIMATION INTO TEXTURE and CREATE GEOMETRY FROM BASE MODEL */
-			var BirdGeometry = new THREE.BufferGeometry();
-			var textureAnimation, durationAnimation, originalMaterial,birdMesh, materialShader, vertexPerBird;
-			function nextPowerOf2( n ) { return Math.pow( 2, Math.ceil( Math.log( n ) / Math.log( 2 ) ) ) };
 
 
-			Math.lerp = function (value1, value2, amount) {
+			// Custom Geometry - using 3 triangles each. No UVs, no normals currently.
+			var BirdGeometry = function () {
 
 
-				amount = Math.max( Math.min( amount, 1 ), 0 );
-				return value1 + (value2 - value1) * amount;
-				
-			};
+				var triangles = BIRDS * 3;
+				var points = triangles * 3;
 
 
-			var geos = [ 'Parrot', 'Flamingo', 'Horse' ]
-			var colors = [ 0xccFFFF, 0xffdeff, 0xffdede ]
-			var selectModel = Math.floor( Math.random() * geos.length )
-			new GLTFLoader().load( 'models/gltf/' + geos[ selectModel ] + '.glb', function ( gltf ) {
+				THREE.BufferGeometry.call( this );
 
 
-				var animations = gltf.animations;
-				durationAnimation = Math.round( animations[ 0 ].duration * 60 );
-				var birdGeo = gltf.scene.children[ 0 ].geometry;
-				originalMaterial = gltf.scene.children[ 0 ].material;
-				var morphAttributes = birdGeo.morphAttributes.position;
-				var tHeight = nextPowerOf2( durationAnimation );
-				var tWidth = nextPowerOf2( birdGeo.getAttribute( 'position' ).count );
-				vertexPerBird = birdGeo.getAttribute( 'position' ).count;
-				var tData = new Float32Array( 3 * tWidth * tHeight );
+				var vertices = new THREE.BufferAttribute( new Float32Array( points * 3 ), 3 );
+				var birdColors = new THREE.BufferAttribute( new Float32Array( points * 3 ), 3 );
+				var references = new THREE.BufferAttribute( new Float32Array( points * 2 ), 2 );
+				var birdVertex = new THREE.BufferAttribute( new Float32Array( points ), 1 );
 
 
-				for( var i = 0 ; i < tWidth ; i++ ){
+				this.setAttribute( 'position', vertices );
+				this.setAttribute( 'birdColor', birdColors );
+				this.setAttribute( 'reference', references );
+				this.setAttribute( 'birdVertex', birdVertex );
 
 
-					for( var j = 0 ; j < tHeight ; j++ ){
+				// this.setAttribute( 'normal', new Float32Array( points * 3 ), 3 );
 
 
-						var offset = j * tWidth * 3;
 
 
-						var curFrame = j;
-						var curMorph = Math.floor( j / durationAnimation * morphAttributes.length );
-						var nextMorph = ( Math.floor( j / durationAnimation * morphAttributes.length ) + 1 ) % morphAttributes.length;
-						var lerpAmount = j / durationAnimation * morphAttributes.length % 1;
+				var v = 0;
 
 
-						if( j < durationAnimation ){
+				function verts_push() {
+
+					for ( var i = 0; i < arguments.length; i ++ ) {
+
+						vertices.array[ v ++ ] = arguments[ i ];
 
 
-							tData[ offset + i * 3 ] = Math.lerp( morphAttributes[ curMorph ].array[ i * 3 ], morphAttributes[ nextMorph ].array[ i * 3 ], lerpAmount );
-							tData[ offset + i * 3 + 1 ] = Math.lerp( morphAttributes[ curMorph ].array[ i * 3 + 1 ], morphAttributes[ nextMorph ].array[ i * 3 + 1 ], lerpAmount );
-							tData[ offset + i * 3 + 2 ] = Math.lerp( morphAttributes[ curMorph ].array[ i * 3 + 2 ], morphAttributes[ nextMorph ].array[ i * 3 + 2 ], lerpAmount );
-						
-						}
 					}
 					}
 
 
 				}
 				}
-				
-				textureAnimation = new THREE.DataTexture( tData, tWidth, tHeight, THREE.RGBFormat, THREE.FloatType );
-				textureAnimation.needsUpdate = true;
 
 
-				var vertices = [], color = [], reference = [], seeds = [], indices = [];
-				var totalVertices = birdGeo.getAttribute( 'position' ).count * 3 * BIRDS;
-				for( var i = 0 ; i < totalVertices ; i++ ){
+				var wingsSpan = 20;
 
 
-					var bIndex = i % ( birdGeo.getAttribute( 'position' ).count * 3 );
-					vertices.push( birdGeo.getAttribute( 'position' ).array[ bIndex ] );
-					color.push( birdGeo.getAttribute( 'color' ).array[ bIndex ] );
+				for ( var f = 0; f < BIRDS; f ++ ) {
 
 
-				}
+					// Body
+					verts_push(
+						0, - 0, - 20,
+						0, 4, - 20,
+						0, 0, 30
+					);
 
 
-				var r = Math.random();
-				for( var i = 0 ; i < birdGeo.getAttribute( 'position' ).count * BIRDS ; i++ ){
-					
-					var bIndex = i % ( birdGeo.getAttribute( 'position' ).count );
-					var bird = Math.floor( i / birdGeo.getAttribute( 'position' ).count );
-					if( bIndex == 0 ) r = Math.random();
-					var j = ~ ~ bird;
-					var x = ( j % WIDTH ) / WIDTH;
-					var y = ~ ~ ( j / WIDTH ) / WIDTH;
-					reference.push( x, y, bIndex / tWidth, durationAnimation / tHeight );
-					seeds.push( bird, r, Math.random(), Math.random() );
+					// Left Wing
+					verts_push(
+						0, 0, - 15,
+						- wingsSpan, 0, 0,
+						0, 0, 15
+					);
+
+					// Right Wing
+					verts_push(
+						0, 0, 15,
+						wingsSpan, 0, 0,
+						0, 0, - 15
+					);
 
 
 				}
 				}
 
 
-				for( var i = 0 ; i < birdGeo.index.array.length * BIRDS ; i++ ){
+				for ( var v = 0; v < triangles * 3; v ++ ) {
+
+					var i = ~ ~ ( v / 3 );
+					var x = ( i % WIDTH ) / WIDTH;
+					var y = ~ ~ ( i / WIDTH ) / WIDTH;
+
+					var c = new THREE.Color(
+						0x444444 +
+						~ ~ ( v / 9 ) / BIRDS * 0x666666
+					);
+
+					birdColors.array[ v * 3 + 0 ] = c.r;
+					birdColors.array[ v * 3 + 1 ] = c.g;
+					birdColors.array[ v * 3 + 2 ] = c.b;
+
+					references.array[ v * 2 ] = x;
+					references.array[ v * 2 + 1 ] = y;
 
 
-					var offset = Math.floor( i / birdGeo.index.array.length ) * ( birdGeo.getAttribute( 'position' ).count );				
-					indices.push( birdGeo.index.array[ i % birdGeo.index.array.length ] + offset );
+					birdVertex.array[ v ] = v % 9;
 
 
 				}
 				}
 
 
-				BirdGeometry.setAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
-				BirdGeometry.setAttribute( 'birdColor', new THREE.BufferAttribute( new Float32Array( color ), 3 ) );
-				BirdGeometry.setAttribute( 'color', new THREE.BufferAttribute( new Float32Array( color ), 3 ) );
-				BirdGeometry.setAttribute( 'reference', new THREE.BufferAttribute( new Float32Array( reference ), 4 ) );
-				BirdGeometry.setAttribute( 'seeds', new THREE.BufferAttribute( new Float32Array( seeds ), 4 ) );
+				this.scale( 0.2, 0.2, 0.2 );
 
 
-				BirdGeometry.setIndex( indices );
+			};
 
 
-				init();
-				animate();
+			BirdGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
 
 
-			} );
 
 
 			var container, stats;
 			var container, stats;
 			var camera, scene, renderer;
 			var camera, scene, renderer;
@@ -331,6 +416,9 @@
 			var velocityUniforms;
 			var velocityUniforms;
 			var birdUniforms;
 			var birdUniforms;
 
 
+			init();
+			animate();
+
 			function init() {
 			function init() {
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
@@ -340,24 +428,10 @@
 				camera.position.z = 350;
 				camera.position.z = 350;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
-				scene.background = new THREE.Color( colors[ selectModel ] );
-				scene.fog = new THREE.Fog( colors[ selectModel ], 100, 1000 );
-
-				// LIGHTS
-
-				var hemiLight = new THREE.HemisphereLight( colors[ selectModel ], 0xffffff, 1.6 );
-				hemiLight.color.setHSL( 0.6, 1, 0.6 );
-				hemiLight.groundColor.setHSL( 0.095, 1, 0.75 );
-				hemiLight.position.set( 0, 50, 0 );
-				scene.add( hemiLight );
+				scene.background = new THREE.Color( 0xffffff );
+				scene.fog = new THREE.Fog( 0xffffff, 100, 1000 );
 
 
-				var dirLight = new THREE.DirectionalLight( 0x00CED1, 0.6 );
-				dirLight.color.setHSL( 0.1, 1, 0.95 );
-				dirLight.position.set( - 1, 1.75, 1 );
-				dirLight.position.multiplyScalar( 30 );
-				scene.add( dirLight );
-
-				renderer = new THREE.WebGLRenderer( { antialias : true, alpha : true } );
+				renderer = new THREE.WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
@@ -371,19 +445,18 @@
 				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
 				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
 				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
 				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
 
 
+				//
+
 				window.addEventListener( 'resize', onWindowResize, false );
 				window.addEventListener( 'resize', onWindowResize, false );
 
 
 				var gui = new GUI();
 				var gui = new GUI();
 
 
-				var effectController = {
 
 
+				var effectController = {
 					separation: 20.0,
 					separation: 20.0,
 					alignment: 20.0,
 					alignment: 20.0,
 					cohesion: 20.0,
 					cohesion: 20.0,
-					freedom: 0.75,
-					size: 0.1,
-					count: BIRDS
-
+					freedom: 0.75
 				};
 				};
 
 
 				var valuesChanger = function () {
 				var valuesChanger = function () {
@@ -392,8 +465,6 @@
 					velocityUniforms[ "alignmentDistance" ].value = effectController.alignment;
 					velocityUniforms[ "alignmentDistance" ].value = effectController.alignment;
 					velocityUniforms[ "cohesionDistance" ].value = effectController.cohesion;
 					velocityUniforms[ "cohesionDistance" ].value = effectController.cohesion;
 					velocityUniforms[ "freedomFactor" ].value = effectController.freedom;
 					velocityUniforms[ "freedomFactor" ].value = effectController.freedom;
-					if( materialShader ) materialShader.uniforms[ "size" ].value = effectController.size;
-					BirdGeometry.setDrawRange ( 0, vertexPerBird * effectController.count )
 
 
 				};
 				};
 
 
@@ -402,8 +473,6 @@
 				gui.add( effectController, "separation", 0.0, 100.0, 1.0 ).onChange( valuesChanger );
 				gui.add( effectController, "separation", 0.0, 100.0, 1.0 ).onChange( valuesChanger );
 				gui.add( effectController, "alignment", 0.0, 100, 0.001 ).onChange( valuesChanger );
 				gui.add( effectController, "alignment", 0.0, 100, 0.001 ).onChange( valuesChanger );
 				gui.add( effectController, "cohesion", 0.0, 100, 0.025 ).onChange( valuesChanger );
 				gui.add( effectController, "cohesion", 0.0, 100, 0.025 ).onChange( valuesChanger );
-				gui.add( effectController, "size", 0, 1, 0.01 ).onChange( valuesChanger );
-				gui.add( effectController, "count", 0, BIRDS, 1 ).onChange( valuesChanger );
 				gui.close();
 				gui.close();
 
 
 				initBirds();
 				initBirds();
@@ -444,86 +513,42 @@
 				velocityVariable.wrapT = THREE.RepeatWrapping;
 				velocityVariable.wrapT = THREE.RepeatWrapping;
 				positionVariable.wrapS = THREE.RepeatWrapping;
 				positionVariable.wrapS = THREE.RepeatWrapping;
 				positionVariable.wrapT = THREE.RepeatWrapping;
 				positionVariable.wrapT = THREE.RepeatWrapping;
-				
+
 				var error = gpuCompute.init();
 				var error = gpuCompute.init();
 				if ( error !== null ) {
 				if ( error !== null ) {
+
 				    console.error( error );
 				    console.error( error );
+
 				}
 				}
+
 			}
 			}
 
 
 			function initBirds() {
 			function initBirds() {
 
 
-				var geometry = BirdGeometry;
-
-				var m = new THREE.MeshStandardMaterial({
-					vertexColors : true,
-					flatShading : true,
-					roughness : 1,
-					metalness : 0
-				})
-
-				m.onBeforeCompile = ( shader ) => {
-
-					shader.uniforms.texturePosition = { value : null };
-					shader.uniforms.textureVelocity = { value : null };
-					shader.uniforms.textureAnimation = { value : textureAnimation };
-					shader.uniforms.time = { value : 1.0 };
-					shader.uniforms.size = { value : 0.1 };
-					shader.uniforms.delta = { value : 0.0 };
-
-					var token = '#define STANDARD';
-        			var insert = 'attribute vec4 reference;';
-					insert += 'attribute vec4 seeds;';
-					insert += 'attribute vec3 birdColor;';
-					insert += 'uniform sampler2D texturePosition;';
-					insert += 'uniform sampler2D textureVelocity;';
-					insert += 'uniform sampler2D textureAnimation;';
-					insert += 'uniform float size;';
-					insert += 'uniform float time;';
-
-					shader.vertexShader = shader.vertexShader.replace( token, token + '\n' + insert );
-
-					var token = '#include <begin_vertex>';
-					var insert = 'vec4 tmpPos = texture2D( texturePosition, reference.xy );';
-				
-					insert += 'vec3 pos = tmpPos.xyz;';
-					insert += 'vec3 velocity = normalize(texture2D( textureVelocity, reference.xy ).xyz);';
-					insert += 'vec3 aniPos = texture2D( textureAnimation, vec2( reference.z, mod( ( time + seeds.x ) * ( ( 0.0004 + seeds.y / 10000.0) + normalize( velocity ) / 20000.0 ), reference.w ) ) ).xyz;';
-					insert += 'vec3 newPosition = position;';
-					
-					insert += 'newPosition = mat3( modelMatrix ) * ( newPosition + aniPos );';
-					insert += 'newPosition *= size + seeds.y * size * 0.2;';
-					
-					insert += 'velocity.z *= -1.;';
-					insert += 'float xz = length( velocity.xz );';
-					insert += 'float xyz = 1.;';
-					insert += 'float x = sqrt( 1. - velocity.y * velocity.y );';
-
-					insert += 'float cosry = velocity.x / xz;';
-					insert += 'float sinry = velocity.z / xz;';
-
-					insert += 'float cosrz = x / xyz;';
-					insert += 'float sinrz = velocity.y / xyz;';
-
-					insert += 'mat3 maty =  mat3( cosry, 0, -sinry, 0    , 1, 0     , sinry, 0, cosry );';
-					insert += 'mat3 matz =  mat3( cosrz , sinrz, 0, -sinrz, cosrz, 0, 0     , 0    , 1 );';
-
-					insert += 'newPosition =  maty * matz * newPosition;';
-					insert += 'newPosition += pos;';
-					
-					insert += 'vec3 transformed = vec3( newPosition );';
-					
-        			shader.vertexShader = shader.vertexShader.replace( token, insert );
-
-					materialShader = shader;
-
-				}    
-
-				birdMesh = new THREE.Mesh( geometry, m );
+				var geometry = new BirdGeometry();
+
+				// For Vertex and Fragment
+				birdUniforms = {
+					"color": { value: new THREE.Color( 0xff2200 ) },
+					"texturePosition": { value: null },
+					"textureVelocity": { value: null },
+					"time": { value: 1.0 },
+					"delta": { value: 0.0 }
+				};
+
+				// THREE.ShaderMaterial
+				var material = new THREE.ShaderMaterial( {
+					uniforms: birdUniforms,
+					vertexShader: document.getElementById( 'birdVS' ).textContent,
+					fragmentShader: document.getElementById( 'birdFS' ).textContent,
+					side: THREE.DoubleSide
+
+				} );
+
+				var birdMesh = new THREE.Mesh( geometry, material );
 				birdMesh.rotation.y = Math.PI / 2;
 				birdMesh.rotation.y = Math.PI / 2;
-				
-				birdMesh.castShadow = true;
-				birdMesh.receiveShadow = true;
+				birdMesh.matrixAutoUpdate = false;
+				birdMesh.updateMatrix();
 
 
 				scene.add( birdMesh );
 				scene.add( birdMesh );
 
 
@@ -628,7 +653,7 @@
 
 
 				var now = performance.now();
 				var now = performance.now();
 				var delta = ( now - last ) / 1000;
 				var delta = ( now - last ) / 1000;
-				
+
 				if ( delta > 1 ) delta = 1; // safety cap on large deltas
 				if ( delta > 1 ) delta = 1; // safety cap on large deltas
 				last = now;
 				last = now;
 
 
@@ -636,8 +661,8 @@
 				positionUniforms[ "delta" ].value = delta;
 				positionUniforms[ "delta" ].value = delta;
 				velocityUniforms[ "time" ].value = now;
 				velocityUniforms[ "time" ].value = now;
 				velocityUniforms[ "delta" ].value = delta;
 				velocityUniforms[ "delta" ].value = delta;
-				if( materialShader ) materialShader.uniforms[ "time" ].value = now;
-				if( materialShader ) materialShader.uniforms[ "delta" ].value = delta;
+				birdUniforms[ "time" ].value = now;
+				birdUniforms[ "delta" ].value = delta;
 
 
 				velocityUniforms[ "predator" ].value.set( 0.5 * mouseX / windowHalfX, - 0.5 * mouseY / windowHalfY, 0 );
 				velocityUniforms[ "predator" ].value.set( 0.5 * mouseX / windowHalfX, - 0.5 * mouseY / windowHalfY, 0 );
 
 
@@ -645,13 +670,14 @@
 				mouseY = 10000;
 				mouseY = 10000;
 
 
 				gpuCompute.compute();
 				gpuCompute.compute();
-				
-				if( materialShader ) materialShader.uniforms[ "texturePosition" ].value = gpuCompute.getCurrentRenderTarget( positionVariable ).texture;
-				if( materialShader ) materialShader.uniforms[ "textureVelocity" ].value = gpuCompute.getCurrentRenderTarget( velocityVariable ).texture;
-				
+
+				birdUniforms[ "texturePosition" ].value = gpuCompute.getCurrentRenderTarget( positionVariable ).texture;
+				birdUniforms[ "textureVelocity" ].value = gpuCompute.getCurrentRenderTarget( velocityVariable ).texture;
+
 				renderer.render( scene, camera );
 				renderer.render( scene, camera );
+
 			}
 			}
 
 
 		</script>
 		</script>
 	</body>
 	</body>
-</html>
+</html>

+ 664 - 0
examples/webgl_gpgpu_birds_gltf.html

@@ -0,0 +1,664 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - gpgpu - flocking</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>
+			body {
+				background-color: #fff;
+				color: #444;
+			}
+			a {
+				color:#08f;
+			}
+		</style>
+	</head>
+	<body>
+
+		<div id="info">
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl gpgpu birds + GLTF mesh<br/>
+			Flamingo by <a href="http://mirada.com/">mirada</a> from <a href="http://ro.me">rome</a><br/>
+			Move mouse to disturb birds. 
+		</div>
+
+		<!-- shader for bird's position -->
+		<script id="fragmentShaderPosition" type="x-shader/x-fragment">
+
+			uniform float time;
+			uniform float delta;
+
+			void main()	{
+
+				vec2 uv = gl_FragCoord.xy / resolution.xy;
+				vec4 tmpPos = texture2D( texturePosition, uv );
+				vec3 position = tmpPos.xyz;
+				vec3 velocity = texture2D( textureVelocity, uv ).xyz;
+
+				float phase = tmpPos.w;
+
+				phase = mod( ( phase + delta +
+					length( velocity.xz ) * delta * 3. +
+					max( velocity.y, 0.0 ) * delta * 6. ), 62.83 );
+
+				gl_FragColor = vec4( position + velocity * delta * 15. , phase );
+
+			}
+
+		</script>
+
+		<!-- shader for bird's velocity -->
+		<script id="fragmentShaderVelocity" type="x-shader/x-fragment">
+
+			uniform float time;
+			uniform float testing;
+			uniform float delta; // about 0.016
+			uniform float separationDistance; // 20
+			uniform float alignmentDistance; // 40
+			uniform float cohesionDistance; //
+			uniform float freedomFactor;
+			uniform vec3 predator;
+
+			const float width = resolution.x;
+			const float height = resolution.y;
+
+			const float PI = 3.141592653589793;
+			const float PI_2 = PI * 2.0;
+			// const float VISION = PI * 0.55;
+
+			float zoneRadius = 40.0;
+			float zoneRadiusSquared = 1600.0;
+
+			float separationThresh = 0.45;
+			float alignmentThresh = 0.65;
+
+			const float UPPER_BOUNDS = BOUNDS;
+			const float LOWER_BOUNDS = -UPPER_BOUNDS;
+
+			const float SPEED_LIMIT = 9.0;
+
+			float rand( vec2 co ){
+				return fract( sin( dot( co.xy, vec2(12.9898,78.233) ) ) * 43758.5453 );
+			}
+
+			void main() {
+
+				zoneRadius = separationDistance + alignmentDistance + cohesionDistance;
+				separationThresh = separationDistance / zoneRadius;
+				alignmentThresh = ( separationDistance + alignmentDistance ) / zoneRadius;
+				zoneRadiusSquared = zoneRadius * zoneRadius;
+
+
+				vec2 uv = gl_FragCoord.xy / resolution.xy;
+				vec3 birdPosition, birdVelocity;
+
+				vec3 selfPosition = texture2D( texturePosition, uv ).xyz;
+				vec3 selfVelocity = texture2D( textureVelocity, uv ).xyz;
+
+				float dist;
+				vec3 dir; // direction
+				float distSquared;
+
+				float separationSquared = separationDistance * separationDistance;
+				float cohesionSquared = cohesionDistance * cohesionDistance;
+
+				float f;
+				float percent;
+
+				vec3 velocity = selfVelocity;
+
+				float limit = SPEED_LIMIT;
+
+				dir = predator * UPPER_BOUNDS - selfPosition;
+				dir.z = 0.;
+				// dir.z *= 0.6;
+				dist = length( dir );
+				distSquared = dist * dist;
+
+				float preyRadius = 150.0;
+				float preyRadiusSq = preyRadius * preyRadius;
+
+
+				// move birds away from predator
+				if ( dist < preyRadius ) {
+
+					f = ( distSquared / preyRadiusSq - 1.0 ) * delta * 100.;
+					velocity += normalize( dir ) * f;
+					limit += 5.0;
+				}
+
+
+				// if (testing == 0.0) {}
+				// if ( rand( uv + time ) < freedomFactor ) {}
+
+
+				// Attract flocks to the center
+				vec3 central = vec3( 0., 0., 0. );
+				dir = selfPosition - central;
+				dist = length( dir );
+
+				dir.y *= 2.5;
+				velocity -= normalize( dir ) * delta * 5.;
+
+				for ( float y = 0.0; y < height; y++ ) {
+					for ( float x = 0.0; x < width; x++ ) {
+
+						vec2 ref = vec2( x + 0.5, y + 0.5 ) / resolution.xy;
+						birdPosition = texture2D( texturePosition, ref ).xyz;
+
+						dir = birdPosition - selfPosition;
+						dist = length( dir );
+
+						if ( dist < 0.0001 ) continue;
+
+						distSquared = dist * dist;
+
+						if ( distSquared > zoneRadiusSquared ) continue;
+
+						percent = distSquared / zoneRadiusSquared;
+
+						if ( percent < separationThresh ) { // low
+
+							// Separation - Move apart for comfort
+							f = ( separationThresh / percent - 1.0 ) * delta;
+							velocity -= normalize( dir ) * f;
+
+						} else if ( percent < alignmentThresh ) { // high
+
+							// Alignment - fly the same direction
+							float threshDelta = alignmentThresh - separationThresh;
+							float adjustedPercent = ( percent - separationThresh ) / threshDelta;
+
+							birdVelocity = texture2D( textureVelocity, ref ).xyz;
+
+							f = ( 0.5 - cos( adjustedPercent * PI_2 ) * 0.5 + 0.5 ) * delta;
+							velocity += normalize( birdVelocity ) * f;
+
+						} else {
+
+							// Attraction / Cohesion - move closer
+							float threshDelta = 1.0 - alignmentThresh;
+							float adjustedPercent = ( percent - alignmentThresh ) / threshDelta;
+
+							f = ( 0.5 - ( cos( adjustedPercent * PI_2 ) * -0.5 + 0.5 ) ) * delta;
+
+							velocity += normalize( dir ) * f;
+
+						}
+
+					}
+
+				}
+
+				// this make tends to fly around than down or up
+				// if (velocity.y > 0.) velocity.y *= (1. - 0.2 * delta);
+
+				// Speed Limits
+				if ( length( velocity ) > limit ) {
+					velocity = normalize( velocity ) * limit;
+				}
+
+				gl_FragColor = vec4( velocity, 1.0 );
+
+			}
+
+		</script>
+
+		<script type="module">
+
+			import * as THREE from '../build/three.module.js';
+			import Stats from './jsm/libs/stats.module.js';
+			import { GUI } from './jsm/libs/dat.gui.module.js';
+			import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
+			import { GPUComputationRenderer } from './jsm/misc/GPUComputationRenderer.js';
+
+			/* TEXTURE WIDTH FOR SIMULATION */
+			var WIDTH = 64
+			var BIRDS = WIDTH * WIDTH;
+			
+			/* BAKE ANIMATION INTO TEXTURE and CREATE GEOMETRY FROM BASE MODEL */
+			var BirdGeometry = new THREE.BufferGeometry();
+			var textureAnimation, durationAnimation, originalMaterial,birdMesh, materialShader, vertexPerBird;
+			function nextPowerOf2( n ) { return Math.pow( 2, Math.ceil( Math.log( n ) / Math.log( 2 ) ) ) };
+
+			Math.lerp = function (value1, value2, amount) {
+
+				amount = Math.max( Math.min( amount, 1 ), 0 );
+				return value1 + (value2 - value1) * amount;
+				
+			};
+
+			var gltfs = [ 'models/gltf/Parrot.glb', 'models/gltf/Flamingo.glb' ]
+            var colors = [ 0xccFFFF, 0xffdeff ]
+            var sizes = [ 0.2, 0.1 ]
+			var selectModel = Math.floor( Math.random() * gltfs.length )
+			new GLTFLoader().load( gltfs[ selectModel ], function ( gltf ) {
+
+				var animations = gltf.animations;
+				durationAnimation = Math.round( animations[ 0 ].duration * 60 );
+				var birdGeo = gltf.scene.children[ 0 ].geometry;
+				originalMaterial = gltf.scene.children[ 0 ].material;
+				var morphAttributes = birdGeo.morphAttributes.position;
+				var tHeight = nextPowerOf2( durationAnimation );
+				var tWidth = nextPowerOf2( birdGeo.getAttribute( 'position' ).count );
+				vertexPerBird = birdGeo.getAttribute( 'position' ).count;
+				var tData = new Float32Array( 3 * tWidth * tHeight );
+
+				for( var i = 0 ; i < tWidth ; i++ ){
+
+					for( var j = 0 ; j < tHeight ; j++ ){
+
+						var offset = j * tWidth * 3;
+
+						var curFrame = j;
+						var curMorph = Math.floor( j / durationAnimation * morphAttributes.length );
+						var nextMorph = ( Math.floor( j / durationAnimation * morphAttributes.length ) + 1 ) % morphAttributes.length;
+						var lerpAmount = j / durationAnimation * morphAttributes.length % 1;
+
+						if( j < durationAnimation ){
+
+							tData[ offset + i * 3 ] = Math.lerp( morphAttributes[ curMorph ].array[ i * 3 ], morphAttributes[ nextMorph ].array[ i * 3 ], lerpAmount );
+							tData[ offset + i * 3 + 1 ] = Math.lerp( morphAttributes[ curMorph ].array[ i * 3 + 1 ], morphAttributes[ nextMorph ].array[ i * 3 + 1 ], lerpAmount );
+							tData[ offset + i * 3 + 2 ] = Math.lerp( morphAttributes[ curMorph ].array[ i * 3 + 2 ], morphAttributes[ nextMorph ].array[ i * 3 + 2 ], lerpAmount );
+						
+						}
+					}
+
+				}
+				
+				textureAnimation = new THREE.DataTexture( tData, tWidth, tHeight, THREE.RGBFormat, THREE.FloatType );
+				textureAnimation.needsUpdate = true;
+
+				var vertices = [], color = [], reference = [], seeds = [], indices = [];
+				var totalVertices = birdGeo.getAttribute( 'position' ).count * 3 * BIRDS;
+				for( var i = 0 ; i < totalVertices ; i++ ){
+
+					var bIndex = i % ( birdGeo.getAttribute( 'position' ).count * 3 );
+					vertices.push( birdGeo.getAttribute( 'position' ).array[ bIndex ] );
+					color.push( birdGeo.getAttribute( 'color' ).array[ bIndex ] );
+
+				}
+
+				var r = Math.random();
+				for( var i = 0 ; i < birdGeo.getAttribute( 'position' ).count * BIRDS ; i++ ){
+					
+					var bIndex = i % ( birdGeo.getAttribute( 'position' ).count );
+					var bird = Math.floor( i / birdGeo.getAttribute( 'position' ).count );
+					if( bIndex == 0 ) r = Math.random();
+					var j = ~ ~ bird;
+					var x = ( j % WIDTH ) / WIDTH;
+					var y = ~ ~ ( j / WIDTH ) / WIDTH;
+					reference.push( x, y, bIndex / tWidth, durationAnimation / tHeight );
+					seeds.push( bird, r, Math.random(), Math.random() );
+
+				}
+
+				for( var i = 0 ; i < birdGeo.index.array.length * BIRDS ; i++ ){
+
+					var offset = Math.floor( i / birdGeo.index.array.length ) * ( birdGeo.getAttribute( 'position' ).count );				
+					indices.push( birdGeo.index.array[ i % birdGeo.index.array.length ] + offset );
+
+				}
+
+				BirdGeometry.setAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
+				BirdGeometry.setAttribute( 'birdColor', new THREE.BufferAttribute( new Float32Array( color ), 3 ) );
+				BirdGeometry.setAttribute( 'color', new THREE.BufferAttribute( new Float32Array( color ), 3 ) );
+				BirdGeometry.setAttribute( 'reference', new THREE.BufferAttribute( new Float32Array( reference ), 4 ) );
+				BirdGeometry.setAttribute( 'seeds', new THREE.BufferAttribute( new Float32Array( seeds ), 4 ) );
+
+				BirdGeometry.setIndex( indices );
+
+				init();
+				animate();
+
+			} );
+
+			var container, stats;
+			var camera, scene, renderer;
+			var mouseX = 0, mouseY = 0;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+
+			var BOUNDS = 800, BOUNDS_HALF = BOUNDS / 2;
+
+			var last = performance.now();
+
+			var gpuCompute;
+			var velocityVariable;
+			var positionVariable;
+			var positionUniforms;
+			var velocityUniforms;
+			var birdUniforms;
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 3000 );
+				camera.position.z = 350;
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( colors[ selectModel ] );
+				scene.fog = new THREE.Fog( colors[ selectModel ], 100, 1000 );
+
+				// LIGHTS
+
+				var hemiLight = new THREE.HemisphereLight( colors[ selectModel ], 0xffffff, 1.6 );
+				hemiLight.color.setHSL( 0.6, 1, 0.6 );
+				hemiLight.groundColor.setHSL( 0.095, 1, 0.75 );
+				hemiLight.position.set( 0, 50, 0 );
+				scene.add( hemiLight );
+
+				var dirLight = new THREE.DirectionalLight( 0x00CED1, 0.6 );
+				dirLight.color.setHSL( 0.1, 1, 0.95 );
+				dirLight.position.set( - 1, 1.75, 1 );
+				dirLight.position.multiplyScalar( 30 );
+				scene.add( dirLight );
+
+				renderer = new THREE.WebGLRenderer( { antialias : true, alpha : true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				container.appendChild( renderer.domElement );
+
+				initComputeRenderer();
+
+				stats = new Stats();
+				container.appendChild( stats.dom );
+
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+				var gui = new GUI();
+
+				var effectController = {
+
+					separation: 20.0,
+					alignment: 20.0,
+					cohesion: 20.0,
+					freedom: 0.75,
+					size: sizes[ selectModel ],
+					count: BIRDS
+
+				};
+
+				var valuesChanger = function () {
+
+					velocityUniforms[ "separationDistance" ].value = effectController.separation;
+					velocityUniforms[ "alignmentDistance" ].value = effectController.alignment;
+					velocityUniforms[ "cohesionDistance" ].value = effectController.cohesion;
+					velocityUniforms[ "freedomFactor" ].value = effectController.freedom;
+					if( materialShader ) materialShader.uniforms[ "size" ].value = effectController.size;
+					BirdGeometry.setDrawRange ( 0, vertexPerBird * effectController.count )
+
+				};
+
+				valuesChanger();
+
+                gui.add( effectController, "separation", 0.0, 100.0, 1.0 ).onChange( valuesChanger );
+				gui.add( effectController, "alignment", 0.0, 100, 0.001 ).onChange( valuesChanger );
+				gui.add( effectController, "cohesion", 0.0, 100, 0.025 ).onChange( valuesChanger );
+				gui.add( effectController, "size", 0, 1, 0.01 ).onChange( valuesChanger );
+				gui.add( effectController, "count", 0, BIRDS, 1 ).onChange( valuesChanger );
+				gui.close();
+
+				initBirds();
+
+			}
+
+			function initComputeRenderer() {
+
+				gpuCompute = new GPUComputationRenderer( WIDTH, WIDTH, renderer );
+
+				var dtPosition = gpuCompute.createTexture();
+				var dtVelocity = gpuCompute.createTexture();
+				fillPositionTexture( dtPosition );
+				fillVelocityTexture( dtVelocity );
+
+				velocityVariable = gpuCompute.addVariable( "textureVelocity", document.getElementById( 'fragmentShaderVelocity' ).textContent, dtVelocity );
+				positionVariable = gpuCompute.addVariable( "texturePosition", document.getElementById( 'fragmentShaderPosition' ).textContent, dtPosition );
+
+				gpuCompute.setVariableDependencies( velocityVariable, [ positionVariable, velocityVariable ] );
+				gpuCompute.setVariableDependencies( positionVariable, [ positionVariable, velocityVariable ] );
+
+				positionUniforms = positionVariable.material.uniforms;
+				velocityUniforms = velocityVariable.material.uniforms;
+
+				positionUniforms[ "time" ] = { value: 0.0 };
+				positionUniforms[ "delta" ] = { value: 0.0 };
+				velocityUniforms[ "time" ] = { value: 1.0 };
+				velocityUniforms[ "delta" ] = { value: 0.0 };
+				velocityUniforms[ "testing" ] = { value: 1.0 };
+				velocityUniforms[ "separationDistance" ] = { value: 1.0 };
+				velocityUniforms[ "alignmentDistance" ] = { value: 1.0 };
+				velocityUniforms[ "cohesionDistance" ] = { value: 1.0 };
+				velocityUniforms[ "freedomFactor" ] = { value: 1.0 };
+				velocityUniforms[ "predator" ] = { value: new THREE.Vector3() };
+				velocityVariable.material.defines.BOUNDS = BOUNDS.toFixed( 2 );
+
+				velocityVariable.wrapS = THREE.RepeatWrapping;
+				velocityVariable.wrapT = THREE.RepeatWrapping;
+				positionVariable.wrapS = THREE.RepeatWrapping;
+				positionVariable.wrapT = THREE.RepeatWrapping;
+				
+				var error = gpuCompute.init();
+				if ( error !== null ) {
+				    console.error( error );
+				}
+			}
+
+			function initBirds() {
+
+				var geometry = BirdGeometry;
+
+				var m = new THREE.MeshStandardMaterial({
+					vertexColors : true,
+					flatShading : true,
+					roughness : 1,
+					metalness : 0
+				})
+
+				m.onBeforeCompile = ( shader ) => {
+
+					shader.uniforms.texturePosition = { value : null };
+					shader.uniforms.textureVelocity = { value : null };
+					shader.uniforms.textureAnimation = { value : textureAnimation };
+					shader.uniforms.time = { value : 1.0 };
+					shader.uniforms.size = { value : 0.1 };
+					shader.uniforms.delta = { value : 0.0 };
+
+                    var token = '#define STANDARD';
+                    
+                    var insert = /* glsl */`
+                        attribute vec4 reference;
+                        attribute vec4 seeds;
+                        attribute vec3 birdColor;
+                        uniform sampler2D texturePosition;
+                        uniform sampler2D textureVelocity;
+                        uniform sampler2D textureAnimation;
+                        uniform float size;
+                        uniform float time;
+                    `;
+
+					shader.vertexShader = shader.vertexShader.replace( token, token + insert );
+
+                    var token = '#include <begin_vertex>';
+                        
+                    var insert = /* glsl */`
+                        vec4 tmpPos = texture2D( texturePosition, reference.xy );
+                    
+                        vec3 pos = tmpPos.xyz;
+                        vec3 velocity = normalize(texture2D( textureVelocity, reference.xy ).xyz);
+                        vec3 aniPos = texture2D( textureAnimation, vec2( reference.z, mod( ( time + seeds.x ) * ( ( 0.0004 + seeds.y / 10000.0) + normalize( velocity ) / 20000.0 ), reference.w ) ) ).xyz;
+                        vec3 newPosition = position;
+                        
+                        newPosition = mat3( modelMatrix ) * ( newPosition + aniPos );
+                        newPosition *= size + seeds.y * size * 0.2;
+                        
+                        velocity.z *= -1.;
+                        float xz = length( velocity.xz );
+                        float xyz = 1.;
+                        float x = sqrt( 1. - velocity.y * velocity.y );
+
+                        float cosry = velocity.x / xz;
+                        float sinry = velocity.z / xz;
+
+                        float cosrz = x / xyz;
+                        float sinrz = velocity.y / xyz;
+
+                        mat3 maty =  mat3( cosry, 0, -sinry, 0    , 1, 0     , sinry, 0, cosry );
+                        mat3 matz =  mat3( cosrz , sinrz, 0, -sinrz, cosrz, 0, 0     , 0    , 1 );
+
+                        newPosition =  maty * matz * newPosition;
+                        newPosition += pos;
+                        
+                        vec3 transformed = vec3( newPosition );
+                    `;
+					
+        			shader.vertexShader = shader.vertexShader.replace( token, insert );
+
+					materialShader = shader;
+
+				}    
+
+				birdMesh = new THREE.Mesh( geometry, m );
+				birdMesh.rotation.y = Math.PI / 2;
+				
+				birdMesh.castShadow = true;
+				birdMesh.receiveShadow = true;
+
+				scene.add( birdMesh );
+
+			}
+
+			function fillPositionTexture( texture ) {
+
+				var theArray = texture.image.data;
+
+				for ( var k = 0, kl = theArray.length; k < kl; k += 4 ) {
+
+					var x = Math.random() * BOUNDS - BOUNDS_HALF;
+					var y = Math.random() * BOUNDS - BOUNDS_HALF;
+					var z = Math.random() * BOUNDS - BOUNDS_HALF;
+
+					theArray[ k + 0 ] = x;
+					theArray[ k + 1 ] = y;
+					theArray[ k + 2 ] = z;
+					theArray[ k + 3 ] = 1;
+
+				}
+
+			}
+
+			function fillVelocityTexture( texture ) {
+
+				var theArray = texture.image.data;
+
+				for ( var k = 0, kl = theArray.length; k < kl; k += 4 ) {
+
+					var x = Math.random() - 0.5;
+					var y = Math.random() - 0.5;
+					var z = Math.random() - 0.5;
+
+					theArray[ k + 0 ] = x * 10;
+					theArray[ k + 1 ] = y * 10;
+					theArray[ k + 2 ] = z * 10;
+					theArray[ k + 3 ] = 1;
+
+				}
+
+			}
+
+
+			function onWindowResize() {
+
+				windowHalfX = window.innerWidth / 2;
+				windowHalfY = window.innerHeight / 2;
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			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 animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				var now = performance.now();
+				var delta = ( now - last ) / 1000;
+				
+				if ( delta > 1 ) delta = 1; // safety cap on large deltas
+				last = now;
+
+				positionUniforms[ "time" ].value = now;
+				positionUniforms[ "delta" ].value = delta;
+				velocityUniforms[ "time" ].value = now;
+				velocityUniforms[ "delta" ].value = delta;
+				if( materialShader ) materialShader.uniforms[ "time" ].value = now;
+				if( materialShader ) materialShader.uniforms[ "delta" ].value = delta;
+
+				velocityUniforms[ "predator" ].value.set( 0.5 * mouseX / windowHalfX, - 0.5 * mouseY / windowHalfY, 0 );
+
+				mouseX = 10000;
+				mouseY = 10000;
+
+				gpuCompute.compute();
+				
+				if( materialShader ) materialShader.uniforms[ "texturePosition" ].value = gpuCompute.getCurrentRenderTarget( positionVariable ).texture;
+				if( materialShader ) materialShader.uniforms[ "textureVelocity" ].value = gpuCompute.getCurrentRenderTarget( velocityVariable ).texture;
+				
+				renderer.render( scene, camera );
+			}
+
+		</script>
+	</body>
+</html>

+ 1 - 3
examples/webgl_lights_hemisphere.html

@@ -178,8 +178,6 @@
 
 
 					scene.add( mesh );
 					scene.add( mesh );
 
 
-					console.log( mesh.material)
-
 					var mixer = new THREE.AnimationMixer( mesh );
 					var mixer = new THREE.AnimationMixer( mesh );
 					mixer.clipAction( gltf.animations[ 0 ] ).setDuration( 1 ).play();
 					mixer.clipAction( gltf.animations[ 0 ] ).setDuration( 1 ).play();
 					mixers.push( mixer );
 					mixers.push( mixer );
@@ -258,4 +256,4 @@
 
 
 		</script>
 		</script>
 	</body>
 	</body>
-</html>
+</html>