Difference between revisions of "Team:CU-Boulder/Test"
Jimmynovik (Talk | contribs) |
Jimmynovik (Talk | contribs) |
||
Line 1: | Line 1: | ||
+ | |||
+ | <!DOCTYPE html> | ||
<html lang="en"> | <html lang="en"> | ||
<head> | <head> | ||
− | <title>three.js webgl - | + | <title>three.js webgl - gpgpu - flocking</title> |
<meta charset="utf-8"> | <meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | ||
<style> | <style> | ||
− | |||
body { | body { | ||
− | color: # | + | background-color: #ffffff; |
+ | margin: 0px; | ||
+ | overflow: hidden; | ||
font-family:Monospace; | font-family:Monospace; | ||
font-size:13px; | font-size:13px; | ||
text-align:center; | text-align:center; | ||
+ | text-align:center; | ||
+ | cursor: pointer; | ||
+ | } | ||
− | + | a { | |
− | + | color:#0078ff; | |
− | + | ||
} | } | ||
#info { | #info { | ||
+ | color: #000; | ||
position: absolute; | position: absolute; | ||
− | top: | + | top: 10px; |
− | + | width: 100%; | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
} | } | ||
Line 32: | Line 33: | ||
<body> | <body> | ||
− | |||
<div id="info"> | <div id="info"> | ||
− | <a href="http://threejs.org" target="_blank">three.js</a> | + | <a href="http://threejs.org" target="_blank">three.js</a> - <span id="birds"></span> webgl gpgpu birds<br/> |
+ | Select <span id="options"></span> birds<br/> | ||
+ | Move mouse to disturb birds. | ||
+ | |||
</div> | </div> | ||
− | |||
<script src="http://threejs.org/build/three.min.js"></script> | <script src="http://threejs.org/build/three.min.js"></script> | ||
− | <script src="http://threejs.org/examples/js/ | + | <script src="http://threejs.org/examples/js/Detector.js"></script> |
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script> | <script src="http://threejs.org/examples/js/libs/stats.min.js"></script> | ||
+ | <script src="http://threejs.org/examples/js/libs/dat.gui.min.js"></script> | ||
− | <script> | + | <script src="js/SimulationRenderer.js"></script> |
− | + | <!-- | |
− | + | TODO: If you're reading this, you may wish to improve this example by | |
− | + | - Create a better shading for the birds? | |
− | + | - Refactoring the SimulationRenderer to a more generic TextureRenderer / making the GPGPU workflow easier? | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | --> | |
− | + | ||
− | + | ||
− | + | ||
+ | <!-- pass through vertex shader --> | ||
+ | <script id="vertexShader" type="x-shader/x-vertex"> | ||
+ | |||
+ | void main() { | ||
+ | |||
+ | gl_Position = vec4( position, 1.0 ); | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | + | </script> | |
− | + | ||
− | + | <!-- pass through fragment shader --> | |
+ | <script id="fragmentShader" type="x-shader/x-fragment"> | ||
− | + | uniform vec2 resolution; | |
+ | uniform float time; | ||
+ | uniform sampler2D texture; | ||
− | + | void main() { | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | vec2 uv = gl_FragCoord.xy / resolution.xy; | |
− | + | ||
− | + | vec3 color = texture2D( texture, uv ).xyz; | |
+ | |||
+ | gl_FragColor = vec4( color, 1.0 ); | ||
} | } | ||
− | + | </script> | |
+ | <!-- end pass through shaders --> | ||
− | + | <!-- shader for bird's position --> | |
+ | <script id="fragmentShaderPosition" type="x-shader/x-fragment"> | ||
− | + | uniform vec2 resolution; | |
+ | uniform float time; | ||
+ | uniform float delta; | ||
+ | uniform sampler2D textureVelocity; | ||
+ | uniform sampler2D texturePosition; | ||
− | + | 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 vec2 resolution; | ||
+ | uniform float time; | ||
+ | uniform float testing; | ||
+ | uniform float delta; // about 0.016 | ||
+ | uniform float seperationDistance; // 20 | ||
+ | uniform float alignmentDistance; // 40 | ||
+ | uniform float cohesionDistance; // | ||
+ | uniform float freedomFactor; | ||
+ | uniform vec3 predator; | ||
+ | |||
+ | |||
+ | uniform sampler2D textureVelocity; | ||
+ | uniform sampler2D texturePosition; | ||
+ | |||
+ | const float width = WIDTH; | ||
+ | const float height = WIDTH; | ||
+ | |||
+ | const float PI = 3.141592653589793; | ||
+ | const float PI_2 = PI * 2.0; | ||
+ | // const float VISION = PI * 0.55; | ||
+ | |||
+ | float zoneRadius = 40.0; | ||
+ | float zoneRadiusSquared = zoneRadius * zoneRadius; | ||
+ | |||
+ | float separationThresh = 0.45; | ||
+ | float alignmentThresh = 0.65; | ||
+ | |||
+ | const float UPPER_BOUNDS = 400.0; | ||
+ | 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 = seperationDistance + alignmentDistance + cohesionDistance; | ||
+ | separationThresh = seperationDistance / zoneRadius; | ||
+ | alignmentThresh = ( seperationDistance + 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 seperationSquared = seperationDistance * seperationDistance; | |
+ | 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="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> | ||
+ | |||
+ | if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); | ||
+ | |||
+ | var hash = document.location.hash.substr( 1 ); | ||
+ | if (hash) hash = parseInt(hash, 0); | ||
+ | |||
+ | /* TEXTURE WIDTH FOR SIMULATION */ | ||
+ | var WIDTH = hash || 32; | ||
+ | |||
+ | var BIRDS = WIDTH * WIDTH; | ||
+ | |||
+ | // Custom Geometry - using 3 triangles each. No UVs, no normals currently. | ||
+ | THREE.BirdGeometry = function () { | ||
+ | |||
+ | var triangles = BIRDS * 3; | ||
+ | var points = triangles * 3; | ||
+ | |||
+ | THREE.BufferGeometry.call( this ); | ||
+ | |||
+ | 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 ); | ||
+ | |||
+ | this.addAttribute( 'position', vertices ); | ||
+ | this.addAttribute( 'birdColor', birdColors ); | ||
+ | this.addAttribute( 'reference', references ); | ||
+ | this.addAttribute( 'birdVertex', birdVertex ); | ||
+ | |||
+ | // this.addAttribute( 'normal', new Float32Array( points * 3 ), 3 ); | ||
+ | |||
+ | |||
+ | var v = 0; | ||
+ | |||
+ | function verts_push() { | ||
+ | for (var i=0; i < arguments.length; i++) { | ||
+ | vertices.array[v++] = arguments[i]; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | var wingsSpan = 20; | ||
+ | |||
+ | for (var f = 0; f<BIRDS; f++ ) { | ||
+ | |||
+ | // Body | ||
+ | verts_push( | ||
+ | 0, -0, -20, | ||
+ | 0, 4, -20, | ||
+ | 0, 0, 30 | ||
+ | ); | ||
+ | |||
+ | // 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 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; | ||
+ | |||
+ | birdVertex.array[ v ] = v % 9; | ||
+ | |||
+ | } | ||
+ | |||
+ | this.applyMatrix( new THREE.Matrix4().makeScale( 0.2, 0.2, 0.2 ) ); | ||
+ | |||
+ | } | ||
+ | |||
+ | THREE.BirdGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); | ||
+ | |||
+ | |||
+ | var container, stats; | ||
+ | var camera, scene, renderer, geometry, i, h, color; | ||
+ | var mouseX = 0, mouseY = 0; | ||
+ | |||
+ | var windowHalfX = window.innerWidth / 2; | ||
+ | var windowHalfY = window.innerHeight / 2; | ||
+ | |||
+ | var PARTICLES = WIDTH * WIDTH; | ||
+ | var BOUNDS = 800, BOUNDS_HALF = BOUNDS / 2; | ||
+ | |||
+ | document.getElementById('birds').innerText = PARTICLES; | ||
+ | |||
+ | function change(n) { | ||
+ | location.hash = n; | ||
+ | location.reload(); | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | |||
+ | var options = ''; | ||
+ | for (i=1; i<7; i++) { | ||
+ | var j = Math.pow(2, i); | ||
+ | options += '<a href="#" onclick="return change(' + j + ')">' + (j * j) + '</a> '; | ||
+ | } | ||
+ | document.getElementById('options').innerHTML = options; | ||
+ | |||
+ | var last = performance.now(); | ||
+ | |||
+ | var simulator; | ||
+ | |||
+ | 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(); | ||
+ | |||
+ | scene.fog = new THREE.Fog( 0xffffff, 100, 1000 ); | ||
+ | |||
+ | renderer = new THREE.WebGLRenderer(); | ||
+ | renderer.setClearColor( scene.fog.color ); | ||
+ | renderer.setPixelRatio( window.devicePixelRatio ); | ||
+ | renderer.setSize( window.innerWidth, window.innerHeight ); | ||
container.appendChild( renderer.domElement ); | container.appendChild( renderer.domElement ); | ||
− | + | simulator = new SimulationRenderer(WIDTH, renderer); | |
+ | simulator.init(); | ||
stats = new Stats(); | stats = new Stats(); | ||
Line 198: | Line 518: | ||
stats.domElement.style.top = '0px'; | stats.domElement.style.top = '0px'; | ||
container.appendChild( stats.domElement ); | container.appendChild( stats.domElement ); | ||
+ | |||
+ | document.addEventListener( 'mousemove', onDocumentMouseMove, false ); | ||
+ | document.addEventListener( 'touchstart', onDocumentTouchStart, false ); | ||
+ | document.addEventListener( 'touchmove', onDocumentTouchMove, false ); | ||
+ | |||
+ | // | ||
window.addEventListener( 'resize', onWindowResize, false ); | window.addEventListener( 'resize', onWindowResize, false ); | ||
− | |||
− | |||
− | + | var gui = new dat.GUI(); | |
− | + | ||
− | + | ||
+ | var effectController = { | ||
+ | seperation: 20.0, | ||
+ | alignment: 20.0, | ||
+ | cohesion: 20.0, | ||
+ | freedom: 0.75 | ||
+ | }; | ||
+ | |||
+ | var valuesChanger = function() { | ||
+ | |||
+ | simulator.velocityUniforms.seperationDistance.value = effectController.seperation; | ||
+ | simulator.velocityUniforms.alignmentDistance.value = effectController.alignment; | ||
+ | simulator.velocityUniforms.cohesionDistance.value = effectController.cohesion; | ||
+ | simulator.velocityUniforms.freedomFactor.value = effectController.freedom; | ||
+ | |||
+ | }; | ||
+ | |||
+ | valuesChanger(); | ||
+ | |||
+ | |||
+ | gui.add( effectController, "seperation", 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.close(); | ||
+ | |||
+ | initBirds(); | ||
} | } | ||
− | |||
− | + | function initBirds() { | |
− | + | ||
− | + | ||
− | + | var geometry = new THREE.BirdGeometry(); | |
− | + | ||
− | + | // For Vertex Shaders | |
+ | birdAttributes = { | ||
+ | // index: { type: 'i', value: [] }, | ||
+ | birdColor: { type: 'c', value: null }, | ||
+ | reference: { type: 'v2', value: null }, | ||
+ | birdVertex: { type: 'f', value: null } | ||
+ | }; | ||
− | + | // For Vertex and Fragment | |
− | + | birdUniforms = { | |
− | + | color: { type: "c", value: new THREE.Color( 0xff2200 ) }, | |
− | + | texturePosition: { type: "t", value: null }, | |
− | + | textureVelocity: { type: "t", value: null }, | |
+ | time: { type: "f", value: 1.0 }, | ||
+ | delta: { type: "f", value: 0.0 }, | ||
− | + | }; | |
− | + | ||
− | + | // ShaderMaterial | |
− | + | var shaderMaterial = new THREE.ShaderMaterial( { | |
− | + | uniforms: birdUniforms, | |
− | + | attributes: birdAttributes, | |
+ | vertexShader: document.getElementById( 'birdVS' ).textContent, | ||
+ | fragmentShader: document.getElementById( 'birdFS' ).textContent, | ||
+ | side: THREE.DoubleSide | ||
− | + | }); | |
− | + | ||
− | |||
− | |||
− | + | // var | |
− | + | birdMesh = new THREE.Mesh( geometry, shaderMaterial ); | |
− | + | birdMesh.rotation.y = Math.PI / 2; | |
+ | birdMesh.matrixAutoUpdate = false; | ||
+ | birdMesh.updateMatrix(); | ||
− | + | scene.add(birdMesh); | |
− | + | ||
− | + | ||
− | + | ||
− | + | } | |
− | + | 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 ); | requestAnimationFrame( animate ); | ||
− | |||
render(); | render(); | ||
+ | stats.update(); | ||
} | } | ||
Line 298: | Line 664: | ||
function render() { | function render() { | ||
− | var | + | var now = performance.now() |
+ | var delta = (now - last) / 1000; | ||
+ | |||
+ | if (delta > 1) delta = 1; // safety cap on large deltas | ||
+ | last = now; | ||
+ | |||
+ | birdUniforms.time.value = now; | ||
+ | birdUniforms.delta.value = delta; | ||
+ | |||
+ | simulator.simulate( delta ); | ||
+ | simulator.velocityUniforms.predator.value.set( mouseX / windowHalfX, -mouseY / windowHalfY, 0 ); | ||
+ | |||
+ | mouseX = 10000; | ||
+ | mouseY = 10000; | ||
− | |||
renderer.render( scene, camera ); | renderer.render( scene, camera ); | ||
Revision as of 22:17, 26 May 2015
<!DOCTYPE html>