#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);
}
#version 300 es
// ╔═════════════╦════════════════╗
// ║ Marco Gomez ║ https://mgz.me ║
// ╚═════════════╩════════════════╝
precision highp float;
#define duration 128.0
uniform vec2 resolution;
uniform float sampleRate;
uniform float blockOffset;
out vec2 fragColor;
const float PI = acos(-1.0);
const float TAU = PI * 2.0;
const float rootC2 = 65.417;
float notes[85];
void precomputeNotes(float rootNote) {
for (int i = 0; i <= (12 * 7); i++) {
notes[i] = rootNote * pow(abs(2.0), (float(i) / 12.0));
}
}
float getNote(int noteIdx, int octave) {
return notes[(noteIdx - 1) + ((octave - 1) * 12)];
}
float aLerp(float start, float end, float t, float A, float B) {
return (
(A * (end - t)) / (end - start) +
(B * (t - start) / (end - start)));
}
float naiveADSR(float t, vec2 A, vec2 D, vec2 S, vec2 R) {
vec2 start = vec2(0.0);
float adsr = 0.0;
if (t < A.x) {
adsr = aLerp(start.x, A.x, t, start.y, A.y);
} else if (t < D.x) {
adsr = aLerp(A.x, D.x, t, A.y, D.y);
} else if (t < S.x) {
adsr = aLerp(D.x, S.x, t, D.y, S.y);
} else if(t < R.x) {
adsr = aLerp(S.x, R.x, t, S.y, R.y);
} else {
adsr = 0.0;
}
return adsr;
}
#define leftRight vec2(1.0, 1.0)
#define kickMaxFreq 130.81
#define scaleX 0.005
#define squareNum 10.0
#define L 0.5
#define basicA vec2(0.001, 1.0)
#define basicD vec2(0.4, 0.3)
#define basicS vec2(0.8, 0.3)
#define basicR vec2(1.5, 0.0)
#define snareA vec2(0.0002, 1.0)
#define snareD vec2(0.12, 0.09)
#define snareS vec2(0.3, 0.09)
#define snareR vec2(0.7, 0.0)
#define brushA vec2(0.01, 0.6)
#define brushD vec2(0.2, 0.1)
#define brushS vec2(0.22, 0.05)
#define brushR vec2(0.5, 0.0)
#define hatA vec2(0.001, 1.0)
#define hatD vec2(0.02, 0.5)
#define hatS vec2(0.02, 0.4)
#define hatR vec2(0.1, 0.0)
#define kNoiseA vec2(0.0002, 1.0)
#define kNoiseD vec2(0.03, 0.1)
#define kNoiseS vec2(0.05, 0.1)
#define kNoiseR vec2(0.06, 0.0)
#define kickA vec2(0.0002, 1.0)
#define kickD vec2(0.2, 0.0)
#define kickS vec2(0.22, 0.0)
#define kickR vec2(0.22, 0.0)
#define kickFA vec2(0.001, 1.0)
#define kickFD vec2(0.2, 0.0)
#define kickFS vec2(0.22, 0.0)
#define kickFR vec2(0.22, 0.0)
#define stabA vec2(0.0002, 1.0)
#define stabD vec2(0.2, 0.1)
#define stabS vec2(0.22, 0.1)
#define stabR vec2(0.92, 0.0)
vec2 stereoNoise(float t, float freq, vec2 lr) {
float f = fract(sin(freq * t * 234.0) * 43153.0);
float adsr = naiveADSR(t, kNoiseA, kNoiseD, kNoiseS, kNoiseR);
return vec2(f * lr) * adsr;
}
vec2 stereoSin(float t, float freq, vec2 lr) {
float adsr = naiveADSR(t, basicA, basicD, basicS, basicR);
return vec2(sin(freq * t * TAU)) * lr * adsr;
}
vec2 stereoStab(float t, float freq, vec2 lr) {
float adsr = naiveADSR(t, stabA, stabD, stabS, stabR);
return vec2(sin(freq * t * TAU * 0.5)) * lr * adsr;
}
vec2 stereoKick(float t, float freq, vec2 lr) {
float adsr = naiveADSR(t, kickA, kickD, kickS, kickR);
float freq_adsr = naiveADSR(t, kickFA, kickFD, kickFS, kickFR);
freq = (freq + freq_adsr * kickMaxFreq) * 0.6;
return vec2(sin(freq * t * TAU)) * lr * adsr * 2.0;
}
vec2 stereoSnare(float t, float freq, vec2 lr) {
float f = fract(sin(freq * t * 234.0) * 43153.0);
float adsr = naiveADSR(t, snareA, snareD, snareS, snareR);
return vec2(f * lr) * adsr * 2.0;
}
vec2 stereoBrush(float t, float freq, vec2 lr) {
float f = fract(sin(freq * t * 234.0) * 43153.0);
float adsr = naiveADSR(t, brushA, brushD, brushS, brushR);
return vec2(f * lr) * adsr;
}
vec2 stereoHat(float t, float freq, vec2 lr) {
float f = fract(sin(freq * t * 234.0) * 43153.0);
float adsr = naiveADSR(t, hatA, hatD, hatS, hatR);
return vec2(f * lr) * adsr;
}
vec2 stereoSaw(float t, float freq, vec2 lr) {
return vec2(fract(freq * t / 2.0)) * lr;
}
vec2 stereoTri(float t, float freq, vec2 lr) {
return vec2(abs(fract(freq * t) - 0.5) * 3.0);
}
vec2 stereoSquare(float t, float freq, vec2 lr) {
float f = 0.0;
for (float i = 1.0; i <= squareNum; i += 2.0) {
f += sin((i * PI * freq * t * 0.5) / L) / i;
}
f *= (4.0 / PI);
return f * lr;
}
vec2 beat1(float t) {
vec2 f = stereoStab(t, getNote(1, 5), vec2(0.3, 0.9)); // C5
f += stereoKick(t, getNote(1, 2), leftRight); // C2
f += stereoTri(t, getNote(6, 2), leftRight); // F2
return f;
}
vec2 beat2(float t) {
vec2 f = stereoStab(t, getNote(4, 6), vec2(0.9, 0.5)); // Eb6
f += stereoStab(t, getNote(8, 5), leftRight); // G5
f += stereoKick(t, getNote(1, 2), leftRight) * 0.7; // C2
return f;
}
vec2 beat3(float t) {
vec2 f = stereoStab(t, getNote(11, 5), vec2(0.3, 0.9)); // Bb5
f += stereoStab(t, getNote(8, 5), leftRight); // G5
f += stereoTri(t, getNote(6, 2), leftRight); // F2
return f;
}
vec2 beat4(float t) {
vec2 f = stereoStab(t, getNote(9, 4), vec2(0.6, 0.8)); // Ab4
f += stereoKick(t, getNote(1, 2), leftRight) * 0.5; // C2
return f;
}
vec2 beat5(float t) {
vec2 f = stereoStab(t, getNote(11, 5), vec2(0.5,0.9)); // Bb5
f += stereoSnare(t, getNote(1, 2), leftRight) * 0.21; // C2
return f;
}
vec2 beat6(float t) {
return stereoStab(t, getNote(4, 5), vec2(0.6,0.7)); // Eb5
}
vec2 beat7(float t) {
vec2 f = stereoStab(t, getNote(3, 4), vec2(0.9, 0.5)); // D4
f += stereoTri(t, getNote(6, 2), leftRight); // F2
return f;
}
vec2 beat8(float t) {
vec2 f = stereoStab(t, getNote(6, 4), vec2(0.5, 0.9)); // F4
f += stereoKick(t, getNote(1, 2), leftRight) * 0.5; // C2
return f;
}
vec2 beat9(float t) {
vec2 f = stereoStab(t, getNote(1, 4), vec2(0.6, 0.6)); // C4
f += stereoBrush(t, getNote(1, 4) * 1.94, vec2(0.0, 0.4)); // C4ish
f += stereoKick(t, getNote(1, 2), leftRight); // C2
f += stereoTri(t, getNote(4, 2), leftRight); // Eb2
return f;
}
vec2 beat10(float t) {
vec2 f = stereoStab(t, getNote(11, 6), vec2(0.9, 0.5)) * 0.5; // Bb6
f += stereoKick(t, getNote(1, 2), leftRight) * 0.7; // C2
return f;
}
vec2 beat11(float t) {
vec2 f = stereoStab(t, getNote(11, 4), vec2(0.2, 0.9)); // Bb4
return f;
}
vec2 beat12(float t) {
vec2 f = stereoStab(t, getNote(4, 4), vec2(0.9, 0.3)); // Eb4
f += stereoKick(t, getNote(1, 2), leftRight) * 0.5; // C2
return f;
}
vec2 beat13(float t) {
vec2 f = stereoStab(t, getNote(1, 6), vec2(0.3, 0.9)); // C6
f += stereoHat(t, getNote(1, 4) * 1.94,vec2(0.4, 0.0)); // C4ish
f += stereoTri(t, getNote(3, 2), leftRight); // D2
f += stereoSnare(t,getNote(1, 2), leftRight) * 0.21; // C2
return f;
}
vec2 beat14(float t) {
vec2 f = stereoStab(t, getNote(3, 5), vec2(0.9, 0.7)); // D5
f += stereoHat(t, getNote(1, 4) * 1.94, vec2(0.4, 0.0)) * 0.9; // C4ish
return f;
}
vec2 beat15(float t) {
vec2 f = stereoStab(t, getNote(4, 5), vec2(0.5, 0.9)); // Eb5
f += stereoHat(t, getNote(1, 4) * 1.94,vec2(0.4, 0.0)) * 0.8; // C4ish
f += stereoTri(t, getNote(11, 2), leftRight); // Bb2
return f;
}
vec2 beat16(float t) {
vec2 f = stereoStab(t, getNote(11, 5), vec2(0.9, 0.7)); // Bb5
f += stereoHat(t, getNote(1, 4) * 1.94, vec2(0.4, 0.0)) * 0.7; // C4ish
f += stereoTri(t, getNote(4, 2) + fract(t) * 12.0 - 20.0, leftRight); // Eb2
return f;
}
mat2 rot(float a) {
return mat2(cos(a), -sin(a), sin(a), cos(a));
}
vec2 mainSound(float time) {
float t = time;
float speed = 0.25;
float sequenceLength = 16.0;
float len = sequenceLength * speed;
float m = mod(t, len);
float loopLength = (m < 0.5) ? 2.0 : 1.0;
float sequencer = floor(mod(t, len) / speed + 1.0);
time = (t < 16.0) ? mod(t, len) : mod(t, loopLength * speed);
time = time * smoothstep(-0.01, 0.01, time);
vec2 f;
if (sequencer == 1.0) f = beat1(time);
else if (sequencer == 2.0) f = beat2(time);
else if (sequencer == 3.0) f = beat3(time);
else if (sequencer == 4.0) f = beat4(time);
else if (sequencer == 5.0) f = beat5(time);
else if (sequencer == 6.0) f = beat6(time);
else if (sequencer == 7.0) f = beat7(time);
else if (sequencer == 8.0) f = beat8(time);
else if (sequencer == 9.0) f = beat9(time);
else if (sequencer == 10.0) f = beat10(time);
else if (sequencer == 11.0) f = beat11(time);
else if (sequencer == 12.0) f = beat12(time);
else if (sequencer == 13.0) f = beat13(time);
else if (sequencer == 14.0) f = beat14(time);
else if (sequencer == 15.0) f = beat15(time);
else if (sequencer == 16.0) f = beat16(time);
if (t > 32.0 && t < 64.0 || t > 8.0 && t < 16.0) {
f = mix((f * vec2(0.990, 1.001) * rot(m * 256.0)), f * 4.0, 0.5);
} else {
f = f * 2.0;
}
return f / 8.0;
}
void main(void) {
precomputeNotes(rootC2);
vec2 coord = floor(gl_FragCoord.xy);
float time = blockOffset + (coord.x + coord.y * resolution.x) / sampleRate;
fragColor = mainSound(time);
}