GLSL Sierpiński Glitch Texture #3
- 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(); 
this old thing was tricky to port to glsl, canvas port was easy (codepen here) – used gpt a bit for glsl version… got it eventually: take a look