#version 410 core uniform float fGlobalTime; // in seconds uniform vec2 v2Resolution; // viewport resolution (in pixels) uniform sampler1D texFFT; // towards 0.0 is bass / lower freq, towards 1.0 is higher / treble freq uniform sampler1D texFFTSmoothed; // this one has longer falloff and less harsh transients uniform sampler2D texBirds; uniform sampler2D texGrass; uniform sampler2D texNormal; uniform sampler2D texPerlin; uniform sampler2D texTiles; uniform sampler2D texZigZag; layout(location = 0) out vec4 out_color; // out_color must be written in order to see anything const float PI = 3.14159254; float _d; int _mID; // minimal spheretracer setup: smallest distance we have seen so far and material ID at that point // if we find a closer distance, store distance and material ID float minMat(float d, int id) { if (d < _d) { _d = d; _mID = id; } return _d; } // distances float ball(vec3 p) { return max(max(abs(p.x) - 3.0 + sin(fGlobalTime * .9) + texture(texFFT, .2).x * 40., abs(p.y) - .5), abs(p.z) - .5); } float the_ball(vec3 p) { float rotation = sin(fGlobalTime * .7) * 6.0 + texture(texFFTSmoothed, .2).x * 50.0; p.yz = vec2( cos(rotation) * p.y + sin(rotation) * p.z, cos(rotation) * p.z - sin(rotation) * p.y); float offset = 1.5 + sin(fGlobalTime * 2.1); return min( min( min( ball(p - vec3(0, offset, 0)), ball(p + vec3(0, offset, 0))), ball(p - vec3(0, 0, offset))), ball(p + vec3(0, 0, offset))); } float the_floor(vec3 p) { return p.y + 1.0; } // combined scene float scene(vec3 p) { float d = 999999; d = minMat(the_ball(p), 0); // second parameter is material ID //d = minMat(the_floor(p), 1); return d; } vec3 calcBallNormal( vec3 v ) { vec3 n; float e = 0.0001; n.x = the_ball( v + vec3(e,0,0) ) - the_ball( v - vec3(e,0,0) ); n.y = the_ball( v + vec3(0,e,0) ) - the_ball( v - vec3(0,e,0) ); n.z = the_ball( v + vec3(0,0,e) ) - the_ball( v - vec3(0,0,e) ); return normalize(n); } vec3 calcBallLighting( vec3 p, vec3 camPos ) { vec3 norm = calcBallNormal(p); vec3 lightDir = normalize(vec3(-1,1,-1)); float diff = dot(lightDir,norm); diff = clamp( diff,0.0,1.0); vec3 V = normalize( camPos - p ); vec3 L = lightDir; vec3 H = normalize( V + L ); float specular = dot(H,norm); specular = clamp( specular, 0.0, 1.0 ); vec2 uv = vec2(p.x, p.y + p.z); return texture(texBirds, uv).yzz * (texture(texZigZag, uv).y * .8 + .2) * 2.0 * diff + pow( specular, 50 ); } void main(void) { vec2 uv = gl_FragCoord.xy / v2Resolution; float aspect = v2Resolution.x / v2Resolution.y; float fCamTime = fGlobalTime / 3.0; vec3 camPos = vec3(cos(fGlobalTime * .9) * 2.0,sin(fGlobalTime * .8),-8.0 + sin(fGlobalTime) * 3.0); vec3 camDir = normalize(vec3(0.0,-0.0, 1.0)); vec3 camUp = normalize(vec3(sin(fGlobalTime) * .4,1,0)); float camFovTan = tan(60.0 * PI/360); vec2 sc = (uv*2 - vec2(1)) * vec2(aspect,1); vec3 rayDir = normalize(mat3(cross(camDir,camUp), camUp, -camDir) * normalize(vec3(sc, -1/camFovTan))); // march ray float numSteps = 100; float maxDist = 1000; float t = 0; float i = 0; for (; i < 1; i+= 1/numSteps) { _d = 100000; scene(camPos + rayDir * t); if ((abs(_d) / t < camFovTan/v2Resolution.y) || (t > maxDist)) break; t += _d; } if ((t > maxDist) || (i >= 1)) { // ray missed, paint background vec2 lol = gl_FragCoord.xy / v2Resolution - .5; vec2 fart = lol * (sin(fGlobalTime * 1.1) * .4 + .6) * 4.0; float rotation = sin(fGlobalTime * .88) * 5.0; fart = vec2( cos(rotation) * fart.x + sin(rotation) * fart.y, cos(rotation) * fart.y + sin(rotation) * fart.x) * (1.0 + texture(texFFT, .1).x * 40.); out_color.rgb = texture(texTiles, fart).yzx * vec3(1) * .2 * (sin(atan(lol.y, lol.x) * 5.0 + sin(fGlobalTime * 1.4) * 20.0) * .5 + .5); } else { // ray hit, select material vec3 p = camPos + rayDir * t; switch(_mID) { case 0: out_color.rgb = calcBallLighting( p, camPos ); break; case 1: out_color.rgb = vec3(1,1,1) * ((mod(p.x,2) < 1) == (mod(p.z,2) < 1) ? 1 : 0.1); break; } } out_color.rgb -= pow(texture(texPerlin, gl_FragCoord.xy / v2Resolution.y).x, 2.0) * pow(abs(gl_FragCoord.y / v2Resolution.y * 2.0 - 1.0), 2.0); out_color.rgb = pow(clamp(out_color.rgb, 0.0, 1.0) * 22.0, vec3(5.0)); // gamma adjust out_color.rgb = pow(out_color.rgb, vec3(1/2.2)); }