)
}
}
)
(
}
{
)
)
(
)
(
(
{
}
)
(
)
}
)
)
{
(
(
)
)
}
)
(
}

GLSL Sierpiński Glitch Texture #3

  1. const vert = `#version 300 es
  2. layout(location = 0) in vec3 position;
  3. out vec2 uv;
  4. void main(void) {
  5.   uv = position.xy * 0.5 + 0.5;
  6.   gl_Position = vec4(position, 1.0);
  7. }
  8. `;
  9.  
  10. const frag1 = `#version 300 es
  11. precision highp float;
  12. uniform float time;
  13. uniform float dx;
  14. uniform float dy;
  15.  
  16. float w2 = 1.0 / float(${innerWidth * 2});
  17. float w10 = 1.0 / (float(${innerWidth * 2}) * 100.); 
  18. float convert = 3.141592653589 / 180.;
  19.  
  20. float sn;
  21. float cs;
  22.  
  23. out vec4 fragColor;
  24.  
  25. void main(void) {
  26.   vec2 uv = gl_FragCoord.xy / vec2(float(${innerWidth * 2}), float(${innerHeight * 2}));
  27.  
  28.   float xp = uv.x * float(${innerWidth * 2});
  29.   float yp = (1. - uv.y) * float(${innerHeight * 2});
  30.   int x = 10 | 2;
  31.   int xp2 = int(xp) << 1; 
  32.   float t = mod(float(int(yp) | int(xp + yp * .1) ) * (xp + dx) * (w10), 6.283185307179586);
  33.  
  34.   if (t < 0.) {
  35.     sn = 1.27323954 * t + .405284735 * t * t; 
  36.   } else {
  37.     sn = 1.27323954 * t - 0.405284735 * t * t;
  38.   }
  39.  
  40.   t = mod(float( (xp2 | int(yp + xp * .1 + dy) )) * convert, 6.283185307179586);
  41.  
  42.   t += 1.57079632;
  43.   if (t > 3.14159265) {
  44.     t -= 6.28318531;
  45.   }
  46.   if (t < 0.) {
  47.     cs = 1.27323954 * t + 0.405284735 * t * t;
  48.   } else {
  49.     cs = 1.27323954 * t - 0.405284735 * t * t;
  50.   }
  51.  
  52.   float c1 = 30. * (sn - cs);
  53.  
  54.   if (c1 < 0.) c1 = 255. - c1;
  55.   c1 = float((int(c1) << 4 | int(c1)) & 255) / 255.;
  56.  
  57.   fragColor = vec4(c1, c1, c1, 1.0);
  58. } 
  59. `;
  60.  
  61. const frag2 = `#version 300 es
  62. precision highp float;
  63. in vec2 uv;
  64.  
  65.   // The max kernel size (impacts performance)
  66. #define maxKernel 1.0
  67.  
  68. // The max offset (doesn't impact performance)
  69. #define maxOffset 34.0
  70. uniform sampler2D uTexture; 
  71.  
  72.  
  73. // https://www.shadertoy.com/view/mdGcRh
  74. vec3 fastBlur(vec2 uv, vec2 texel, vec2 kd)
  75. {
  76. float r = kd.x * kd.y;
  77. float rr = 1.0/r;
  78. vec3 col = vec3(0.0);
  79. float a = 1.0;
  80.  
  81. for (float x = -r; x <= r; x += kd.y) {       
  82. for (float y = -r; y <= r; y += kd.y)  {
  83. a++;
  84. vec2 c = uv + vec2(x,y) * texel;
  85. 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))); 
  86. }
  87. }
  88.  
  89. return col / a;
  90. }
  91.  
  92.  
  93. out vec4 fragColor;
  94. void main(void) {
  95.   vec4 color = texture(uTexture, uv);
  96.   vec4 colorB = texture(uTexture, vec2(uv.x, 1. - uv.y));
  97.   vec3 result = (color.rgb - colorB.rgb) * 1.2;
  98.  
  99.     float amt = .4;
  100.     vec2 texel = vec2(1.0)/ vec2(float(${innerWidth * 2}), float(${innerHeight * 2}));
  101.  
  102.     vec2 kd = round(vec2(amt * maxKernel + 1.0, amt * maxOffset + 1.0));
  103.  
  104.     vec3 blur = fastBlur(uv, texel, kd);
  105.  
  106.   fragColor = vec4(result, color.a);
  107. }
  108. `;
  109.  
  110.   const frag3 = `#version 300 es
  111. precision highp float;
  112. in vec2 uv;
  113.  
  114.   // The max kernel size (impacts performance)
  115. #define maxKernel 4.0
  116.  
  117. // The max offset (doesn't impact performance)
  118. #define maxOffset 34.0
  119. uniform sampler2D uTexture; 
  120.  
  121.  
  122. // https://www.shadertoy.com/view/mdGcRh
  123. vec3 fastBlur(vec2 uv, vec2 texel, vec2 kd)
  124. {
  125. float r = kd.x * kd.y;
  126. float rr = 1.0/r;
  127. vec3 col = vec3(0.0);
  128. float a = 1.0;
  129.  
  130. for (float x = -r; x <= r; x += kd.y) {       
  131. for (float y = -r; y <= r; y += kd.y)  {
  132. a++;
  133.       vec2 c = uv + vec2(x,y) * texel;
  134.  
  135.       col += texture(
  136.  
  137.       uTexture, 
  138.  
  139.       c 
  140.       + fract(sin(dot(c, vec2(2.9898, 78.233))) * 13758.5453) * texel * kd.y * 2.4
  141.       - kd.yy * texel
  142.  
  143.       ).rgb * (2.0 - distance(vec2(x,y) * rr, vec2(0.0)));
  144. }
  145. }
  146.  
  147. return col / a;
  148. }
  149.  
  150.  
  151. out vec4 fragColor;
  152. void main(void) {
  153.   vec4 color = texture(uTexture, uv);
  154.  
  155.     float amt = .4;
  156.     vec2 texel = vec2(1.0)/ vec2(float(${innerWidth * 2}), float(${innerHeight * 2}));
  157.  
  158.     vec2 kd = round(vec2(amt * maxKernel + 1.0, amt * maxOffset + 1.0));
  159.  
  160.   vec4 blur = vec4(fastBlur(uv, texel, kd), 1.);
  161.     //1-(1-A)*(1-B)
  162.   vec3 f = 1. - (1. - color.rgb) * (1. - blur.rgb);  
  163.  
  164.  
  165.   fragColor = vec4(f.rgb, 1.);
  166. } 
  167. `;
  168.  
  169.  
  170.  
  171. document.body.style.background = '#000';
  172. const gl = document.body
  173.   .appendChild(document.createElement('canvas'))
  174.   .getContext('webgl2');
  175.  
  176. Object.assign(gl.canvas.style, {
  177.   position: 'absolute',
  178.   left: 0,
  179.   top: 0
  180. });
  181.  
  182. const s = 1;
  183. const verts = new Float32Array([
  184.   -s, -s, 0,
  185.   s, -s, 0,
  186.   -s, s, 0,
  187.   s, s, 0,
  188. ]);
  189.  
  190. const buffer = gl.createBuffer();
  191. gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  192. gl.bufferData(gl.ARRAY_BUFFER, verts, gl.STATIC_DRAW);
  193.  
  194. function createShaderProgram(vertexSource, fragmentSource) {
  195.   const vs = gl.createShader(gl.VERTEX_SHADER);
  196.   gl.shaderSource(vs, vertexSource);
  197.   gl.compileShader(vs);
  198.  
  199.   const fs = gl.createShader(gl.FRAGMENT_SHADER);
  200.   gl.shaderSource(fs, fragmentSource);
  201.   gl.compileShader(fs);
  202.  
  203.   const program = gl.createProgram();
  204.   gl.attachShader(program, vs);
  205.   gl.attachShader(program, fs);
  206.   gl.linkProgram(program);
  207.  
  208.   if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  209.     console.error('Could not link program:', gl.getProgramInfoLog(program));
  210.   }
  211.  
  212.   return program;
  213. }
  214.  
  215. const program1 = createShaderProgram(vert, frag1);
  216. const program2 = createShaderProgram(vert, frag2);
  217. const program3 = createShaderProgram(vert, frag3);
  218.  
  219. const framebuffer1 = gl.createFramebuffer();
  220. const framebuffer2 = gl.createFramebuffer();
  221. const texture1 = gl.createTexture();
  222. const texture2 = gl.createTexture();
  223.  
  224. gl.bindTexture(gl.TEXTURE_2D, texture1);
  225. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, innerWidth, innerHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  226. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  227. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  228. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  229.  
  230. gl.bindTexture(gl.TEXTURE_2D, texture2);
  231. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, innerWidth, innerHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  232. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  233. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  234. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  235.  
  236. gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer1);
  237. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture1, 0);
  238.  
  239. gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer2);
  240. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture2, 0);
  241.  
  242. const onResize = () => {
  243.   gl.canvas.width = innerWidth * 2;
  244.   gl.canvas.height = innerHeight * 2;
  245.   gl.canvas.style.width = innerWidth + 'px'
  246.   gl.canvas.style.height = innerHeight + 'px'
  247.   gl.viewport(0, 0, innerWidth * 2, innerHeight * 2);
  248.   gl.bindTexture(gl.TEXTURE_2D, texture1);
  249.   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, innerWidth * 2, innerHeight * 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  250.   gl.bindTexture(gl.TEXTURE_2D, texture2);
  251.   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, innerWidth * 2, innerHeight * 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  252. };
  253.  
  254. window.onresize = onResize;
  255. onResize();
  256.  
  257. gl.disable(gl.DEPTH_TEST);
  258.  
  259. let mx = 0;
  260. let my = 0;
  261. let dx = 0;
  262. let dy = 0;
  263.  
  264. window.onpointermove = e => {
  265.   mx = e.clientX;
  266.   my = e.clientY;
  267. };
  268.  
  269. const loop = () => {
  270.  
  271.   dx += (mx * 2 - (innerWidth) - dx) / 8;
  272.   dy += (my * 2 - dy) / 8;
  273.  
  274.   // first pass
  275.   gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer1);
  276.   gl.useProgram(program1);
  277.  
  278.   const mxUniform = gl.getUniformLocation(program1, 'dx');
  279.   gl.uniform1f(mxUniform, dx);
  280.  
  281.   const myUniform = gl.getUniformLocation(program1, 'dy');
  282.   gl.uniform1f(myUniform, dy);
  283.  
  284.   gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  285.   const pos1 = gl.getAttribLocation(program1, 'position');
  286.   gl.enableVertexAttribArray(pos1);
  287.   gl.vertexAttribPointer(pos1, 3, gl.FLOAT, false, 0, 0);
  288.   gl.clearColor(0, 0, 0, 1);
  289.   gl.clear(gl.COLOR_BUFFER_BIT);
  290.   gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  291.  
  292.   // second pass
  293.   gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer2);
  294.   gl.useProgram(program2);
  295.   gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  296.   const pos2 = gl.getAttribLocation(program2, 'position');
  297.   gl.enableVertexAttribArray(pos2);
  298.   gl.vertexAttribPointer(pos2, 3, gl.FLOAT, false, 0, 0);
  299.   const uTexture = gl.getUniformLocation(program2, 'uTexture');
  300.   gl.uniform1i(uTexture, 0);
  301.   gl.activeTexture(gl.TEXTURE0);
  302.   gl.bindTexture(gl.TEXTURE_2D, texture1);
  303.   gl.clearColor(0, 0, 0, 1);
  304.   gl.clear(gl.COLOR_BUFFER_BIT);
  305.   gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  306.  
  307.   // third pass
  308.   gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  309.   gl.useProgram(program3);
  310.   gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  311.   const pos3 = gl.getAttribLocation(program3, 'position');
  312.   gl.enableVertexAttribArray(pos3);
  313.   gl.vertexAttribPointer(pos3, 3, gl.FLOAT, false, 0, 0);
  314.   const u2Texture = gl.getUniformLocation(program3, 'uTexture');
  315.   gl.uniform1i(u2Texture, 0);
  316.   gl.activeTexture(gl.TEXTURE0);
  317.   gl.bindTexture(gl.TEXTURE_2D, texture2);
  318.   gl.clearColor(0, 0, 0, 1);
  319.   gl.clear(gl.COLOR_BUFFER_BIT);
  320.   gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
  321.  
  322.   requestAnimationFrame(loop);
  323. };
  324. 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

// binary // color // filters // glsl // graphics // hacks // hex // javascript // math // webgl

squigs

  1. const canvas = document.body.appendChild(document.createElement("canvas"));
  2. const c = canvas.getContext("2d");
  3. document.body.style.margin = 0;
  4.  
  5. function resize() {
  6.   canvas.width = innerWidth * 2;
  7.   canvas.height = innerHeight * 2;
  8.   canvas.style.width = innerWidth + "px";
  9.   canvas.style.height = innerHeight + "px";
  10. }
  11. addEventListener("resize", resize);
  12. resize();
  13.  
  14. const PAD = 50;
  15. const RAD = 2;
  16. const SPEED = 40;
  17. const TWO_PI = Math.PI * 2;
  18.  
  19. let mode = "draw";
  20.  
  21. let t = Math.random() * TWO_PI,
  22.   x = innerWidth,
  23.   y = innerHeight,
  24.   vx = 0,
  25.   vy = 0,
  26.   ta = 0,
  27.   w = 10,
  28.   h = 1,
  29.   hue = 20;
  30.  
  31. function loop() {
  32.   c.globalAlpha = 1;
  33.   if (Math.random() < 0.12) {
  34.     let alpha = 0.02;
  35.     if (Math.random() < 0.1) alpha = 0.1;
  36.     c.fillStyle = `rgba(255, 255, 255, ${alpha})`;
  37.     c.fillRect(0, 0, canvas.width, canvas.height);
  38.   }
  39.   for (var i = 0; i < SPEED; i++) {
  40.     t = Math.sin(ta) * TWO_PI;
  41.     vx = RAD * Math.cos(t);
  42.     vy = RAD * Math.sin(t);
  43.     ta += Math.random() * 0.1 - 0.05;
  44.     x += vx;
  45.     y += vy;
  46.  
  47.     if (Math.random() < 0.005) {
  48.       mode = "no draw";
  49.       hue = [200, 20, 10, 40][~~(Math.random() * 4)];
  50.       if (Math.random() < 0.5) {
  51.         w = Math.random() * 200;
  52.         h = Math.random() * Math.random() * 10;
  53.       } else {
  54.         w = Math.random() * 20;
  55.         h = Math.random() * Math.random() * 200;
  56.       }
  57.     } else if (Math.random() < 0.005) {
  58.       mode = "draw";
  59.     }
  60.  
  61.     if (mode === "draw") {
  62.       c.shadowColor = "rgba(0, 205, 205, 0.2)";
  63.       c.shadowBlur = 5;
  64.       c.fillStyle = `hsl(${hue}, 100%, 50%)`;
  65.       c.fillRect(x, y, w, h);
  66.  
  67.       c.shadowColor = null;
  68.       c.shadowBlur = 0;
  69.     }
  70.  
  71.     if (x < -PAD) {
  72.       x = innerWidth + PAD;
  73.     } else if (x > canvas.width + PAD) {
  74.       x = -PAD;
  75.     }
  76.     if (y < -PAD) {
  77.       y = innerHeight + PAD;
  78.     } else if (y > canvas.height + PAD) {
  79.       y = -PAD;
  80.     }
  81.   }
  82.   c.globalAlpha = 0.9;
  83.   c.drawImage(canvas, -2, -1, canvas.width + 3, canvas.height + 4);
  84.  
  85.   requestAnimationFrame(loop);
  86. }
  87. loop();

More fun speed coding for some recent youtube shorts…

Canvas Blur Repeatedly

  1. document.body.style.margin = 0
  2. const canvas = document.body.appendChild(
  3.   document.createElement('canvas')
  4. )
  5. const c = canvas.getContext('2d')
  6.  
  7. function clear() {
  8.   c.fillStyle = 'rgb(95 182 209)'
  9.   c.fillRect(0, 0, innerWidth, innerHeight)
  10. }
  11.  
  12. function resize() {
  13.   canvas.width = innerWidth
  14.   canvas.height = innerHeight
  15.   clear()
  16. }
  17. resize()
  18.  
  19. addEventListener('resize', resize)
  20.  
  21. function loop() {
  22.   const size = Math.min(innerWidth / 2, 
  23.   innerHeight / 2)
  24.   const halfSize = size / 2
  25.  
  26.   c.filter = 'blur(50px)'
  27.   c.fillStyle = 'rgba(0, 0, 0, 0.02)'
  28.   c.fillRect(
  29.     innerWidth / 2 - halfSize, 
  30.     innerHeight / 2 - halfSize,
  31.     size, size)
  32.  
  33.   requestAnimationFrame(loop)
  34. }
  35. loop()

Apply a blur filter to a rectangle over and over again…

Browser support at the time of the post is still lacking – and there are some interesting rendering differences between Chrome and Firefox:

Firefox on left and Chrome on right…

As nice as it would be to be able to use these I don’t recommend it yet. Using a GLSL shader is the way to go for now…

snippet.zone ~ 2021-24 /// {s/z}