X
precision mediump float;
#define MAX_ITER 100
#define EPSILON 0.001
#define MAX_DIST 30.0
uniform float alpha;
uniform sampler2D fft;
uniform vec2 resolution;
uniform float time;
float GetScene(vec3 p);
float Combine(float a, float b) {
return min(a, b);
}
float Subtract(float a, float b) {
return max(-a, b);
}
vec3 GetNormal(vec3 p, float edelta) {
vec2 e = vec2(0.0, EPSILON * edelta);
return normalize(vec3(
GetScene(p + e.yxx) - GetScene(p - e.yxx),
GetScene(p + e.xyx) - GetScene(p - e.xyx),
GetScene(p + e.xxy) - GetScene(p - e.xxy)
));
}
vec3 GetLight(float dist, vec3 pos, vec3 dir, float specDelta, float edelta) {
if (dist < EPSILON) {
vec3 normal = GetNormal(pos, edelta);
float diffuse = max(0.0, dot(-dir, normal));
float specular = pow(diffuse, specDelta);
vec3 color = vec3(diffuse + specular);
return color;
} else {
return vec3(0.0);
}
}
vec3 Repeat(vec3 p, vec3 d) {
return mod(p, d) - 0.5 * d;
}
float Dot2(vec3 v) {
return dot(v, v);
}
float Smin(float a, float b, float k) {
float res = exp(-k * a) + exp(-k * b);
return -log(res) / k;
}
float Sphere(vec3 p, float r) {
return length(p) - r;
}
float Box(vec3 p, vec3 b) {
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
vec4 bass;
vec4 medium;
vec4 high;
void main(void) {
vec4 t1 = texture2D(fft, vec2(0.1));
float clpm = clamp(t1.r, 0.5, 1.0);
vec3 cameraOrigin = vec3(sin(time * 0.1 + clpm * 0.3), time, cos(time * 0.1 + clpm * 0.3));
vec3 cameraTarget = vec3(0.0, time * -2.0, 0.0);
vec3 upDirection = vec3(0.0, 1.0, 0.0);
vec3 cameraDirection = normalize(cameraTarget - cameraOrigin);
vec3 cameraRight = normalize(cross(upDirection, cameraOrigin));
vec3 cameraUp = cross(cameraDirection, cameraRight);
vec2 screenPos = (-1.0 + 2.0 * gl_FragCoord.xy / resolution.xy) * (resolution.x / resolution.y);
vec3 dir = normalize(cameraRight * screenPos.x + cameraUp * screenPos.y + cameraDirection);
float total = 0.0;
float dist = EPSILON;
vec3 position = cameraOrigin;
bass = texture2D(fft, vec2(0.0, 0.0));
medium = texture2D(fft, vec2(0.5, 0.0));
high = texture2D(fft, vec2(1.0, 0.0));
for (int i = 0; i < MAX_ITER; ++i) {
if (dist < EPSILON || total > MAX_DIST)
break;
dist = GetScene(position);
total += dist;
position += dist * dir;
}
float len = length(position - cameraOrigin) * 0.04;
vec3 color = GetLight(dist, position, dir, 150.0, 1.0) + vec3(sin(dir.y + time * 0.4) * 0.5, cos(dir.y + time * 0.1) * 0.5, 0.1);
color = mix(color, vec3(1.1 - sin(clpm)), 0.6);
gl_FragColor = (vec4(color - len, 1.0) + vec4(vec3(0.05), 0.0)) * alpha;
}
float Displacement(vec3 p, float delta) {
return sin(delta * p.x) * sin(delta * p.y) * sin(delta * p.z);
}
float GetScene(vec3 position) {
vec4 t0 = texture2D(fft, vec2(0.35));
vec4 t1 = texture2D(fft, vec2(0.1));
float clpm = clamp(t1.r, 0.5, 1.0);
vec3 p = position;
vec3 roomSize = vec3(1.0);
float holeSize = 0.4 + (t0.r + clpm);
vec3 q0 = Repeat(p, vec3(1.8));
vec3 q1 = Repeat(p, vec3(2.34));
float walls = Box(q0, roomSize);
float wallHole0 = Box(q0, vec3(2.0, holeSize, holeSize));
float wallHole1 = Box(q0, vec3(holeSize, 2.0, holeSize));
float wallHole2 = Box(q0, vec3(holeSize, holeSize, 2.0));
float wallHole3 = Box(q0, vec3(0.8));
float wallHole4 = Sphere(q1, 0.8);
float blob0 = Sphere(p + vec3(sin(clpm + bass.r) - 0.5 + sin(time) * 1.2, -time + (2.0 + (sin(time * 0.5) * 0.8)), -0.5 + sin(time * 2.0) * 0.25), 0.5 + abs(sin(clpm * 0.5) * 0.1));
float blob1 = Sphere(p + vec3(cos(clpm - bass.r) + sin(clpm), -time + (2.0 + (sin(clpm) * 0.99)), -0.5 + cos(clpm* 2.0) * 0.1), 0.2 + abs(sin(clpm * 0.5) * 0.1));
float blob2 = Sphere(p + vec3(cos(-clpm) , -time + (2.0 + (cos(clpm) * 0.99)), 0.5 * cos(-clpm)), 0.2 + abs(sin(clpm * 0.5) * 0.1));
blob0 += high.r;
blob1 *= clpm;
blob2 *= clpm;
walls = Subtract(wallHole0, walls);
walls = Subtract(wallHole1, walls);
walls = Subtract(wallHole2, walls);
walls = Subtract(wallHole3, walls);
walls = Displacement(p-0.9, 0.3) + walls;
walls = Combine(walls, blob0 + Displacement(p, 1.5));
float blobs = blob1 + Displacement(p, 1.5);
blobs = Smin(blob2 + Displacement(p + vec3(clpm * 0.5, clpm * 0.1, clpm * 0.3), 2.0 - cos(clpm * 0.01) * 5.0) * 0.12, blobs, 32.0);
walls = Smin(walls, blobs, 32.0);
return walls;
}