1const shader = `
2 // Heavily modified off of https://www.shadertoy.com/view/3sKGWw
3 // big thanks to these resources as well:
4 // https://youtu.be/3CycKKJiwis
5 // https://www.shadertoy.com/view/4djSRW
6 // https://www.shadertoy.com/view/3s3GDn
7
8 precision mediump float;
9 uniform vec2 u_resolution;
10 uniform float u_time;
11 uniform bool u_mask;
12
13 float random(vec2 p){
14 vec3 p3 = fract(vec3(p.xyx) * .1031);
15 p3 += dot(p3, p3.yzx + 33.33);
16 return fract((p3.x + p3.y) * p3.z);
17 }
18
19 vec2 random2(vec2 p){
20 vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
21 p3 += dot(p3, p3.yzx+33.33);
22 return fract((p3.xx+p3.yz)*p3.zy);
23 }
24
25 void main() {
26 float glow;
27 vec2 uv;
28 vec2 fl;
29 vec2 local_uv;
30 vec2 seed;
31 vec2 centre;
32 vec2 cell;
33 float t = u_time * 0.00015;
34 float blinkTime = u_time * 0.0068;
35 float rotationAngle = -t * 21.0;
36 mat2 rotation = mat2(cos(rotationAngle), -sin(rotationAngle),
37 sin(rotationAngle), cos(rotationAngle));
38 vec3 col = vec3(0);
39
40 centre = vec2(cos(t), sin(t)) * 5.0 + 0.5;
41
42 // Get uv from the fragment coordinates, rotation and depth
43 uv = (centre - (gl_FragCoord.xy - u_resolution / 2.0) / (1600.0 / 25.0)) * rotation;
44 fl = floor(uv);
45 // The local cell coordinates. uv-fl == frac(uv)
46 local_uv = uv - fl - 0.5;
47
48 // For a 3x3 group of cells around the fragment, find the distance from the points
49 // of each to the current fragment and draw an accumulative glow accordingly
50 // The local cell is (0, 0)
51 for(float j = -1.0; j <= 1.0; j++){
52 for(float k = -1.0; k <= 1.0; k++){
53 cell = vec2(j, k);
54 seed = 128.0 + (fl + cell);
55 glow =
56 ((0.6 + 0.5 * sin((128.0 * random(seed)) * blinkTime))) * 25.0
57 * pow(0.005 / length(local_uv - (cell + 0.9 * (random2(seed) - 0.5))), 2.0);
58 col += vec3(0.2 * glow) + 0.1 * glow;
59 }
60 }
61
62 col = 1.0 - exp(-col);
63 col = pow(col, vec3(0.45));
64
65 if (u_mask) {
66 float mask = smoothstep(100.0, 300.0, length(vec2(gl_FragCoord.x - u_resolution.x/2.0, gl_FragCoord.y - 200.0)));
67 col *= mask;
68 }
69
70 gl_FragColor = vec4(col * (u_mask ? 0.6 : 0.25), 0);
71 }
72`;
73
74function createShader(gl, type, source) {
75 const shader = gl.createShader(type);
76 gl.shaderSource(shader, source);
77 gl.compileShader(shader);
78 const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
79 if (success) {
80 return shader;
81 }
82
83 // eslint-disable-next-line no-console
84 console.error(gl.getShaderInfoLog(shader));
85 gl.deleteShader(shader);
86 throw new Error("Failed to compile shader");
87}
88
89function createProgram(gl, vertexShader, fragmentShader) {
90 const program = gl.createProgram();
91
92 gl.attachShader(program, vertexShader);
93 gl.attachShader(program, fragmentShader);
94 gl.linkProgram(program);
95
96 const success = gl.getProgramParameter(program, gl.LINK_STATUS);
97 if (success) {
98 return program;
99 }
100
101 // eslint-disable-next-line no-console
102 console.error(gl.getProgramInfoLog(program));
103 gl.deleteProgram(program);
104 throw new Error("Failed to link program");
105}