87 lines
3.2 KiB
GLSL
87 lines
3.2 KiB
GLSL
/* @kishimisu - 2023
|
|
|
|
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)
|
|
|
|
An audio-reactive scene that maps the frequencies of the input music
|
|
and the audio volume to different cells, colors, size and intensity!
|
|
|
|
I've been struggling to complete this scene as I wanted to repeat
|
|
the space with random variations for each cell. There's a wonderful
|
|
tutorial by Blackle Mori explaining how to achieve this (https://www.youtube.com/watch?v=I8fmkLK1OKg) ,
|
|
however I'm using an accumulation technique for the lighting with a
|
|
fixed number of steps (30) which gets broken with this new technique.
|
|
|
|
I decided to keep a reasonable random variation amount to prevent having
|
|
raymarching artifacts that are too visible. I couldn't get totally rid of them,
|
|
however with this kind of audio reactive scene it seems to be more acceptable
|
|
as there's a lot of rapid movements!
|
|
*/
|
|
|
|
#define light(d, att) 1. / (1.+pow(abs(d*att), 1.3))
|
|
#define rot(a) mat2(cos(a + vec4(0,33,11,0)))
|
|
|
|
/* Audio-related functions */
|
|
#define getLevel(x) (texelFetch(iChannel0, ivec2(int(x*512.), 0), 0).r)
|
|
#define logX(x,a,c) (1./(exp(-a*(x-c))+1.))
|
|
float logisticAmp(float amp){
|
|
float c = .88, a = 20.;
|
|
return (logX(amp, a, c) - logX(0.0, a, c)) / (logX(1.0, a, c) - logX(0.0, a, c));
|
|
}
|
|
float getPitch(float freq, float octave){
|
|
freq = pow(2., freq) * 261.;
|
|
freq = pow(2., octave) * freq / 12000.;
|
|
return logisticAmp(getLevel(freq));
|
|
}
|
|
float getVol(float samples) {
|
|
float avg = 0.;
|
|
for (float i = 0.; i < samples; i++) avg += getLevel(i/samples);
|
|
return avg / samples;
|
|
}
|
|
/* ----------------------- */
|
|
|
|
float sdBox( vec3 p, vec3 b ) {
|
|
vec3 q = abs(p) - b;
|
|
return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0);
|
|
}
|
|
float hash13(vec3 p3) {
|
|
p3 = fract(p3 * .1031);
|
|
p3 += dot(p3, p3.zyx + 31.32);
|
|
return fract((p3.x + p3.y) * p3.z);
|
|
}
|
|
|
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
|
vec2 uv = (2.*fragCoord-iResolution.xy)/iResolution.y;
|
|
vec3 col = vec3(.1,.0,.14);
|
|
float vol = getVol(8.);
|
|
|
|
vec3 ro = vec3(0, 8, 12)*(1. + vol*.3);
|
|
ro.zx *= rot(iTime*.4);
|
|
vec3 f = normalize(-ro), r = normalize(cross(vec3(0,1,0), f));
|
|
vec3 rd = normalize(f + uv.x*r + uv.y*cross(f, r));
|
|
|
|
float hasSound = 1.; if (iChannelTime[0] <= 0.) hasSound = .4;
|
|
|
|
for (float i = 0., t = 0.; i < 30.; i++) {
|
|
vec3 p = ro + t*rd;
|
|
|
|
vec2 cen = floor(p.xz) + .5;
|
|
vec3 id = abs(vec3(cen.x, 0, cen.y));
|
|
float d = length(id);
|
|
|
|
float freq = smoothstep(0., 20., d)*3.*hasSound + hash13(id)*2.;
|
|
float pitch = getPitch(freq, .7);
|
|
|
|
float v = vol*smoothstep(2., 0., d);
|
|
float h = d*.2*(1.+pitch*1.5) + v*2.;
|
|
float me = sdBox(p - vec3(cen.x, -50., cen.y), vec3(.3, 50. + h, .3)+pitch) - .05;
|
|
|
|
col += mix(mix(vec3(.8,.2,.4), vec3(0,1,0), min(v*2.,1.)), vec3(.5,.3,1.2), smoothstep(10., 30., d))
|
|
*(cos(id)+1.5)
|
|
* (pitch * d*.08 + v)
|
|
* light(me, 20.) * (1. + vol*2.);
|
|
|
|
t += me;
|
|
}
|
|
|
|
fragColor = vec4(col,1.0);
|
|
} |