PageSourceSearch

https://www.scientology-denmark.org/js-static/ias-2023/particles.js?_=

js scientology-denmark.org collected 2026-10-07 20:00:09 UTC 17,045 bytes, 582 lines download raw bytes

1class Particles {
2	
3	constructor(webgl) {
4		this.webgl = webgl;
5		this.container = new THREE.Object3D();
6	}
7
8	init(src) {
9		const loader = new THREE.TextureLoader();
10
11		loader.load(src, (texture) => {
12			this.texture = texture;
13			this.texture.minFilter = THREE.LinearFilter;
14			this.texture.magFilter = THREE.LinearFilter;
15			this.texture.format = THREE.RGBFormat;
16
17			this.width = texture.image.width;
18			this.height = texture.image.height;
19
20			// hardcoded to improve browser compatibility
21			this.width = 151;
22			this.height = 150;
23
24			this.initPoints(true);
25			this.initHitArea();
26			this.initTouch();
27			this.resize();
28			this.show();
29		});
30
31		var self = this;
32
33		$(window).resize(function(){
34			setTimeout(function(){
35				self.resize();
36			}, 500);
37		});
38	}
39
40	initPoints(discard) {
41		this.numPoints = this.width * this.height;
42
43		let numVisible = this.numPoints;
44		let threshold = 0;
45		let originalColors;
46
47		if (discard ) {
48			// discard pixels darker than threshold #22
49			numVisible = 0;
50			threshold = 34;
51
52			const img = this.texture.image;
53			const canvas = document.createElement('canvas');
54			const ctx = canvas.getContext('2d');
55
56			canvas.width = this.width;
57			canvas.height = this.height;
58			ctx.scale(1, -1);
59			ctx.drawImage(img, 0, 0, this.width, this.height * -1);
60
61			const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
62			originalColors = Float32Array.from(imgData.data);
63
64			for (let i = 0; i < this.numPoints; i++) {
65				if (originalColors[i * 4 + 0] > threshold) numVisible++;
66			}
67
68			// console.log('numVisible', numVisible, this.numPoints);
69		}
70
71		const uniforms = {
72			uTime: { value: 0 },
73			uRotation: { value: this.getThreejsVector(0) },
74			uRandom: { value: 1.0 },
75			uDepth: { value: 2.0 },
76			uDepthModifier: { value: 0.0 },
77			uSize: { value: 0.0 },
78			uSizeDescrease: { value: 0.0 },
79			uTextureSize: { value: new THREE.Vector2(this.width, this.height) },
80			uResolution: { value: new THREE.Vector2(this.webgl.renderer.domElement.width, this.webgl.renderer.domElement.height) },
81			uTexture: { value: this.texture },
82			uTouch: { value: null },
83		};
84
85		const material = new THREE.RawShaderMaterial({
86			uniforms,
87			vertexShader: vertexShader,
88			fragmentShader: fragmentShader,
89			depthTest: false,
90			transparent: true,
91			blending: THREE.AdditiveBlending
92		});
93
94		const geometry = new THREE.InstancedBufferGeometry();
95
96		// positions
97		const positions = new THREE.BufferAttribute(new Float32Array(4 * 3), 3);
98		positions.setXYZ(0, -0.5,  0.5,  0.0);
99		positions.setXYZ(1,  0.5,  0.5,  0.0);
100		positions.setXYZ(2, -0.5, -0.5,  0.0);
101		positions.setXYZ(3,  0.5, -0.5,  0.0);
102		geometry.addAttribute('position', positions);
103
104		// uvs
105		const uvs = new THREE.BufferAttribute(new Float32Array(4 * 2), 2);
106		uvs.setXYZ(0,  0.0,  0.0);
107		uvs.setXYZ(1,  1.0,  0.0);
108		uvs.setXYZ(2,  0.0,  1.0);
109		uvs.setXYZ(3,  1.0,  1.0);
110		geometry.addAttribute('uv', uvs);
111
112		// index
113		geometry.setIndex(new THREE.BufferAttribute(new Uint16Array([ 0, 2, 1, 2, 3, 1 ]), 1));
114
115		const indices = new Uint16Array(numVisible);
116		const offsets = new Float32Array(numVisible * 3);
117		const angles = new Float32Array(numVisible);
118
119		for (let i = 0, j = 0; i < this.numPoints; i++) {
120			if (discard && originalColors[i * 4 + 0] <= threshold) continue;
121
122			offsets[j * 3 + 0] = i % this.width;
123			offsets[j * 3 + 1] = Math.floor(i / this.width);
124
125			indices[j] = i;
126
127			angles[j] = Math.random() * Math.PI;
128
129			j++;
130		}
131
132		geometry.addAttribute('pindex', new THREE.InstancedBufferAttribute(indices, 1, false));
133		geometry.addAttribute('offset', new THREE.InstancedBufferAttribute(offsets, 3, false));
134		geometry.addAttribute('angle', new THREE.InstancedBufferAttribute(angles, 1, false));
135
136		this.object3D = new THREE.Mesh(geometry, material);
137		this.container.add(this.object3D);
138	}
139
140	getThreejsVector(angleInDegrees) {
141		const angleInRadians = angleInDegrees * Math.PI / 180;
142		const s = Math.sin(angleInRadians);
143		const c = Math.cos(angleInRadians);
144		return new THREE.Vector2(s, c);
145	}
146
147	initTouch() {
148		// create only once
149		// if (!this.touch) this.touch = new TouchTexture(this);
150		// this.object3D.material.uniforms.uTouch.value = this.touch.texture;
151	}
152
153	initHitArea() {
154		const geometry = new THREE.PlaneGeometry(this.width, this.height, 1, 1);
155		const material = new THREE.MeshBasicMaterial({ color: 0xFFFFFF, wireframe: true, depthTest: false });
156		material.visible = false;
157		this.hitArea = new THREE.Mesh(geometry, material);
158		this.container.add(this.hitArea);
159	}
160
161	addListeners() {
162		this.handlerInteractiveMove = this.onInteractiveMove.bind(this);
163
164		if(!this.webgl.interactive) {
165			return;
166		}
167		this.webgl.interactive.addListener('interactive-move', this.handlerInteractiveMove);
168		this.webgl.interactive.objects.push(this.hitArea);
169		this.webgl.interactive.enable();
170	}
171
172	removeListeners() {
173		if(!this.webgl.interactive) {
174			return;
175		}
176		this.webgl.interactive.removeListener('interactive-move', this.handlerInteractiveMove);
177		const index = this.webgl.interactive.objects.findIndex(obj => obj === this.hitArea);
178		this.webgl.interactive.objects.splice(index, 1);
179		this.webgl.interactive.disable();
180	}
181
182	// ---------------------------------------------------------------------------------------------
183	// PUBLIC
184	// ---------------------------------------------------------------------------------------------
185
186	update(delta) {
187		if (!this.object3D) return;
188		// if (this.touch) this.touch.update();
189
190		this.object3D.material.uniforms.uTime.value += delta;
191	}
192
193	show(time = 1.0) {
194		var self = this;
195		// reset
196		var targetParticleSize = 0.5;
197		gsap.fromTo(this.object3D.material.uniforms.uSize, { duration: time, value: targetParticleSize }, { value: targetParticleSize });
198		gsap.to(this.object3D.material.uniforms.uRandom, { duration: time, value: 0.5 });
199		
200		var container = this.webgl.app.container;
201
202		
203		var tlIn = gsap.timeline({
204			scrollTrigger: {
205				trigger: container.querySelector(".ias-2023-4d-logo-inner"),
206				start: "bottom bottom",
207				pin: true,
208				pinSpacing: false,
209				endTrigger: container.querySelector('.ias-2023-image-grid-title'),
210				// end: "top-=60% center",
211				end: "top center",  // [trigger] [scroller] positions
212				scrub: true,
213				//  markers: true,
214				invalidateOnRefresh: true, // invalidate on resize
215			}
216		});
217
218		tlIn.fromTo(container.querySelector(".ias-2023-4d-logo-holder"), time * 0.7, { autoAlpha: 0 }, { autoAlpha: 1.0 }, 0);
219		tlIn.fromTo(this.object3D.material.uniforms.uDepth, time, { value: 4*150.0 }, { value: 4.0 }, 0);
220		
221		var rotationObj = {
222			value: 180
223		};
224
225		tlIn.fromTo(rotationObj, time, {
226			value: 180
227		}, {
228			value: 0,
229			onUpdate() {
230				self.object3D.material.uniforms.uRotation.value = self.getThreejsVector(rotationObj.value);
231			}
232		}, 0);
233
234		tlIn.fromTo(container.querySelector(".ias-2023-4d-logo"), { duration: 0.3, opacity: 0 }, { opacity: 1 }, "-=0.3");
235
236		// timeline out
237		var tlOut = gsap.timeline({
238			scrollTrigger: {
239				trigger: container.querySelector('.ias-2023-image-grid-wrapper'),
240				start: "top bottom", // trigger, scroller
241				endTrigger: container.querySelector('.ias-2023-image-grid-overlay'),
242				// end: "top bottom",
243				pinnedContainer: container.querySelector(".ias-2023-4d-logo-inner"),
244				// pin: container.querySelector(".ias-2023-4d-logo-inner"),
245				pinSpacing: false,
246				end: "bottom top",
247				scrub: true,
248				// markers: true,
249				invalidateOnRefresh: true, // invalidate on resize
250			}
251		});
252
253		// pin
254		gsap.timeline({
255			scrollTrigger: {
256				trigger: container.querySelector('.ias-2023-image-grid-wrapper'),
257				start: "top-=25% bottom", // trigger, scroller
258				endTrigger: $(container).next()[0],
259				// endTrigger: container.querySelector('.ias-2023-image-grid-overlay'),
260				end: "bottom bottom",
261				// pinnedContainer: container.querySelector(".ias-2023-4d-logo-inner"),
262				// pin: container.querySelector(".ias-2023-4d-logo-positioner"),
263				pinnedContainer: container.querySelector(".ias-2023-4d-logo-inner"),
264				pin: container.querySelector(".ias-2023-4d-logo-inner"),
265				// pin: container.querySelector(".ias-2023-4d-logo-wrapper"),
266				pinSpacing: false,
267				scrub: true,
268				//  markers: true,
269				invalidateOnRefresh: true, // invalidate on resize
270			}
271		});
272
273		tlOut.fromTo(this.object3D.material.uniforms.uDepthModifier, time, { value: 0.0 }, { value: 150.0 });
274		tlOut.fromTo(rotationObj, time, {
275			value: 0
276		}, {
277			value: -180,
278			onUpdate() {
279				self.object3D.material.uniforms.uRotation.value = self.getThreejsVector(rotationObj.value);
280			}
281		}, 0);
282		tlOut.fromTo(container.querySelector(".ias-2023-4d-logo img"), time*0.1, {opacity: 1}, { opacity: 0 }, 0);
283		tlOut.fromTo(container.querySelector('.ias-2023-4d-logo-positioner'), time*0.2, {y: 0}, {y: "30%"});
284		tlOut.fromTo(this.object3D.material.uniforms.uSizeDescrease, time, { value: 0 }, { value: targetParticleSize * 0.8 }, 0);
285		
286		window.timelines = window.timelines || [];
287		window.timelines.push(tlOut);
288
289		this.addListeners();
290	}
291
292	// hide(_destroy, time = 0.8) {
293	// 	return new Promise((resolve, reject) => {
294	// 		TweenLite.to(this.object3D.material.uniforms.uRandom, time, { value: 5.0, onComplete: () => {
295	// 			if (_destroy) this.destroy();
296	// 			resolve();
297	// 		} });
298	// 		TweenLite.to(this.object3D.material.uniforms.uDepth, time, { value: -20.0, ease: Quad.easeIn });
299	// 		TweenLite.to(this.object3D.material.uniforms.uSize, time * 0.8, { value: 0.0 });
300
301	// 		this.removeListeners();
302	// 	});
303	// }
304
305	destroy() {
306		if (!this.object3D) return;
307
308		this.object3D.parent.remove(this.object3D);
309		this.object3D.geometry.dispose();
310		this.object3D.material.dispose();
311		this.object3D = null;
312
313		if (!this.hitArea) return;
314
315		this.hitArea.parent.remove(this.hitArea);
316		this.hitArea.geometry.dispose();
317		this.hitArea.material.dispose();
318		this.hitArea = null;
319	}
320
321	// ---------------------------------------------------------------------------------------------
322	// EVENT HANDLERS
323	// ---------------------------------------------------------------------------------------------
324
325	resize() {
326		if (!this.object3D) return;
327		var scale = this.webgl.fovHeight / this.height * 0.4;
328		if(this.webgl.app.container.querySelector('.ias-2023-4d-logo__human-rights')) {
329			scale = this.webgl.fovHeight / this.height * 0.43;
330		}
331		if($(window).width() <= 1024) {
332			scale = this.webgl.fovHeight / this.height * 0.45;
333		}
334		if($(window).width() < 992) {
335			var windowHeight = Math.max(window.innerHeight || 0, window.outerHeight || 0
335);
336			scale = this.webgl.fovHeight / this.height / windowHeight * 250;
337		}
338
339		this.object3D.scale.set(scale, scale, 1);
340		this.hitArea.scale.set(scale, scale, 1);
341		this.object3D.material.uniforms.uResolution.value.x = this.webgl.renderer.domElement.width;
342		this.object3D.material.uniforms.uResolution.value.y = this.webgl.renderer.domElement.height;
343	}
344
345	onInteractiveMove(e) {
346		const uv = e.intersectionData.uv;
347		// if (this.touch) this.touch.addTouch(uv);
348	}
349}
350
351var vertexShader = `// @author brunoimbrizi / http://brunoimbrizi.com
352
353precision highp float;
354#define GLSLIFY 1
355
356attribute float pindex;
357attribute vec3 position;
358attribute vec3 offset;
359attribute vec2 uv;
360attribute float angle;
361
362uniform mat4 modelViewMatrix;
363uniform mat4 projectionMatrix;
364
365uniform float uTime;
366uniform float uRandom;
367uniform float uDepth;
368uniform float uDepthModifier;
369uniform float uSize;
370uniform float uSizeDescrease;
371uniform vec2 uTextureSize;
372uniform sampler2D uTexture;
373uniform sampler2D uTouch;
374uniform vec2 uRotation;
375
376varying vec2 vPUv;
377varying vec2 vUv;
378
379//
380// Description : Array and textureless GLSL 2D simplex noise function.
381//      Author : Ian McEwan, Ashima Arts.
382//  Maintainer : ijm
383//     Lastmod : 20110822 (ijm)
384//     License : Copyright (C) 2011 Ashima Arts. All rights reserved.
385//               Distributed under the MIT License. See LICENSE file.
386//               https://github.com/ashima/webgl-noise
387//
388
389vec3 mod289_1_0(vec3 x) {
390      return x - floor(x * (1.0 / 289.0)) * 289.0;
391}
392
393vec2 mod289_1_0(vec2 x) {
394      return x - floor(x * (1.0 / 289.0)) * 289.0;
395}
396
397vec3 permute_1_1(vec3 x) {
398      return mod289_1_0(((x*34.0)+1.0)*x);
399}
400
401float snoise_1_2(vec2 v)
402  {
403      const vec4 C = vec4(0.211324865405187,  // (3.0-sqrt(3.0))/6.0
404                      0.366025403784439,  // 0.5*(sqrt(3.0)-1.0)
405                     -0.577350269189626,  // -1.0 + 2.0 * C.x
406                      0.024390243902439); // 1.0 / 41.0
407// First corner
408  vec2 i  = floor(v + dot(v, C.yy) );
409  vec2 x0 = v -   i + dot(i, C.xx);
410
411// Other corners
412  vec2 i1;
413  //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
414  //i1.y = 1.0 - i1.x;
415  i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
416  // x0 = x0 - 0.0 + 0.0 * C.xx ;
417  // x1 = x0 - i1 + 1.0 * C.xx ;
418  // x2 = x0 - 1.0 + 2.0 * C.xx ;
419  vec4 x12 = x0.xyxy + C.xxzz;
420  x12.xy -= i1;
421
422// Permutations
423  i = mod289_1_0(i); // Avoid truncation effects in permutation
424  vec3 p = permute_1_1( permute_1_1( i.y + vec3(0.0, i1.y, 1.0 ))
425    + i.x + vec3(0.0, i1.x, 1.0 ));
426
427  vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
428  m = m*m ;
429  m = m*m ;
430
431// Gradients: 41 points uniformly over a line, mapped onto a diamond.
432// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
433
434  vec3 x = 2.0 * fract(p * C.www) - 1.0;
435  vec3 h = abs(x) - 0.5;
436  vec3 ox = floor(x + 0.5);
437  vec3 a0 = x - ox;
438
439// Normalise gradients implicitly by scaling m
440// Approximation of: m *= inversesqrt( a0*a0 + h*h );
441  m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
442
443// Compute final noise value at P
444  vec3 g;
445  g.x  = a0.x  * x0.x  + h.x  * x0.y;
446  g.yz = a0.yz * x12.xz + h.yz * x12.yw;
447  return 130.0 * dot(m, g);
448}
449
450
451
452float random(float n) {
453        return fract(sin(n) * 43758.5453123);
454}
455
456vec2 adjustRotation33(vec2 rotation, float displacedZ) {
457
458	vec2 target = vec2(0.0, 1.0);
459	
460	float dist = abs(displacedZ);
461	
462	vec2 diff = rotation - target;
463	
464	vec2 adjusted = mix(rotation, target, smoothstep(0.0, 1.0, dist)); 
465	
466	return adjusted;
467  
468  }
469
470  vec2 adjustRotation(vec2 uRotation, float displacedZ) {
471
472	float targetZ = 0.0; // Target z coordinate value
473	vec2 targetRotation = vec2(0.0, 1.0); // Target rotation
474
475	// Calculate the weight based on the proximity of displacedZ to targetZ
476	// float weight = 1.0 - abs(displacedZ - targetZ);
477	float weight = 1.0 - smoothstep(0.0, 50.0, abs(displacedZ - targetZ));
478
479	// Interpolate uRotation towards the target rotation
480	vec2 adjusted = mix(uRotation, targetRotation, weight);
481  
482	return adjusted;
483  
484  }
485
486void main() {
487        vUv = uv;
488
489    // particle uv
490    vec2 puv = offset.xy / uTextureSize;
491    vPUv = puv;
492
493    // pixel color
494    vec4 colA = texture2D(uTexture, puv);
495    float grey = colA.r * 0.21 + colA.g * 0.71 + colA.b * 0.07;
496    //float grey = colA.r + colA.g + colA.b;
497
498    // displacement
499    vec3 displaced = offset;
500    // randomise
501    displaced.xy += vec2(random(pindex) - 0.5, random(offset.x + pindex) - 0.5) * uRandom;
502    // float rndz = (random(pindex) + snoise_1_2(vec2(pindex * 0.1, uTime * 0.1)));
503    float rndz = (random(pindex) + snoise_1_2(vec2(pindex * 0.01, uTime * 0.005)));
504      displaced.z += rndz * (random(pindex) * 2.0 * (uDepth + uDepthModifier));
505	// displaced.z += rndz * (2.0 * uDepth);
506    // center
507    displaced.xy -= uTextureSize * 0.5;
508
509    // touch
510    float t = texture2D(uTouch, puv).r;
511    displaced.z += t * 20.0 * rndz;
512    displaced.x += cos(angle) * t * 20.0 * rndz;
513    displaced.y += sin(angle) * t * 20.0 * rndz;
514
515    // particle size
516    float psize = (snoise_1_2(vec2(uTime, pindex) * 0.5) + 2.0);
517    psize *= max(grey, 0.2);
518    psize *= (uSize - uSizeDescrease);
519
520	// Interpolate uRotation towards the target rotation
521	vec2 rotation = adjustRotation(uRotation, displaced.z);
522	 // vec2 rotation = uRotation;
523	
524	//  rotate
525	displaced = vec3(
526		displaced.x * rotation.y + displaced.y * rotation.x,
527		displaced.y * rotation.y - displaced.x * rotation.x,
528		displaced.z);
529
530    // final position
531    vec4 mvPosition = modelViewMatrix * vec4(displaced, 1.0);
532    mvPosition.xyz += position * psize;
533    vec4 finalPosition = projectionMatrix * mvPosition;
534
535
536    gl_Position = finalPosition;
537}
538
539`;
540
541
542var fragmentShader = `// @author brunoimbrizi / http://brunoimbrizi.com
543
544precision highp float;
545
546uniform sampler2D uTexture;
547uniform vec2 uResolution;
548
549
550varying vec2 vPUv;
551varying vec2 vUv;
552
553void main() {
554	vec4 color = vec4(0.0);
555	vec2 uv = vUv;
556	vec2 puv = vPUv;
557
558	// pixel color
559	vec4 colA = texture2D(uTexture, puv);
560
561	// greyscale
562	//float grey = colA.r * 0.21 + colA.g * 0.71 + colA.b * 0.07;
563	//vec4 colB = vec4(grey, grey, grey, 1.0);
564
565	// circle
566	float border = 0.5;
567	float radius = 0.5;
568	float dist = radius - distance(uv, vec2(0.5));
569	float t = smoothstep(0.0, border, dist);
570
571	// vec2 position = gl_FragCoord.xy / uResolution;
572	vec2 position = gl_FragCoord.xy / uResolution;
573  
574	// Fade out particles near the top
575	float fade = 1.0 - smoothstep(0.8, 1.0, position.y);
576
577	// final color
578	color = colA * fade;
579	color.a = t;
580
581	gl_FragColor = color;
582}`;

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.