Browse Source

Examples: Improved interaction in webgpu_compute_birds (#29380)

* Examples: Simpler atmosphere approach in webgpu_compute_birds.

* no message

* Improved bird shape.

* Update webgpu_compute_birds.jpg

* Examples: Improved interaction in webgpu_compute_birds.

---------

Co-authored-by: sunag <sunagbrasil@gmail.com>
mrdoob 1 year ago
parent
commit
4e11cd6d3f
1 changed files with 42 additions and 29 deletions
  1. 42 29
      examples/webgpu_compute_birds.html

+ 42 - 29
examples/webgpu_compute_birds.html

@@ -35,25 +35,24 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { uniform, varying, vec4, add, sub, max, sin, mat3, uint, negate, cameraProjectionMatrix, cameraViewMatrix, positionLocal, modelWorldMatrix, sqrt, attribute, property, float, storage, storageObject, Fn, If, cos, Loop, Continue, normalize, instanceIndex, length } from 'three/tsl';
+			import { uniform, varying, vec4, add, sub, max, dot, sin, mat3, uint, negate, cameraProjectionMatrix, cameraViewMatrix, positionLocal, modelWorldMatrix, sqrt, attribute, property, float, storage, storageObject, Fn, If, cos, Loop, Continue, normalize, instanceIndex, length } from 'three/tsl';
+
+			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 			import Stats from 'three/addons/libs/stats.module.js';
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
 			let container, stats;
 			let camera, scene, renderer;
-			let mouseX = 0, mouseY = 0;
-
-			let windowHalfX = window.innerWidth / 2, windowHalfY = window.innerHeight / 2;
 
 			let last = performance.now();
 
+			let pointer, raycaster;
 			let computeVelocity, computePosition, effectController;
 
 			const BIRDS = 16384;
 			const SPEED_LIMIT = 9.0;
 			const BOUNDS = 800, BOUNDS_HALF = BOUNDS / 2;
-			const UPPER_BOUNDS = BOUNDS;
 
 			// Custom Geometry - using 3 triangles each. No normals currently.
 			class BirdGeometry extends THREE.BufferGeometry {
@@ -140,6 +139,11 @@
 				scene = new THREE.Scene();
 				scene.fog = new THREE.Fog( 0xffffff, 700, 3000 );
 
+				// Pointer
+
+				pointer = new THREE.Vector2();
+				raycaster = new THREE.Raycaster();
+
 				// Sky
 
 				const geometry = new THREE.IcosahedronGeometry( 1, 6 );
@@ -158,9 +162,11 @@
 
 				const mesh = new THREE.Mesh( geometry, material );
 				mesh.rotation.z = 0.75;
-				mesh.scale.setScalar( 1000 );
+				mesh.scale.setScalar( 1200 );
 				scene.add( mesh );
 
+				//
+
 				renderer = new THREE.WebGPURenderer( { antialiasing: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
@@ -168,6 +174,9 @@
 				renderer.toneMapping = THREE.NeutralToneMapping;
 				container.appendChild( renderer.domElement );
 
+				const controls = new OrbitControls( camera, renderer.domElement );
+				controls.connect( /* renderer.domElement */ );
+
 				// Initialize position, velocity, and phase values
 			
 				const positionArray = new Float32Array( BIRDS * 3 );
@@ -226,7 +235,8 @@
 					freedom: uniform( 0.75 ).label( 'freedom' ),
 					now: uniform( 0.0 ),
 					deltaTime: uniform( 0.0 ).label( 'deltaTime' ),
-					predator: uniform( new THREE.Vector3() ).label( 'predator' ),
+					rayOrigin: uniform( new THREE.Vector3() ).label( 'rayOrigin' ),
+					rayDirection: uniform( new THREE.Vector3() ).label( 'rayDirection' )
 				};
 
 				// Create geometry
@@ -303,7 +313,7 @@
 					const limit = property( 'float', 'limit' ).assign( SPEED_LIMIT );
 
 					// Destructure uniforms
-					const { alignment, separation, cohesion, predator, deltaTime } = effectController;
+					const { alignment, separation, cohesion, deltaTime, rayOrigin, rayDirection } = effectController;
 
 					const zoneRadius = separation.add( alignment ).add( cohesion );
 					const separationThresh = separation.div( zoneRadius );
@@ -313,21 +323,24 @@
 					const position = positionStorage.element( instanceIndex );
 					const velocity = velocityStorage.element( instanceIndex );
 
-					// Add influence of mouse position to velocity.
-					const dirToPredator = predator.mul( UPPER_BOUNDS ).sub( position );
-					dirToPredator.z.assign( 0.0 );
-					const distToPredator = length( dirToPredator );
-					const distToPreadatorSq = distToPredator.mul( distToPredator );
+					// Add influence of pointer position to velocity.
+					const directionToRay = rayOrigin.sub( position );
+					const projectionLength = dot( directionToRay, rayDirection );
 
-					const preyRadius = float( 150.0 );
-					const preyRadiusSq = preyRadius.mul( preyRadius );
+					const closestPoint = rayOrigin.sub( rayDirection.mul( projectionLength ) );
+
+					const directionToClosestPoint = closestPoint.sub( position );
+					const distanceToClosestPoint = length( directionToClosestPoint );
+					const distanceToClosestPointSq = distanceToClosestPoint.mul( distanceToClosestPoint );
+
+					const rayRadius = float( 150.0 );
+					const rayRadiusSq = rayRadius.mul( rayRadius );
+
+					If( distanceToClosestPointSq.lessThan( rayRadiusSq ), () => {
 
-					// Move birds away from predator if they are within the predator's area.
-					If( distToPredator.lessThan( preyRadius ), () => {
-			
 						// Scale bird velocity inversely with distance from prey radius center.
-						const velocityAdjust = ( distToPreadatorSq.div( preyRadiusSq ).sub( 1.0 ) ).mul( deltaTime ).mul( 100.0 );
-						velocity.addAssign( normalize( dirToPredator ).mul( velocityAdjust ) );
+						const velocityAdjust = ( distanceToClosestPointSq.div( rayRadiusSq ).sub( 1.0 ) ).mul( deltaTime ).mul( 100.0 );
+						velocity.addAssign( normalize( directionToClosestPoint ).mul( velocityAdjust ) );
 						limit.addAssign( 5.0 );
 
 					} );
@@ -441,9 +454,6 @@
 
 			function onWindowResize() {
 
-				windowHalfX = window.innerWidth / 2;
-				windowHalfY = window.innerHeight / 2;
-
 				camera.aspect = window.innerWidth / window.innerHeight;
 				camera.updateProjectionMatrix();
 
@@ -455,8 +465,8 @@
 
 				if ( event.isPrimary === false ) return;
 
-				mouseX = event.clientX - windowHalfX;
-				mouseY = event.clientY - windowHalfY;
+				pointer.x = ( event.clientX / window.innerWidth ) * 2.0 - 1.0;
+				pointer.y = 1.0 - ( event.clientY / window.innerHeight ) * 2.0;
 
 			}
 
@@ -475,17 +485,20 @@
 				if ( deltaTime > 1 ) deltaTime = 1; // safety cap on large deltas
 				last = now;
 
+				raycaster.setFromCamera( pointer, camera );
+
 				effectController.now.value = now;
 				effectController.deltaTime.value = deltaTime;
-				effectController.predator.value.set( 0.5 * mouseX / windowHalfX, - 0.5 * mouseY / windowHalfY, 0 );
-
-				mouseX = 10000;
-				mouseY = 10000;
+				effectController.rayOrigin.value.copy( raycaster.ray.origin );
+				effectController.rayDirection.value.copy( raycaster.ray.direction );
 
 				renderer.compute( computeVelocity );
 				renderer.compute( computePosition );
 				renderer.render( scene, camera );
 
+				// Move pointer away so we only affect birds when moving the mouse
+				pointer.y = 10;
+
 			}
 
 			init();

粤ICP备19079148号