- Sign In
- Sign Up
WebGL2 FFT Texture
A simple audio visualizer showcasing the usage of the fftTexture sampler2D uniform, this time using WebGL2 and a sine-less hash function.
Created by marcogomez on Sat, 02 Oct 2021 13:20:04 GMT.
#version 300 es // ╔═════════════╦════════════════╗ // ║ Marco Gomez ║ https://mgz.me ║ // ╚═════════════╩════════════════╝ precision highp float; uniform sampler2D prgm3Texture; uniform vec2 resolution; uniform float time; out vec4 fragColor; void main(void) { vec2 uv = gl_FragCoord.xy / resolution.xy; vec4 prgm3 = texture(prgm3Texture, uv); fragColor = prgm3; }
#version 300 es // ╔═════════════╦════════════════╗ // ║ Marco Gomez ║ https://mgz.me ║ // ╚═════════════╩════════════════╝ precision highp float; uniform sampler2D fftTexture; uniform vec2 resolution; uniform float time; uniform int frame; out vec4 fragColor; vec3 hash33(vec3 p3) { p3 = fract(p3 * vec3(0.1031, 0.1030, 0.0973)); p3 += dot(p3, p3.yxz + 19.19); return fract((p3.xxy + p3.yxx) * p3.zyx); } vec3 mixColor(vec3 col1, vec3 col2, float v) { v = clamp(v, 0.0, 1.0); return clamp(col1 + v * (col2 - col1 * 1.5), 0.0, 1.0); } void main(void) { vec2 uv = gl_FragCoord.xy / resolution.xy; uv.x = (uv.x - 0.5 > 0.0) ? uv.x - 0.521 : 0.479 - uv.x; vec2 p = uv * 2.0 - 1.0; p *= vec2(resolution.x / resolution.y, 1.0); p.y += 0.3; vec3 col = vec3(0.0); vec3 ref = vec3(0.0); float nBands = 64.0; float i = floor((uv.x * 1.3 + 0.3) * nBands); float f = fract((uv.x * 1.3 + 0.3) * nBands); float band = i/nBands; band *= band * band; band = band * 0.995; band += 0.005; float s = texture(fftTexture, vec2(band, 0.25)).x; const int nColors = 4; vec3 colors[nColors]; colors[0] = vec3(0.0, 0.0, 1.0); colors[1] = vec3(0.0, 1.0, 1.0); colors[2] = vec3(1.0, 1.0, 0.0); colors[3] = vec3(1.0, 0.0, 0.0); vec3 gradCol = colors[0]; float n = float(nColors) - 1.0; for(int i = 1; i < nColors; i++) { gradCol = mixColor(gradCol, colors[i], (s - float(i - 1) / n) * n); } col += vec3(1.0 - smoothstep(0.0, 0.001, p.y - s * 1.25)); col *= gradCol; ref += vec3(1.0 - smoothstep(0.0, -0.001, p.y + s * 1.25)); ref *= gradCol * smoothstep(-0.5, 0.5, p.y); col = mix(ref, col, smoothstep(-0.005, 0.005, p.y)); col *= smoothstep(0.125, 0.375, f); col *= smoothstep(0.875, 0.625, f); col = clamp(col, 0.0, 1.0); vec3 h = hash33(vec3(gl_FragCoord.xy, float(frame))); float dither = h.x * h.y; col += dither * 0.04; fragColor = vec4(col,1.0); }
#version 300 es // ╔═════════════╦════════════════╗ // ║ Marco Gomez ║ https://mgz.me ║ // ╚═════════════╩════════════════╝ precision highp float; uniform sampler2D prgm1Texture; uniform vec2 resolution; uniform float time; uniform int frame; out vec4 fragColor; vec3 hash33(vec3 p3) { p3 = fract(p3 * vec3(0.1031, 0.1030, 0.0973)); p3 += dot(p3, p3.yxz + 19.19); return fract((p3.xxy + p3.yxx) * p3.zyx); } void main(void) { vec2 uv = gl_FragCoord.xy / resolution.xy; vec4 texCol = texture(prgm1Texture, uv); vec4 col = texCol; float w = 0.1; vec2 a = vec2(uv.x - 0.5, uv.y - 0.66); vec2 b = a * 0.15 / float(10.0); vec3 h = hash33(vec3(gl_FragCoord.xy, frame)); uv += b * h.x; for (float i = 1.0; i > 0.9; i-= 0.000625) { uv -= 0.5; uv *= i; uv += 0.5; col += texture(prgm1Texture, uv) * w * 1.5; w *= 0.95; } col *= 0.9; fragColor = mix(texCol, col, 0.5); }
#version 300 es // ╔═════════════╦════════════════╗ // ║ Marco Gomez ║ https://mgz.me ║ // ╚═════════════╩════════════════╝ precision highp float; uniform sampler2D prgm2Texture; uniform vec2 resolution; uniform float time; uniform float fft; out vec4 fragColor; const float PI = acos(-1.0); const float TAU = PI * 2.0; const float hardscan = -16.0; // -8.0 = soft | -16.0 = medium const float hardPix = -4.0; // -2.0 = soft | -4.0 = hard const float maskDark = 0.5; const float maskLight = 2.5; const float hk = 1.0 / sqrt(3.0); vec3 hueShift(vec3 col, float a) { const vec3 k = vec3(hk); float ca = cos(a); return vec3(col * ca + cross(k, col) * sin(a) + k * dot(k, col) * (1.0 - ca)); } float toLinear(float c) { return (c <= 0.04045) ? c / 12.92 : pow(abs((c + 0.055) / 1.055), 2.4); } vec3 toLinear(vec3 c) { return vec3(toLinear(c.r), toLinear(c.g), toLinear(c.b)); } float toSRGB(float c) { return(c < 0.0031308 ? c * 12.92 : 1.055 * pow(abs(c), 0.41666) - 0.055); } vec3 toSRGB(vec3 c) { return vec3(toSRGB(c.r), toSRGB(c.g), toSRGB(c.b)); } vec3 fetch(vec2 pos, vec2 off, vec2 res) { pos = floor(pos * res + off) / res; if (max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5) { return vec3(0.0); } vec3 fetch = texture(prgm2Texture, pos.xy, -16.0).xyz; fetch = hueShift(fetch, 2.0 * fft + time); return toLinear(mix(fetch, fetch * fetch, 0.5)); } vec2 dist(vec2 pos, vec2 res) { pos = pos * res; return -((pos - floor(pos)) - vec2(0.5)); } float gauss(float pos, float scale) { return exp2(scale * pos * pos); } vec3 horz3(vec2 pos, float off, vec2 res) { vec3 b = fetch(pos, vec2(-1.0, off), res); vec3 c = fetch(pos, vec2(+0.0, off), res); vec3 d = fetch(pos, vec2(+1.0, off), res); float dst = dist(pos, res).x; float scale = hardPix; float wb = gauss(dst - 1.0, scale); float wc = gauss(dst + 0.0, scale); float wd = gauss(dst + 1.0, scale); return (b * wb + c * wc + d * wd) / (wb + wc + wd); } vec3 horz5(vec2 pos, float off, vec2 res) { vec3 a = fetch(pos, vec2(-2.0, off), res); vec3 b = fetch(pos, vec2(-1.0, off), res); vec3 c = fetch(pos, vec2(+0.0, off), res); vec3 d = fetch(pos, vec2(+1.0, off), res); vec3 e = fetch(pos, vec2(+2.0, off), res); float dst = dist(pos, res).x; float scale = hardPix; float wa = gauss(dst - 2.0, scale); float wb = gauss(dst - 1.0, scale); float wc = gauss(dst + 0.0, scale); float wd = gauss(dst + 1.0, scale); float we = gauss(dst + 2.0, scale); return (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we); } float scan(vec2 pos, float off, vec2 res) { float dst = dist(pos, res).y; return gauss(dst + off, hardscan); } vec3 tri(vec2 pos, vec2 res) { vec3 a = horz3(pos, -1.0, res); vec3 b = horz5(pos, +0.0, res); vec3 c = horz3(pos, +1.0, res); float wa = scan(pos, -1.0, res); float wb = scan(pos, +0.0, res); float wc = scan(pos, +1.0, res); return a * wa + b * wb + c * wc; } vec3 mask(vec2 pos) { pos.x += pos.y * 3.0; vec3 m = vec3(maskDark, maskDark, maskDark); pos.x = fract(pos.x / 6.0); if (pos.x < 0.333) { m.r = maskLight; } else if (pos.x < 0.666) { m.g = maskLight; } else { m.b = maskLight; } return m; } float bar(float pos, float bar) { pos -= bar; return pos * pos < 4.0 ? 0.0 : 1.0; } vec2 warp(vec2 uv, vec2 warpAmount) { uv = uv * 2.0 - 1.0; vec2 offset = abs(uv.yx) / vec2(warpAmount.x, warpAmount.y); uv = uv + uv * offset * offset; uv = uv * 0.5 + 0.5; return uv; } void drawVig(inout vec3 color, vec2 uv) { float vignette = uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y); vignette = clamp(pow(abs(16.0 * vignette), 0.1), 0.0, 1.0); color *= vignette; } void main(void) { vec2 warpAmount = vec2(7.0, 5.0); vec2 res = vec2(resolution.x / 4.0, resolution.y / 3.0); vec2 uv = gl_FragCoord.xy / resolution.xy; float vig = (0.0 + 1.0 * 21.0 * uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y)); float v = exp(-0.01 * length(uv)) * vig; vec2 pos = mix(uv, warp(uv, warpAmount), 0.75); vec4 color = vec4(tri(pos, res) * mask(gl_FragCoord.xy), 1.0); color.xyz = toSRGB(color.xyz * 2.0); color = mix(color, color * v, 0.7); fragColor = vec4(color.xyz, 1.0); }
xxxxxxxxxx
// ╔═════════════╦════════════════╗
// ║ Marco Gomez ║ https://mgz.me ║
// ╚═════════════╩════════════════╝
precision highp float;
uniform sampler2D prgm3Texture;
uniform vec2 resolution;
uniform float time;
out vec4 fragColor;
void main(void) {
vec2 uv = gl_FragCoord.xy / resolution.xy;
vec4 prgm3 = texture(prgm3Texture, uv);
fragColor = prgm3;
}
104 fps 14ms
00:00:00.31
0.00