- const vert = `#version 300 es 
- layout(location = 0) in vec3 position; 
- out vec2 uv; 
- void main(void) {
-   uv = position.xy * 0.5 + 0.5; 
-   gl_Position = vec4(position, 1.0); 
- } 
- `; 
-   
- const frag1 = `#version 300 es 
- precision highp float; 
- uniform float time; 
- uniform float dx; 
- uniform float dy; 
-   
- float w2 = 1.0 / float(${innerWidth * 2});
- float w10 = 1.0 / (float(${innerWidth * 2}) * 100.); 
- float convert = 3.141592653589 / 180.; 
-   
- float sn; 
- float cs; 
-   
- out vec4 fragColor; 
-   
- void main(void) {
-   vec2 uv = gl_FragCoord.xy / vec2(float(${innerWidth * 2}), float(${innerHeight * 2}));
-   
-   float xp = uv.x * float(${innerWidth * 2});
-   float yp = (1. - uv.y) * float(${innerHeight * 2});
-   int x = 10 | 2; 
-   int xp2 = int(xp) << 1;  
-   float t = mod(float(int(yp) | int(xp + yp * .1) ) * (xp + dx) * (w10), 6.283185307179586); 
-   
-   if (t < 0.) {
-     sn = 1.27323954 * t + .405284735 * t * t;  
-   } else {
-     sn = 1.27323954 * t - 0.405284735 * t * t; 
-   } 
-   
-   t = mod(float( (xp2 | int(yp + xp * .1 + dy) )) * convert, 6.283185307179586); 
-   
-   t += 1.57079632; 
-   if (t > 3.14159265) {
-     t -= 6.28318531; 
-   } 
-   if (t < 0.) {
-     cs = 1.27323954 * t + 0.405284735 * t * t; 
-   } else {
-     cs = 1.27323954 * t - 0.405284735 * t * t; 
-   } 
-   
-   float c1 = 30. * (sn - cs); 
-   
-   if (c1 < 0.) c1 = 255. - c1; 
-   c1 = float((int(c1) << 4 | int(c1)) & 255) / 255.; 
-   
-   fragColor = vec4(c1, c1, c1, 1.0); 
- }  
- `; 
-   
- const frag2 = `#version 300 es 
- precision highp float; 
- in vec2 uv; 
-   
-   // The max kernel size (impacts performance) 
- #define maxKernel 1.0 
-   
- // The max offset (doesn't impact performance) 
- #define maxOffset 34.0 
- uniform sampler2D uTexture;  
-   
-   
- // https://www.shadertoy.com/view/mdGcRh 
- vec3 fastBlur(vec2 uv, vec2 texel, vec2 kd) 
- {
- float r = kd.x * kd.y; 
- float rr = 1.0/r; 
- vec3 col = vec3(0.0); 
- float a = 1.0; 
-   
- for (float x = -r; x <= r; x += kd.y) {       
- for (float y = -r; y <= r; y += kd.y)  {
- a++; 
- vec2 c = uv + vec2(x,y) * texel; 
- col += texture(uTexture, c + fract(sin(dot(c, vec2(12.9898, 78.233))) * 43758.5453) * texel * kd.y * 2.0 - kd.yy * texel).rgb * (2.0 - distance(vec2(x,y) * rr, vec2(0.0)));  
- } 
- } 
-   
- return col / a; 
- } 
-   
-   
- out vec4 fragColor; 
- void main(void) {
-   vec4 color = texture(uTexture, uv); 
-   vec4 colorB = texture(uTexture, vec2(uv.x, 1. - uv.y)); 
-   vec3 result = (color.rgb - colorB.rgb) * 1.2; 
-   
-     float amt = .4; 
-     vec2 texel = vec2(1.0)/ vec2(float(${innerWidth * 2}), float(${innerHeight * 2}));
-   
-     vec2 kd = round(vec2(amt * maxKernel + 1.0, amt * maxOffset + 1.0)); 
-   
-     vec3 blur = fastBlur(uv, texel, kd); 
-   
-   fragColor = vec4(result, color.a); 
- } 
- `; 
-   
-   const frag3 = `#version 300 es 
- precision highp float; 
- in vec2 uv; 
-   
-   // The max kernel size (impacts performance) 
- #define maxKernel 4.0 
-   
- // The max offset (doesn't impact performance) 
- #define maxOffset 34.0 
- uniform sampler2D uTexture;  
-   
-   
- // https://www.shadertoy.com/view/mdGcRh 
- vec3 fastBlur(vec2 uv, vec2 texel, vec2 kd) 
- {
- float r = kd.x * kd.y; 
- float rr = 1.0/r; 
- vec3 col = vec3(0.0); 
- float a = 1.0; 
-   
- for (float x = -r; x <= r; x += kd.y) {       
- for (float y = -r; y <= r; y += kd.y)  {
- a++; 
-       vec2 c = uv + vec2(x,y) * texel; 
-   
-       col += texture( 
-   
-       uTexture,  
-   
-       c  
-       + fract(sin(dot(c, vec2(2.9898, 78.233))) * 13758.5453) * texel * kd.y * 2.4 
-       - kd.yy * texel 
-   
-       ).rgb * (2.0 - distance(vec2(x,y) * rr, vec2(0.0))); 
- } 
- } 
-   
- return col / a; 
- } 
-   
-   
- out vec4 fragColor; 
- void main(void) {
-   vec4 color = texture(uTexture, uv); 
-   
-     float amt = .4; 
-     vec2 texel = vec2(1.0)/ vec2(float(${innerWidth * 2}), float(${innerHeight * 2}));
-   
-     vec2 kd = round(vec2(amt * maxKernel + 1.0, amt * maxOffset + 1.0)); 
-   
-   vec4 blur = vec4(fastBlur(uv, texel, kd), 1.); 
-     //1-(1-A)*(1-B) 
-   vec3 f = 1. - (1. - color.rgb) * (1. - blur.rgb);   
-   
-   
-   fragColor = vec4(f.rgb, 1.); 
- }  
- `; 
-   
-   
-   
- document.body.style.background = '#000'; 
- const gl = document.body 
-   .appendChild(document.createElement('canvas'))
-   .getContext('webgl2');
-   
- Object.assign(gl.canvas.style, {
-   position: 'absolute', 
-   left: 0, 
-   top: 0 
- }); 
-   
- const s = 1; 
- const verts = new Float32Array([ 
-   -s, -s, 0, 
-   s, -s, 0, 
-   -s, s, 0, 
-   s, s, 0, 
- ]); 
-   
- const buffer = gl.createBuffer(); 
- gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 
- gl.bufferData(gl.ARRAY_BUFFER, verts, gl.STATIC_DRAW); 
-   
- function createShaderProgram(vertexSource, fragmentSource) {
-   const vs = gl.createShader(gl.VERTEX_SHADER); 
-   gl.shaderSource(vs, vertexSource); 
-   gl.compileShader(vs); 
-   
-   const fs = gl.createShader(gl.FRAGMENT_SHADER); 
-   gl.shaderSource(fs, fragmentSource); 
-   gl.compileShader(fs); 
-   
-   const program = gl.createProgram(); 
-   gl.attachShader(program, vs); 
-   gl.attachShader(program, fs); 
-   gl.linkProgram(program); 
-   
-   if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
-     console.error('Could not link program:', gl.getProgramInfoLog(program));
-   } 
-   
-   return program; 
- } 
-   
- const program1 = createShaderProgram(vert, frag1); 
- const program2 = createShaderProgram(vert, frag2); 
- const program3 = createShaderProgram(vert, frag3); 
-   
- const framebuffer1 = gl.createFramebuffer(); 
- const framebuffer2 = gl.createFramebuffer(); 
- const texture1 = gl.createTexture(); 
- const texture2 = gl.createTexture(); 
-   
- gl.bindTexture(gl.TEXTURE_2D, texture1); 
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, innerWidth, innerHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 
-   
- gl.bindTexture(gl.TEXTURE_2D, texture2); 
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, innerWidth, innerHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 
-   
- gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer1); 
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture1, 0); 
-   
- gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer2); 
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture2, 0); 
-   
- const onResize = () => {
-   gl.canvas.width = innerWidth * 2; 
-   gl.canvas.height = innerHeight * 2; 
-   gl.canvas.style.width = innerWidth + 'px' 
-   gl.canvas.style.height = innerHeight + 'px' 
-   gl.viewport(0, 0, innerWidth * 2, innerHeight * 2); 
-   gl.bindTexture(gl.TEXTURE_2D, texture1); 
-   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, innerWidth * 2, innerHeight * 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 
-   gl.bindTexture(gl.TEXTURE_2D, texture2); 
-   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, innerWidth * 2, innerHeight * 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 
- }; 
-   
- window.onresize = onResize; 
- onResize(); 
-   
- gl.disable(gl.DEPTH_TEST); 
-   
- let mx = 0; 
- let my = 0; 
- let dx = 0; 
- let dy = 0; 
-   
- window.onpointermove = e => {
-   mx = e.clientX; 
-   my = e.clientY; 
- }; 
-   
- const loop = () => {
-   
-   dx += (mx * 2 - (innerWidth) - dx) / 8; 
-   dy += (my * 2 - dy) / 8; 
-   
-   // first pass 
-   gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer1); 
-   gl.useProgram(program1); 
-   
-   const mxUniform = gl.getUniformLocation(program1, 'dx'); 
-   gl.uniform1f(mxUniform, dx); 
-   
-   const myUniform = gl.getUniformLocation(program1, 'dy'); 
-   gl.uniform1f(myUniform, dy); 
-   
-   gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 
-   const pos1 = gl.getAttribLocation(program1, 'position'); 
-   gl.enableVertexAttribArray(pos1); 
-   gl.vertexAttribPointer(pos1, 3, gl.FLOAT, false, 0, 0); 
-   gl.clearColor(0, 0, 0, 1); 
-   gl.clear(gl.COLOR_BUFFER_BIT); 
-   gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
-   
-   // second pass 
-   gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer2); 
-   gl.useProgram(program2); 
-   gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 
-   const pos2 = gl.getAttribLocation(program2, 'position'); 
-   gl.enableVertexAttribArray(pos2); 
-   gl.vertexAttribPointer(pos2, 3, gl.FLOAT, false, 0, 0); 
-   const uTexture = gl.getUniformLocation(program2, 'uTexture'); 
-   gl.uniform1i(uTexture, 0); 
-   gl.activeTexture(gl.TEXTURE0); 
-   gl.bindTexture(gl.TEXTURE_2D, texture1); 
-   gl.clearColor(0, 0, 0, 1); 
-   gl.clear(gl.COLOR_BUFFER_BIT); 
-   gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
-   
-   // third pass 
-   gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
-   gl.useProgram(program3); 
-   gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 
-   const pos3 = gl.getAttribLocation(program3, 'position'); 
-   gl.enableVertexAttribArray(pos3); 
-   gl.vertexAttribPointer(pos3, 3, gl.FLOAT, false, 0, 0); 
-   const u2Texture = gl.getUniformLocation(program3, 'uTexture'); 
-   gl.uniform1i(u2Texture, 0); 
-   gl.activeTexture(gl.TEXTURE0); 
-   gl.bindTexture(gl.TEXTURE_2D, texture2); 
-   gl.clearColor(0, 0, 0, 1); 
-   gl.clear(gl.COLOR_BUFFER_BIT); 
-   gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);  
-   
-   requestAnimationFrame(loop); 
- }; 
- loop();