webgl_gpgpu_birds.html 16.9 KB
Newer Older
M
r64  
Mr.doob 已提交
1 2 3 4 5 6
<!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">
M
r105  
Mr.doob 已提交
7
		<link type="text/css" rel="stylesheet" href="main.css">
M
r64  
Mr.doob 已提交
8 9
		<style>
			body {
M
r105  
Mr.doob 已提交
10 11
				background-color: #fff;
				color: #444;
M
r64  
Mr.doob 已提交
12 13
			}
			a {
M
r105  
Mr.doob 已提交
14
				color:#08f;
M
r64  
Mr.doob 已提交
15 16 17 18 19 20
			}
		</style>
	</head>
	<body>

		<div id="info">
M
r113  
Mr.doob 已提交
21
			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl gpgpu birds<br/>
M
r64  
Mr.doob 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
			Move mouse to disturb birds.
		</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 -->
		<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
M
r102  
Mr.doob 已提交
62
			uniform float separationDistance; // 20
M
r64  
Mr.doob 已提交
63
			uniform float alignmentDistance; // 40
M
r68  
Mr.doob 已提交
64
			uniform float cohesionDistance; //
M
r64  
Mr.doob 已提交
65 66 67
			uniform float freedomFactor;
			uniform vec3 predator;

M
r78  
Mr.doob 已提交
68 69
			const float width = resolution.x;
			const float height = resolution.y;
M
r64  
Mr.doob 已提交
70 71 72 73 74 75

			const float PI = 3.141592653589793;
			const float PI_2 = PI * 2.0;
			// const float VISION = PI * 0.55;

			float zoneRadius = 40.0;
M
r72  
Mr.doob 已提交
76
			float zoneRadiusSquared = 1600.0;
M
r64  
Mr.doob 已提交
77 78 79 80

			float separationThresh = 0.45;
			float alignmentThresh = 0.65;

M
r78  
Mr.doob 已提交
81
			const float UPPER_BOUNDS = BOUNDS;
M
r64  
Mr.doob 已提交
82 83 84 85
			const float LOWER_BOUNDS = -UPPER_BOUNDS;

			const float SPEED_LIMIT = 9.0;

M
r102.1  
Mr.doob 已提交
86 87
			float rand( vec2 co ){
				return fract( sin( dot( co.xy, vec2(12.9898,78.233) ) ) * 43758.5453 );
M
r64  
Mr.doob 已提交
88 89
			}

M
r78  
Mr.doob 已提交
90
			void main() {
M
r64  
Mr.doob 已提交
91

M
r102  
Mr.doob 已提交
92 93 94
				zoneRadius = separationDistance + alignmentDistance + cohesionDistance;
				separationThresh = separationDistance / zoneRadius;
				alignmentThresh = ( separationDistance + alignmentDistance ) / zoneRadius;
M
r64  
Mr.doob 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107
				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;

M
r102  
Mr.doob 已提交
108
				float separationSquared = separationDistance * separationDistance;
M
r64  
Mr.doob 已提交
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
				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;

M
r68  
Mr.doob 已提交
127

M
r64  
Mr.doob 已提交
128
				// move birds away from predator
M
r102.1  
Mr.doob 已提交
129
				if ( dist < preyRadius ) {
M
r64  
Mr.doob 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

					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 );
M
r70  
Mr.doob 已提交
145

M
r64  
Mr.doob 已提交
146 147 148
				dir.y *= 2.5;
				velocity -= normalize( dir ) * delta * 5.;

M
r102.1  
Mr.doob 已提交
149 150
				for ( float y = 0.0; y < height; y++ ) {
					for ( float x = 0.0; x < width; x++ ) {
M
r64  
Mr.doob 已提交
151

M
r70  
Mr.doob 已提交
152 153
						vec2 ref = vec2( x + 0.5, y + 0.5 ) / resolution.xy;
						birdPosition = texture2D( texturePosition, ref ).xyz;
M
r64  
Mr.doob 已提交
154 155

						dir = birdPosition - selfPosition;
M
r102.1  
Mr.doob 已提交
156
						dist = length( dir );
M
r64  
Mr.doob 已提交
157

M
r102.1  
Mr.doob 已提交
158
						if ( dist < 0.0001 ) continue;
M
r70  
Mr.doob 已提交
159 160

						distSquared = dist * dist;
M
r64  
Mr.doob 已提交
161

M
r102.1  
Mr.doob 已提交
162
						if ( distSquared > zoneRadiusSquared ) continue;
M
r64  
Mr.doob 已提交
163

M
r70  
Mr.doob 已提交
164
						percent = distSquared / zoneRadiusSquared;
M
r64  
Mr.doob 已提交
165

M
r70  
Mr.doob 已提交
166
						if ( percent < separationThresh ) { // low
M
r64  
Mr.doob 已提交
167

M
r70  
Mr.doob 已提交
168
							// Separation - Move apart for comfort
M
r102.1  
Mr.doob 已提交
169 170
							f = ( separationThresh / percent - 1.0 ) * delta;
							velocity -= normalize( dir ) * f;
M
r64  
Mr.doob 已提交
171

M
r70  
Mr.doob 已提交
172
						} else if ( percent < alignmentThresh ) { // high
M
r64  
Mr.doob 已提交
173

M
r70  
Mr.doob 已提交
174 175 176
							// Alignment - fly the same direction
							float threshDelta = alignmentThresh - separationThresh;
							float adjustedPercent = ( percent - separationThresh ) / threshDelta;
M
r68  
Mr.doob 已提交
177

M
r70  
Mr.doob 已提交
178
							birdVelocity = texture2D( textureVelocity, ref ).xyz;
M
r64  
Mr.doob 已提交
179

M
r70  
Mr.doob 已提交
180
							f = ( 0.5 - cos( adjustedPercent * PI_2 ) * 0.5 + 0.5 ) * delta;
M
r102.1  
Mr.doob 已提交
181
							velocity += normalize( birdVelocity ) * f;
M
r64  
Mr.doob 已提交
182

M
r70  
Mr.doob 已提交
183
						} else {
M
r64  
Mr.doob 已提交
184

M
r70  
Mr.doob 已提交
185 186 187
							// Attraction / Cohesion - move closer
							float threshDelta = 1.0 - alignmentThresh;
							float adjustedPercent = ( percent - alignmentThresh ) / threshDelta;
M
r64  
Mr.doob 已提交
188

M
r70  
Mr.doob 已提交
189
							f = ( 0.5 - ( cos( adjustedPercent * PI_2 ) * -0.5 + 0.5 ) ) * delta;
M
r64  
Mr.doob 已提交
190

M
r102.1  
Mr.doob 已提交
191
							velocity += normalize( dir ) * f;
M
r64  
Mr.doob 已提交
192 193 194 195 196 197 198

						}

					}

				}

M
r68  
Mr.doob 已提交
199

M
r64  
Mr.doob 已提交
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220

				// 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="x-shader/x-vertex" id="birdVS">

			attribute vec2 reference;
			attribute float birdVertex;

			attribute vec3 birdColor;
M
r68  
Mr.doob 已提交
221

M
r64  
Mr.doob 已提交
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
			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 );
M
r68  
Mr.doob 已提交
250

M
r64  
Mr.doob 已提交
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
				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;
M
r68  
Mr.doob 已提交
274

M
r64  
Mr.doob 已提交
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
				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>

M
r106  
Mr.doob 已提交
298
		<script type="module">
M
Mr.doob 已提交
299

M
r106  
Mr.doob 已提交
300
			import * as THREE from '../build/three.module.js';
M
r64  
Mr.doob 已提交
301

M
r106  
Mr.doob 已提交
302 303
			import Stats from './jsm/libs/stats.module.js';
			import { GUI } from './jsm/libs/dat.gui.module.js';
M
r97  
Mr.doob 已提交
304

M
r106  
Mr.doob 已提交
305
			import { GPUComputationRenderer } from './jsm/misc/GPUComputationRenderer.js';
M
r64  
Mr.doob 已提交
306 307

			/* TEXTURE WIDTH FOR SIMULATION */
M
r106  
Mr.doob 已提交
308
			var WIDTH = 32;
M
r64  
Mr.doob 已提交
309

M
r67  
Mr.doob 已提交
310
			var BIRDS = WIDTH * WIDTH;
M
r64  
Mr.doob 已提交
311

M
r67  
Mr.doob 已提交
312
			// Custom Geometry - using 3 triangles each. No UVs, no normals currently.
M
r106  
Mr.doob 已提交
313
			var BirdGeometry = function () {
M
r64  
Mr.doob 已提交
314

M
r67  
Mr.doob 已提交
315 316 317 318 319
				var triangles = BIRDS * 3;
				var points = triangles * 3;

				THREE.BufferGeometry.call( this );

M
r68  
Mr.doob 已提交
320 321 322 323
				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 );
M
r64  
Mr.doob 已提交
324

M
r110  
Mr.doob 已提交
325 326 327 328
				this.setAttribute( 'position', vertices );
				this.setAttribute( 'birdColor', birdColors );
				this.setAttribute( 'reference', references );
				this.setAttribute( 'birdVertex', birdVertex );
M
r64  
Mr.doob 已提交
329

M
r110  
Mr.doob 已提交
330
				// this.setAttribute( 'normal', new Float32Array( points * 3 ), 3 );
M
r67  
Mr.doob 已提交
331 332 333 334 335


				var v = 0;

				function verts_push() {
M
r98  
Mr.doob 已提交
336 337 338 339 340

					for ( var i = 0; i < arguments.length; i ++ ) {

						vertices.array[ v ++ ] = arguments[ i ];

M
r103  
Mr.doob 已提交
341
					}
M
r98  
Mr.doob 已提交
342

M
r103  
Mr.doob 已提交
343
				}
M
r64  
Mr.doob 已提交
344

M
r67  
Mr.doob 已提交
345
				var wingsSpan = 20;
M
r64  
Mr.doob 已提交
346

M
r98  
Mr.doob 已提交
347
				for ( var f = 0; f < BIRDS; f ++ ) {
M
r67  
Mr.doob 已提交
348 349 350

					// Body
					verts_push(
M
r98  
Mr.doob 已提交
351 352
						0, - 0, - 20,
						0, 4, - 20,
M
r67  
Mr.doob 已提交
353
						0, 0, 30
M
r64  
Mr.doob 已提交
354 355
					);

M
r67  
Mr.doob 已提交
356 357
					// Left Wing
					verts_push(
M
r98  
Mr.doob 已提交
358 359
						0, 0, - 15,
						- wingsSpan, 0, 0,
M
r67  
Mr.doob 已提交
360 361
						0, 0, 15
					);
M
r64  
Mr.doob 已提交
362

M
r67  
Mr.doob 已提交
363 364 365 366
					// Right Wing
					verts_push(
						0, 0, 15,
						wingsSpan, 0, 0,
M
r98  
Mr.doob 已提交
367
						0, 0, - 15
M
r67  
Mr.doob 已提交
368
					);
M
r64  
Mr.doob 已提交
369

M
r67  
Mr.doob 已提交
370
				}
M
r64  
Mr.doob 已提交
371

M
r98  
Mr.doob 已提交
372
				for ( var v = 0; v < triangles * 3; v ++ ) {
M
r64  
Mr.doob 已提交
373

M
r98  
Mr.doob 已提交
374 375 376
					var i = ~ ~ ( v / 3 );
					var x = ( i % WIDTH ) / WIDTH;
					var y = ~ ~ ( i / WIDTH ) / WIDTH;
M
r67  
Mr.doob 已提交
377 378 379

					var c = new THREE.Color(
						0x444444 +
M
r98  
Mr.doob 已提交
380
						~ ~ ( v / 9 ) / BIRDS * 0x666666
M
r64  
Mr.doob 已提交
381 382
					);

M
r67  
Mr.doob 已提交
383 384 385 386
					birdColors.array[ v * 3 + 0 ] = c.r;
					birdColors.array[ v * 3 + 1 ] = c.g;
					birdColors.array[ v * 3 + 2 ] = c.b;

M
r98  
Mr.doob 已提交
387
					references.array[ v * 2 ] = x;
M
r67  
Mr.doob 已提交
388 389
					references.array[ v * 2 + 1 ] = y;

M
r98  
Mr.doob 已提交
390
					birdVertex.array[ v ] = v % 9;
M
r64  
Mr.doob 已提交
391 392 393

				}

M
r72  
Mr.doob 已提交
394
				this.scale( 0.2, 0.2, 0.2 );
M
r64  
Mr.doob 已提交
395

M
r72  
Mr.doob 已提交
396
			};
M
r64  
Mr.doob 已提交
397

M
r106  
Mr.doob 已提交
398
			BirdGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
M
r64  
Mr.doob 已提交
399 400 401


			var container, stats;
M
r106  
Mr.doob 已提交
402
			var camera, scene, renderer;
M
r64  
Mr.doob 已提交
403 404 405 406
			var mouseX = 0, mouseY = 0;

			var windowHalfX = window.innerWidth / 2;
			var windowHalfY = window.innerHeight / 2;
M
r68  
Mr.doob 已提交
407

M
r64  
Mr.doob 已提交
408 409 410 411
			var BOUNDS = 800, BOUNDS_HALF = BOUNDS / 2;

			var last = performance.now();

M
r78  
Mr.doob 已提交
412 413 414 415 416 417
			var gpuCompute;
			var velocityVariable;
			var positionVariable;
			var positionUniforms;
			var velocityUniforms;
			var birdUniforms;
M
r64  
Mr.doob 已提交
418 419 420 421 422 423 424 425 426 427 428 429 430

			init();
			animate();

			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();
M
r87  
Mr.doob 已提交
431
				scene.background = new THREE.Color( 0xffffff );
M
r64  
Mr.doob 已提交
432 433 434
				scene.fog = new THREE.Fog( 0xffffff, 100, 1000 );

				renderer = new THREE.WebGLRenderer();
M
r70  
Mr.doob 已提交
435
				renderer.setPixelRatio( window.devicePixelRatio );
M
r64  
Mr.doob 已提交
436
				renderer.setSize( window.innerWidth, window.innerHeight );
M
r67  
Mr.doob 已提交
437
				container.appendChild( renderer.domElement );
M
r64  
Mr.doob 已提交
438

M
r78  
Mr.doob 已提交
439
				initComputeRenderer();
M
r64  
Mr.doob 已提交
440 441

				stats = new Stats();
M
r76  
Mr.doob 已提交
442
				container.appendChild( stats.dom );
M
r64  
Mr.doob 已提交
443 444 445 446 447 448 449 450 451

				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
				document.addEventListener( 'touchmove', onDocumentTouchMove, false );

				//

				window.addEventListener( 'resize', onWindowResize, false );

M
r106  
Mr.doob 已提交
452
				var gui = new GUI();
M
r64  
Mr.doob 已提交
453 454 455


				var effectController = {
M
r102  
Mr.doob 已提交
456
					separation: 20.0,
M
r64  
Mr.doob 已提交
457 458 459 460 461
					alignment: 20.0,
					cohesion: 20.0,
					freedom: 0.75
				};

M
r98  
Mr.doob 已提交
462
				var valuesChanger = function () {
M
r64  
Mr.doob 已提交
463

M
r102  
Mr.doob 已提交
464
					velocityUniforms[ "separationDistance" ].value = effectController.separation;
M
r101  
Mr.doob 已提交
465 466 467
					velocityUniforms[ "alignmentDistance" ].value = effectController.alignment;
					velocityUniforms[ "cohesionDistance" ].value = effectController.cohesion;
					velocityUniforms[ "freedomFactor" ].value = effectController.freedom;
M
r64  
Mr.doob 已提交
468 469 470 471 472

				};

				valuesChanger();

M
r102  
Mr.doob 已提交
473
				gui.add( effectController, "separation", 0.0, 100.0, 1.0 ).onChange( valuesChanger );
M
r64  
Mr.doob 已提交
474 475 476 477 478
				gui.add( effectController, "alignment", 0.0, 100, 0.001 ).onChange( valuesChanger );
				gui.add( effectController, "cohesion", 0.0, 100, 0.025 ).onChange( valuesChanger );
				gui.close();

				initBirds();
M
r68  
Mr.doob 已提交
479

M
r64  
Mr.doob 已提交
480 481
			}

M
r78  
Mr.doob 已提交
482 483
			function initComputeRenderer() {

M
r101  
Mr.doob 已提交
484
				gpuCompute = new GPUComputationRenderer( WIDTH, WIDTH, renderer );
M
r78  
Mr.doob 已提交
485

M
r119  
Mr.doob 已提交
486 487 488 489 490 491
				if ( isSafari() ) {

					gpuCompute.setDataType( THREE.HalfFloatType );

				}

M
r78  
Mr.doob 已提交
492 493 494 495 496 497 498 499 500 501 502 503 504 505
				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;

M
r101  
Mr.doob 已提交
506 507 508 509 510
				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 };
M
r102  
Mr.doob 已提交
511
				velocityUniforms[ "separationDistance" ] = { value: 1.0 };
M
r101  
Mr.doob 已提交
512 513 514 515
				velocityUniforms[ "alignmentDistance" ] = { value: 1.0 };
				velocityUniforms[ "cohesionDistance" ] = { value: 1.0 };
				velocityUniforms[ "freedomFactor" ] = { value: 1.0 };
				velocityUniforms[ "predator" ] = { value: new THREE.Vector3() };
M
r78  
Mr.doob 已提交
516 517 518 519 520 521 522 523
				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();
M
r119  
Mr.doob 已提交
524

M
r78  
Mr.doob 已提交
525
				if ( error !== null ) {
M
r98  
Mr.doob 已提交
526

M
r119  
Mr.doob 已提交
527
					console.error( error );
M
r98  
Mr.doob 已提交
528

M
r103  
Mr.doob 已提交
529
				}
M
r78  
Mr.doob 已提交
530 531

			}
M
r64  
Mr.doob 已提交
532

M
r119  
Mr.doob 已提交
533 534 535 536 537 538
			function isSafari() {

				return !! navigator.userAgent.match( /Safari/i ) && ! navigator.userAgent.match( /Chrome/i );

			}

M
r64  
Mr.doob 已提交
539 540
			function initBirds() {

M
r106  
Mr.doob 已提交
541
				var geometry = new BirdGeometry();
M
r64  
Mr.doob 已提交
542 543 544

				// For Vertex and Fragment
				birdUniforms = {
M
r101  
Mr.doob 已提交
545 546 547 548 549
					"color": { value: new THREE.Color( 0xff2200 ) },
					"texturePosition": { value: null },
					"textureVelocity": { value: null },
					"time": { value: 1.0 },
					"delta": { value: 0.0 }
M
r64  
Mr.doob 已提交
550 551
				};

M
r106  
Mr.doob 已提交
552
				// THREE.ShaderMaterial
M
r72  
Mr.doob 已提交
553
				var material = new THREE.ShaderMaterial( {
M
r98  
Mr.doob 已提交
554 555
					uniforms: birdUniforms,
					vertexShader: document.getElementById( 'birdVS' ).textContent,
M
r64  
Mr.doob 已提交
556
					fragmentShader: document.getElementById( 'birdFS' ).textContent,
M
r67  
Mr.doob 已提交
557
					side: THREE.DoubleSide
M
r64  
Mr.doob 已提交
558

M
r98  
Mr.doob 已提交
559
				} );
M
r64  
Mr.doob 已提交
560

M
r86  
Mr.doob 已提交
561
				var birdMesh = new THREE.Mesh( geometry, material );
M
r64  
Mr.doob 已提交
562 563 564 565
				birdMesh.rotation.y = Math.PI / 2;
				birdMesh.matrixAutoUpdate = false;
				birdMesh.updateMatrix();

M
r98  
Mr.doob 已提交
566
				scene.add( birdMesh );
M
r64  
Mr.doob 已提交
567 568 569

			}

M
r78  
Mr.doob 已提交
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
			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;

				}

			}


M
r64  
Mr.doob 已提交
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
			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() {
M
r67  
Mr.doob 已提交
666

M
r72  
Mr.doob 已提交
667
				var now = performance.now();
M
r98  
Mr.doob 已提交
668
				var delta = ( now - last ) / 1000;
M
r64  
Mr.doob 已提交
669

M
r98  
Mr.doob 已提交
670
				if ( delta > 1 ) delta = 1; // safety cap on large deltas
M
r64  
Mr.doob 已提交
671 672
				last = now;

M
r101  
Mr.doob 已提交
673 674 675 676 677 678
				positionUniforms[ "time" ].value = now;
				positionUniforms[ "delta" ].value = delta;
				velocityUniforms[ "time" ].value = now;
				velocityUniforms[ "delta" ].value = delta;
				birdUniforms[ "time" ].value = now;
				birdUniforms[ "delta" ].value = delta;
M
r64  
Mr.doob 已提交
679

M
r101  
Mr.doob 已提交
680
				velocityUniforms[ "predator" ].value.set( 0.5 * mouseX / windowHalfX, - 0.5 * mouseY / windowHalfY, 0 );
M
r64  
Mr.doob 已提交
681 682 683 684

				mouseX = 10000;
				mouseY = 10000;

M
r78  
Mr.doob 已提交
685 686
				gpuCompute.compute();

M
r101  
Mr.doob 已提交
687 688
				birdUniforms[ "texturePosition" ].value = gpuCompute.getCurrentRenderTarget( positionVariable ).texture;
				birdUniforms[ "textureVelocity" ].value = gpuCompute.getCurrentRenderTarget( velocityVariable ).texture;
M
r77  
Mr.doob 已提交
689

M
r64  
Mr.doob 已提交
690 691 692 693 694 695 696
				renderer.render( scene, camera );

			}

		</script>
	</body>
</html>