1const shader = { 2 vertex: ` 3 // 4 // Description : Array and textureless GLSL 2D simplex noise function. 5 // Author : Ian McEwan, Ashima Arts. 6 // Maintainer : ijm 7 // Lastmod : 20110822 (ijm) 8 // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 9 // Distributed under the MIT License. See LICENSE file. 10 // https://github.com/ashima/webgl-noise 11 // 12 13 vec3 mod289(vec3 x) { 14 return x - floor(x * (1.0 / 289.0)) * 289.0; 15 } 16 17 vec2 mod289(vec2 x) { 18 return x - floor(x * (1.0 / 289.0)) * 289.0; 19 } 20 21 vec3 permute(vec3 x) { 22 return mod289(((x*34.0)+1.0)*x); 23 } 24 25 float snoise(vec2 v) 26 { 27 const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0 28 0.366025403784439, // 0.5*(sqrt(3.0)-1.0) 29 -0.577350269189626, // -1.0 + 2.0 * C.x 30 0.024390243902439); // 1.0 / 41.0 31 // First corner 32 vec2 i = floor(v + dot(v, C.yy) ); 33 vec2 x0 = v - i + dot(i, C.xx); 34 35 // Other corners 36 vec2 i1; 37 //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 38 //i1.y = 1.0 - i1.x; 39 i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); 40 // x0 = x0 - 0.0 + 0.0 * C.xx ; 41 // x1 = x0 - i1 + 1.0 * C.xx ; 42 // x2 = x0 - 1.0 + 2.0 * C.xx ; 43 vec4 x12 = x0.xyxy + C.xxzz; 44 x12.xy -= i1; 45 46 // Permutations 47 i = mod289(i); // Avoid truncation effects in permutation 48 vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) 49 + i.x + vec3(0.0, i1.x, 1.0 )); 50 51 vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); 52 m = m*m ; 53 m = m*m ; 54 55 // Gradients: 41 points uniformly over a line, mapped onto a diamond. 56 // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) 57 58 vec3 x = 2.0 * fract(p * C.www) - 1.0; 59 vec3 h = abs(x) - 0.5; 60 vec3 ox = floor(x + 0.5); 61 vec3 a0 = x - ox; 62 63 // Normalise gradients implicitly by scaling m 64 // Approximation of: m *= inversesqrt( a0*a0 + h*h ); 65 m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); 66 67 // Compute final noise value at P 68 vec3 g; 69 g.x = a0.x * x0.x + h.x * x0.y; 70 g.yz = a0.yz * x12.xz + h.yz * x12.yw; 71 return 130.0 * dot(m, g); 72 } 73 74 uniform float amplitude; 75 uniform float time; 76 attribute float id; 77 attribute float texId; 78 attribute float size; 79 attribute vec3 colour; 80 81 varying vec4 vColor; 82 varying float texIndex; 83 84 void main() { 85 if(size > 0.8) 86 { 87 texIndex = texId; 88 89 float a = (80.0-size)*0.01; 90 a = a > 1.0? 1.0: a; 91 a = a < 0.0? 0.0: a; 92 a *= (snoise(vec2(id, time*0.5))*0.5+0.5); 93 vColor = vec4(colour, a); 94 95 vec3 noise = vec3(snoise(vec2(id, time))*2.0, snoise(vec2(id, time + 10000.0))*2.0, 0.0); 96 97 vec4 mvPosition = modelViewMatrix * vec4( position + noise, 1.0 ); 98 99 gl_PointSize = size * 1.0 * ( 300.0 / length( mvPosition.xyz ) ) + 2.0; 100 101 gl_Position = projectionMatrix * mvPosition; 102 103 } 104 else 105 gl_PointSize = 0.0; 106 } 107 `, 108 fragment: ` 109 uniform vec3 color; 110 uniform sampler2D tex; 111 112 varying vec4 vColor; 113 114 void main() { 115 gl_FragColor = texture2D( tex, gl_PointCoord ); 116 } 117 ` 118}; 119 120class FPS { 121 startTime = Date.now(); 122 prevTime = this.startTime; 123 124 ms = 0; 125 msMin = Infinity; 126 msMax = 0; 127 fps = 0; 128 fpsMin = Infinity; 129 fpsMax = 0; 130 frames = 0; 131 132 begin = () => { 133 this.startTime = Date.now(); 134 }; 135 136 end = () => { 137 const time = Date.now(); 138 139 this.ms = time - this.startTime; 140 this.msMin = Math.min(this.msMin, this.ms); 141 this.msMax = Math.max(this.msMax, this.ms); 142 143 this.frames++; 144 145 if (time > this.prevTime + 1000) { 146 this.fps = Math.round((this.frames * 1000) / (time - this.prevTime)); 147 this.fpsMin = Math.min(this.fpsMin, this.fps); 148 this.fpsMax = Math.max(this.fpsMax, this.fps); 149 150 this.prevTime = time; 151 this.frames = 0; 152 } 153 154 return time; 155 }; 156 157 update = () => { 158 this.startTime = this.end(); 159 }; 160} 161 162class Particles { 163 frameId = null; 164 active = false; 165 fps = new FPS(); 166 currTime = 0; 167 mouseX = -10000; 168 mouseY = -10000; 169 windowHalfX = 0; 170 windowHalfY = 0; 171 renderer = null; 172 camera = null; 173 scene = null; 174 particles = null; 175 springStrength = 0.001; 176 mouseRadius = 5000; 177 mouseStrength = 0.2; 178 damping = 0.002; 179 imageParticlePositions = []; 180 shaderMaterial = null; 181 sourceImageW = 0;
182 sourceImageH = 0; 183 particleDensity = 1; 184 numToDraw = 0; 185 particleFadeTime = 0.01; 186 187 init = (canvas, particleData, sourceImageW, sourceImageH, options) => { 188 this.scale = (options && options.scale) || 0.5; 189 this.particleScale = (options && options.particleScale) || 1; 190 191 this.sourceImageW = sourceImageW; 192 this.sourceImageH = sourceImageH; 193 194 this.imageParticlePositions = particleData.trim().split(" "); 195 196 this.windowHalfX = window.innerWidth / 2; 197 this.windowHalfY = window.innerHeight / 2; 198 199 this.camera = new THREE.OrthographicCamera( 200 -this.windowHalfX, 201 this.windowHalfX, 202 -this.windowHalfY, 203 this.windowHalfY, 204 -500, 205 1000 206 ); 207 this.camera.position.z = 1000; 208 this.scene = new THREE.Scene(); 209 //scene.fog = new THREE.FogExp2(0x000000, 0.0008); 210 211 const uniforms = { 212 amplitude: { 213 type: "f", 214 value: 1.0 215 }, 216 time: { 217 type: "f", 218 value: 0 219 }, 220 color: { 221 type: "c", 222 value: new THREE.Color((options && options.particleColor) || "#fff") 223 }, 224 tex: { 225 type: "t", 226 value: new THREE.TextureLoader().load("/images/particle_2.jpg") 227 } 228 }; 229 230 this.shaderMaterial = new THREE.ShaderMaterial({ 231 uniforms: uniforms, 232 vertexShader: shader.vertex, 233 fragmentShader: shader.fragment, 234 235 blending: (options && options.blendMode) || THREE.SubtractiveBlending, 236 depthTest: false, 237 transparent: true 238 }); 239 240 this.setParticleDensity(1); 241 242 this.renderer = new THREE.WebGLRenderer({ canvas }); 243 this.renderer.setClearColor((options && options.backgroundColor) || "#fff"); 244 245 this.renderer.setPixelRatio(window.devicePixelRatio); 246 this.renderer.setSize(window.innerWidth, window.innerHeight); 247 248 document.addEventListener("mousemove", this.onDocumentMouseMove, false); 249 document.addEventListener("touchstart", this.onDocumentTouchStart, false); 250 document.addEventListener("touchend", this.onDocumentTouchEnd, false); 251 window.addEventListener("resize", this.onWindowResize, false); 252 253 this.start(); 254 }; 255 256 setParticleDensity = factor => { 257 const nParticles = Math.floor(this.imageParticlePositions.length * factor); 258 const geometry = new THREE.BufferGeometry(); 259 // geometry.dynamic = true; 260 261 const positions = new Float32Array(nParticles * 3); 262 const colours = new Float32Array(nParticles * 3); 263 const sizes = new Float32Array(nParticles); 264 const ids = new Float32Array(nParticles); 265 266 geometry.addAttribute("position", new THREE.BufferAttribute(positions, 3)); 267 geometry.addAttribute("colour", new THREE.BufferAttribute(colours, 3)); 268 geometry.addAttribute("size", new THREE.BufferAttribute(sizes, 1)); 269 geometry.addAttribute("id", new THREE.BufferAttribute(ids, 1)); 270 271 if (this.particles) this.scene.remove(this.particles); 272 this.particles = new THREE.Points(geometry, this.shaderMaterial); 273 274 const initPositions = []; 275 const initSizes = []; 276 const particleVelocities = []; 277 const particleActive = []; 278 279 for (let v = 0; v < nParticles; v++) { 280 const particleInfo = this.imageParticlePositions[v].split(","); 281 282 const vertex = new THREE.Vector3(); 283 vertex.x = 284 (parseInt(particleInfo[0]) - this.sourceImageW / 2) * this.scale; 285 vertex.y = 286 (parseInt(particleInfo[1]) - this.sourceImageH / 2) * this.scale; 287 //vertex.x = Math.random()*window.innerWidth-this.windowHalfX; 288 //vertex.y = Math.random()*window.innerHeight-this.windowHalfY; 289 vertex.z = 0; 290 291 initPositions.push(vertex.clone()); 292 particleVelocities.push(new THREE.Vector3()); 293 particleActive.push(0); 294 295 const size = (parseInt(particleInfo[2]) / 100) * 10 + 3; 296 initSizes.push(size); 297 298 positions[v * 3 + 0] = vertex.x; 299 positions[v * 3 + 1] = vertex.y; 300 positions[v * 3 + 2] = 0; 301 302 colours[v * 3 + 0] = 1; 303 colours[v * 3 + 1] = 1; 304 colours[v * 3 + 2] = 1; 305 306 sizes[v] = 0; 307 308 ids[v] = v; 309 } 310 311 this.particles.initPositions = initPositions; 312 this.particles.activeness = particleActive; 313 this.particles.initSizes = initSizes; 314 this.particles.positions = positions; 315 this.particles.velocities = particleVelocities; 316 this.particles.sizes = sizes; 317 318 this.scene.add(this.particles); 319 }; 320 321 onWindowResize = () => { 322 //this.windowHalfX = window.innerWidth / 2; 323 //this.windowHalfY = window.innerHeight / 2; 324 325 this.camera.aspect = window.innerWidth / window.innerHeight; 326 this.camera.updateProjectionMatrix(); 327 328 this.renderer.setSize(window.innerWidth, window.innerHeight); 329 }; 330 331 onDocumentMouseMove = event => { 332 this.mouseX = event.clientX - this.windowHalfX; 333 this.mouseY = event.clientY - this.windowHalfY; 334 }; 335 336 onDocumentTouchStart = event => { 337 this.mouseX = event.changedTouches[0].clientX - this.windowHalfX; 338 this.mouseY = event.changedTouches[0].clientY - this.windowHalfY; 339 console.log(event); 340 }; 341 342 onDocumentTouchEnd = event => { 343 this.mouseX = -9999; 344 this.mouseY = -9999; 345 }; 346 347 animate = () => { 348 this.frameId = requestAnimationFrame(this.animate); 349 this.render(); 350 }; 351 352 start = () => { 353 if (this.active) return; 354 this.active = true; 355 this.frameId = requestAnimationFrame(this.animate); 356 }; 357 358 stop = () => { 359 this.active = false;
360 cancelAnimationFrame(this.frameId); 361 }; 362 363 render = () => { 364 this.fps.update(); 365 366 if (this.particles === null) return; 367 368 if (this.fps.ms < 25) this.numToDraw += 1000; 369 else if (this.fps.ms > 50) this.numToDraw -= 1000; 370 371 this.numToDraw = Math.min( 372 Math.max(this.numToDraw, 0), 373 this.particles.initPositions.length 374 ); 375 376 //console.log(this.fps.ms); 377 // if(this.fps.fps < 20 && this.particleDensity !== 0.5){ 378 // this.particleDensity = 0.5; 379 // this.setParticleDensity(this.particleDensity); 380 // 381 // } 382 383 for (let i = 0; i < this.particles.initPositions.length; i++) { 384 if (i < this.numToDraw) { 385 if (this.particles.activeness[i] < 1) 386 this.particles.activeness[i] += this.particleFadeTime; 387 else this.particles.activeness[i] = 1; 388 } else { 389 if (this.particles.activeness[i] > 0) 390 this.particles.activeness[i] -= this.particleFadeTime; 391 else this.particles.activeness[i] = 0; 392 } 393 394 if (this.particles.activeness[i] > 0) { 395 const pos = new THREE.Vector3( 396 this.particles.positions[i * 3], 397 this.particles.positions[i * 3 + 1], 398 this.particles.positions[i * 3 + 2] 399 ); 400 401 //force toward starting point 402 const posToAnchor = new THREE.Vector3(); 403 posToAnchor.subVectors(pos, this.particles.initPositions[i]); 404 const force = posToAnchor.clone(); 405 force.multiplyScalar(-this.springStrength); 406 407 //damping force 408 const damp = new THREE.Vector3(); 409 damp.set( 410 this.particles.velocities[i].x, 411 this.particles.velocities[i].y, 412 this.particles.velocities[i].z 413 ); 414 damp.multiplyScalar(-this.damping); 415 // force.add(damp); 416 417 //force away from mouse 418 const d = new THREE.Vector3(); 419 d.subVectors(new THREE.Vector3(this.mouseX, this.mouseY, 0), pos); 420 const dMag = (d.x * d.x + d.y * d.y) * 0.05; 421 let strength; 422 if (dMag < this.mouseRadius) { 423 strength = Math.min(-this.mouseStrength / dMag, 0.05); 424 } else strength = 0; 425 426 d.multiplyScalar(strength); 427 force.add(d); 428 429 this.particles.velocities[i].add(force); 430 pos.add(this.particles.velocities[i]); 431 432 this.particles.positions[i * 3] = pos.x; 433 this.particles.positions[i * 3 + 1] = pos.y; 434 this.particles.positions[i * 3 + 2] = pos.z; 435 436 const distToAnchor = 437 posToAnchor.x * posToAnchor.x + posToAnchor.y * posToAnchor.y; 438 const size = Math.min( 439 Math.sin(distToAnchor / 500) * distToAnchor * 0.004 + 440 this.particles.initSizes[i], 441 100 442 ); 443 this.particles.sizes[i] = 444 size * this.particles.activeness[i] * this.particleScale; 445 } 446 } 447 448 this.currTime += 0.005; 449 this.particles.material.uniforms.time.value = this.currTime; 450 //Date.now() * 0.005; 451 452 this.particles.geometry.attributes.position.needsUpdate = true; 453 this.particles.geometry.attributes.size.needsUpdate = true; 454 455 //camera.position.z = mouseY; 456 457 this.renderer.render(this.scene, this.camera); 458 }; 459}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.