
const char* vshader = 
"#version 430 core\n"
"\n"
"layout (location = 0) in vec3 p;\n"
"layout (location = 1) in vec2 uv;\n"
"out vec2 coord;\n"
"\n"
"void main()\n"
"{\n"
"gl_Position = vec4(p.xy, 0.0, 1.0);\n"
"coord = uv;\n"
"}\n"
;

const char* fshader = 
"#version 430 core\n"
"\n"
"layout (location=0) out vec4 color;\n"
"layout (location=1) uniform int t;\n"
"in vec2 coord;\n"
"\n"
"// Timing variables\n"
"const float scene1Start = 5.0f;\n"
"const float scene2Start = 15.0f;\n"
"const float scene3Start = 25.0f;\n"
"const float scene4Start = 35.0f;\n"
"const float scene5Start = 45.0f;\n"
"\n"
"const float fadeLength = 1.0f;\n"
"\n"
"// Color constants rgb\n"
"const vec3 black = vec3(0.0f, 0.0f, 0.0f);\n"
"const vec3 white = vec3(1.0f, 1.0f, 1.0f);\n"
"const vec3 orange = vec3(0.85, 0.43, 0.02);\n"
"const vec3 teal = vec3(0.34, 0.83, 0.81);\n"
"const vec3 magic = vec3(1.0, 0.0, 0.7);\n"
"const vec3 red = vec3(0.9, 0.1, 0.1);\n"
"\n"
"const float height = 1080.0;\n"
"const float width = 1920.0;\n"
"\n"
"// Helper functions\n"
"vec3 fade(float start, float end, float time, vec3 color1, vec3 color2)\n"
"{\n"
"float part = (time - start) / (end - start);\n"
"return mix(color1, color2, part);\n"
"}\n"
"\n"
"float expsmin(float a, float b, float k)\n"
"{\n"
"float res = exp(-k*a) + exp(-k*b);\n"
"return -log(res)/k;\n"
"}\n"
"\n"
"float polsmin(float a, float b, float k)\n"
"{\n"
"float h = clamp(0.5 + 0.5 *(b-a)/k, 0.0, 1.0);\n"
"return mix(b, a, h) - k*h*(1.0 - h);\n"
"}\n"
"\n"
"float powsmin(float a, float b, float k)\n"
"{\n"
"a = pow(a,k);\n"
"b = pow(b,k);\n"
"return pow((a*b)/(a+b), 1.0/k);\n"
"}\n"
"\n"
"vec3 rgb2hsv(vec3 c)\n"
"{\n"
"vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"
"vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n"
"vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"
"float d = q.x - min(q.w, q.y);\n"
"float e = 1.0e-10;\n"
"return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"
"}\n"
"\n"
"vec3 hsv2rgb(vec3 c)\n"
"{\n"
"vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n"
"vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n"
"return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n"
"}\n"
"\n"
"float rand(vec2 co){\n"
"return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\n"
"}\n"
"\n"
"float noise(vec2 n) {\n"
"const vec2 d = vec2(0.0, 1.0);\n"
"vec2 b = floor(n), f = smoothstep(vec2(0.0), vec2(1.0), fract(n));\n"
"return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y);\n"
"}\n"
"\n"
"float fbm(vec2 n, float time) {\n"
"float total = 0.0, amplitude = 1.0;\n"
"for (int i = 0; i <4; i++) {\n"
"total += noise(n) * amplitude;\n"
"n += n*2.1;\n"
"amplitude *= 0.377 + sin(time)/500.0;\n"
"}\n"
"return total;\n"
"}\n"
"\n"
"float swayed(float value, float time, float radius)\n"
"{\n"
"return value + radius * sin(time);\n"
"}\n"
"\n"
"vec3 ray(vec2 uv)\n"
"{\n"
"return normalize(vec3(uv, 1.0f));\n"
"}\n"
"\n"
"vec3 cartToPolar(vec3 cart)\n"
"{\n"
"vec3 pol;\n"
"pol.x = sqrt(dot(cart, cart));\n"
"pol.y = acos(cart.y/pol.x);\n"
"pol.z = atan(cart.x, cart.z);\n"
"return pol;\n"
"}\n"
"\n"
"vec3 polarToCart(vec3 pol)\n"
"{\n"
"vec3 cart;\n"
"cart.x = pol.x * sin(pol.y) * sin(pol.z);\n"
"cart.y = pol.x * cos(pol.y);\n"
"cart.z = pol.x * sin(pol.y) * cos(pol.z);\n"
"return cart;\n"
"}\n"
"\n"
"void mangelprotExpansion(in out vec3 w)\n"
"{\n"
"float x = w.x; float x2 = x*x; float x4 = x2*x2;\n"
"float y = w.y; float y2 = y*y; float y4 = y2*y2;\n"
"float z = w.z; float z2 = z*z; float z4 = z2*z2;\n"
"\n"
"float k3 = x2 + z2;\n"
"float k2 = inversesqrt( k3*k3*k3*k3*k3*k3*k3 );\n"
"float k1 = x4 + y4 + z4 - 6.0*y2*z2 - 6.0*x2*y2 + 2.0*z2*x2;\n"
"float k4 = x2 - y2 + z2;\n"
"\n"
"w.x =  64.0*x*y*z*(x2-z2)*k4*(x4-6.0*x2*z2+z4)*k1*k2;\n"
"w.y = -16.0*y2*k3*k4*k4 + k1*k1;\n"
"w.z = -8.0*y*k4*(x4*x4 - 28.0*x4*x2*z2 + 70.0*x4*z4 - 28.0*x2*z2*z4 + z4*z4)*k1*k2;\n"
"}\n"
"\n"
"vec3 pounchingSphere(float time)\n"
"{\n"
"float y = -0.5 + abs(sin(time)) * 1.5 / pow(time, 0.4);\n"
"float x = 1.0 - abs(mod(time * 0.2, 2.0) - 1.0) * 2.0;\n"
"return vec3(x, y, 0.0f);\n"
"}\n"
"\n"
"float raySphere(vec3 start, vec3 dir, vec3 cen, float r, out vec3 point)\n"
"{\n"
"vec3 m = start - cen;\n"
"float b = dot(m, dir);\n"
"float c = dot(m, m) - r*r;\n"
"if(c > 0.0 && b > 0.0)\n"
"return -1.0;\n"
"float discr = b*b - c;\n"
"if(discr < 0.0)\n"
"return -1.0;\n"
"float t = -b - sqrt(discr);\n"
"point = start + t * dir;\n"
"return t;\n"
"}\n"
"\n"
"vec3 sphereColor(vec2 uv, vec3 sphere, float time, float rad)\n"
"{\n"
"vec3 start = vec3(uv, -3.0);\n"
"vec3 dir = vec3(0.0, 0.0, 1.0);\n"
"\n"
"vec3 point;\n"
"float t = raySphere(start, dir, sphere, rad, point);\n"
"\n"
"if (t < 0.0)\n"
"return magic;\n"
"\n"
"vec3 d = point.xyz - sphere.xyz;\n"
"\n"
"float xrot = 0.2 * sin(time*0.2);\n"
"float yrot = 0.3 * cos(time*0.3);\n"
"float zrot = 0.12 * time;\n"
"\n"
"mat3 rmx = mat3(vec3(1., 0., 0.), vec3(0., cos(xrot), sin(xrot)), vec3(0., -sin(xrot), cos(xrot)));\n"
"mat3 rmy = mat3(vec3(cos(yrot), 0., -sin(yrot)), vec3(0., 1., 0.), vec3(sin(yrot), 0., cos(yrot)));\n"
"mat3 rmz = mat3(vec3(cos(zrot), sin(zrot), 0.), vec3(-sin(zrot), cos(zrot), 0.), vec3(0., 0., 1.));\n"
"\n"
"d.xyz = d.xzy;\n"
"d = rmx * rmy * rmz * d;\n"
"float r = length(d);\n"
"float theta = acos(d.z / r);\n"
"float gamma = atan(d.y / d.x);\n"
"\n"
"bool onT = (step(sin(theta * 8.0), 0.0) > 0);\n"
"bool onG = (step(sin(gamma * 8.0), 0.0) > 0);\n"
"\n"
"if((onT || onG) && !(onT && onG))\n"
"return red;\n"
"return white;\n"
"}\n"
"\n"
"vec3 gridBack(vec2 uv, float time)\n"
"{\n"
"vec2 p = uv * 3.0;\n"
"vec2 fp = floor(p);\n"
"vec2 cp = ceil(p);\n"
"vec2 clp = clamp(uv * 3.0, vec2(-4.0, -2.0), vec2(4.0, 2.0));\n"
"vec2 d = (clp == p) ? min(abs(p-fp), abs(p-cp)) : vec2(max(abs(clp.x - p.x), abs(clp.y - p.y)), 1.0f);\n"
"float value = pow(clamp(1.1 - min(d.x,d.y), 0.0, 2.0), 8.0);\n"
"return vec3(max(0.0, value - 1.0), max(0.0, value - 1.0), min(value, 1.0));\n"
"}\n"
"\n"
"vec2 fixCoords(vec2 uv)\n"
"{\n"
"return vec2(coord.x * width / height, coord.y);\n"
"}\n"
"\n"
"vec3 castRay(vec3 end)\n"
"{\n"
"vec3 start = vec3(0.0, 0.0, end.z - 1.0);\n"
"return normalize(end - start);\n"
"}\n"
"\n"
"float hash(float n)\n"
"{\n"
"return fract(sin(n)*43758.5453);\n"
"}\n"
"\n"
"float cloudNoise(vec3 x)\n"
"{\n"
"vec3 p = floor(x);\n"
"vec3 f = fract(x);\n"
"f = f*f*(3.0-2.0*f);\n"
"float n = p.x + p.y*57.0 + 113.0*p.z;\n"
"return mix(\n"
"mix(\n"
"mix(hash(n+  0.0), hash(n+  1.0),f.x),\n"
"mix(hash(n+ 57.0), hash(n+ 58.0),f.x),f.y),\n"
"mix(\n"
"mix(hash(n+113.0), hash(n+114.0),f.x),\n"
"mix(hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);\n"
"}\n"
"\n"
"float sampleDensity(vec3 p, float time)\n"
"{\n"
"vec3 q = p - vec3(0.1, 0.1, -1.0) * time*0.5;\n"
"float f;\n"
"f  = 0.50000*cloudNoise(q); q = q * 2.02;\n"
"f += 0.25000*cloudNoise(q); q = q * 2.03;\n"
"f += 0.12500*cloudNoise(q); q = q * 2.01;\n"
"f += 0.06250*cloudNoise(q); q = q * 2.02;\n"
"f += 0.03125*cloudNoise(q);\n"
"return clamp(-0.5-p.y + 1.75 * f, 0.0, 1.0);\n"
"}\n"
"float sampleDensityLow(vec3 p, float time)\n"
"{\n"
"vec3 q = p - vec3(0.1, 0.1, -1.0) * time;\n"
"float f;\n"
"f  = 0.50000*cloudNoise(q); q = q * 2.02;\n"
"f += 0.25000*cloudNoise(q);\n"
"return clamp(-0.5-p.y + 1.75 * f, 0.0, 1.0);\n"
"}\n"
"\n"
"vec4 integrate(vec4 sum, float dif, float den, vec3 bgcol, float t)\n"
"{\n"
"// lighting\n"
"vec3 lin = vec3(0.65, 0.7, 0.75) * 1.4 + vec3(1.0, 0.6, 0.3) * dif;\n"
"vec4 col = vec4(mix(vec3(1.0, 0.95, 0.8), vec3(0.25, 0.3, 0.35), den), den);\n"
"col.xyz *= lin;\n"
"col.xyz = mix(col.xyz, bgcol, 1.0 - exp(-0.003 * t*t));\n"
"// front to back blending\n"
"col.a *= 0.4;\n"
"col.rgb *= col.a;\n"
"return sum + col*(1.0-sum.a);\n"
"}\n"
"\n"
"vec3 sundir = normalize(vec3(-1.0, 0.5, 1.0));\n"
"vec4 raymarchClouds(vec3 ro, vec3 rd, vec3 bgcol, float time, float len)\n"
"{\n"
"vec4 sum = vec4(0.0);\n"
"float t = 0.0;\n"
"\n"
"for(int i=0; i<10; i++)\n"
"{\n"
"vec3  pos = ro + t * rd;\n"
"if (pos.y < -3.0 || pos.y > 2.0 || sum.a > 0.99 || t > len)\n"
"break;\n"
"float den = sampleDensity(pos, time);\n"
"if (den > 0.01)\n"
"{\n"
"float dif =  clamp((den - sampleDensity(pos + 0.3 * sundir, time))/0.6, 0.0, 1.0);\n"
"sum = integrate(sum, dif, den, bgcol, t);\n"
"}\n"
"t += max(0.05, 0.02 * t);\n"
"}\n"
"for(int i=0; i<10; i++)\n"
"{\n"
"vec3  pos = ro + t * rd;\n"
"if (pos.y < -3.0 || pos.y > 2.0 || sum.a > 0.99 || t > len)\n"
"break;\n"
"float den = sampleDensityLow(pos, time);\n"
"if (den > 0.01)\n"
"{\n"
"float dif =  clamp((den - sampleDensityLow(pos + 0.3 * sundir, time))/0.6, 0.0, 1.0);\n"
"sum = integrate(sum, dif, den, bgcol, t);\n"
"}\n"
"t += max(0.05, 0.02 * t);\n"
"}\n"
"\n"
"return clamp(sum, 0.0, 1.0);\n"
"}\n"
"\n"
"vec3 sky(vec3 dir)\n"
"{\n"
"float sun = clamp(dot(sundir, dir), 0.0, 1.0);\n"
"vec3 col = vec3(0.5, 0.61, 0.85) - dir.y * 0.2 * vec3(1.0, 0.5, 1.0) + 0.15 * 0.5;\n"
"col += 0.2 * vec3(1.0, 0.6, 0.1) * pow(sun, 8.0);\n"
"return col;\n"
"}\n"
"\n"
"vec3 clouds(vec3 start, vec3 dir, float time, vec3 col, float len)\n"
"{\n"
"vec4 res = raymarchClouds(start, dir, col, time, len);\n"
"col = col*(1.0-res.w) + res.xyz;\n"
"return col;\n"
"}\n"
"\n"
"vec3 clare(vec3 dir, vec3 col)\n"
"{\n"
"float sun = clamp(dot(sundir, dir), 0.0, 1.0);\n"
"col += 0.2 * vec3(1.0, 0.4, 0.2) * pow(sun, 3.0);\n"
"return col;\n"
"}\n"
"\n"
"\n"
"// Signed distance fields\n"
"float sdSphere(vec3 p, float s)\n"
"{\n"
"return length(p) - s;\n"
"}\n"
"\n"
"float mangel(vec3 p)\n"
"{\n"
"vec3 w = p;\n"
"float m = dot(w,w);\n"
"float dz = 1.0;\n"
"\n"
"for( int i=0; i<4; i++ )\n"
"{\n"
"dz = 8.0*pow(sqrt(m),7.0)*dz + 1.0;\n"
"\n"
"mangelprotExpansion(w);\n"
"w = p+w;\n"
"\n"
"m = dot(w,w);\n"
"if( m > 256.0 )\n"
"break;\n"
"}\n"
"return 0.25*log(m)*sqrt(m)/dz;\n"
"}\n"
"\n"
"float mangelSdf(vec3 pos, float time)\n"
"{\n"
"pos = cartToPolar(pos);\n"
"pos.y += sin(time);\n"
"pos.z += 0.05*time;\n"
"pos = polarToCart(pos);\n"
"float dist = mangel(pos/3.0)*3.0;\n"
"return dist;\n"
"}\n"
"\n"
"vec3 mangelSdfNormal(vec3 pos, float px, float time)\n"
"{\n"
"vec2 eps = vec2( 0.25*px, 0.0 );\n"
"return normalize(vec3(\n"
"mangelSdf(pos+eps.xyy, time) - mangelSdf(pos-eps.xyy, time),\n"
"mangelSdf(pos+eps.yxy, time) - mangelSdf(pos-eps.yxy, time),\n"
"mangelSdf(pos+eps.yyx, time) - mangelSdf(pos-eps.yyx, time)));\n"
"}\n"
"\n"
"float sdf(vec3 pos, float time)\n"
"{\n"
"float st = sin(time);\n"
"float ct = cos(time);\n"
"float dist = sdSphere(pos, 1.0 + 0.2* sin(time * 5.0));\n"
"dist = expsmin(dist, sdSphere(pos+vec3(st, ct, 0.0), 0.2), 8.0);\n"
"dist = expsmin(dist, sdSphere(pos+vec3(ct, st, 0.0), 0.2), 8.0);\n"
"dist = expsmin(dist, sdSphere(pos+vec3(ct, 0.0, st), 0.2), 8.0);\n"
"dist = expsmin(dist, sdSphere(pos+vec3(0.0, st, ct), 0.2), 8.0);\n"
"dist = min(dist, sdSphere(pos+vec3(2.0 * st, 0.0, 2.0 * ct), 0.2));\n"
"dist = min(dist, sdSphere(pos+vec3(-3.0 * st, 0.0, -3.0 * ct), 0.2));\n"
"dist = min(dist, sdSphere(pos+vec3(-1.5 * st, -1.5 * st, -1.5 * ct), 0.2));\n"
"return dist;\n"
"}\n"
"\n"
"vec3 sdfNormal(vec3 pos, float px, float time)\n"
"{\n"
"vec2 eps = vec2( 0.25*px, 0.0 );\n"
"return normalize(vec3(\n"
"sdf(pos+eps.xyy, time) - sdf(pos-eps.xyy, time),\n"
"sdf(pos+eps.yxy, time) - sdf(pos-eps.yxy, time),\n"
"sdf(pos+eps.yyx, time) - sdf(pos-eps.yyx, time)));\n"
"}\n"
"\n"
"// Scene bases\n"
"vec3 scene1(float time)\n"
"{\n"
"vec3 col = white;\n"
"if (swayed(coord.y, time + 2.0 * fbm(coord, time), coord.x) < -0.05)\n"
"col = orange;\n"
"else if (swayed(coord.y, time + 2.0 * fbm(coord, time), coord.x) > 0.05)\n"
"col = teal;\n"
"float r = log(4.0 * distance(vec2(0.0,0.0), coord));\n"
"float phi = sin(atan(coord.x, coord.y) + time * 0.3);\n"
"float phi2 = sin(atan(coord.x, coord.y) - time * 0.3);\n"
"col *= r;\n"
"col *= fbm(vec2(r-time, phi * 4.0) * 2.0, time);\n"
"col *= fbm(vec2(r-time, phi2 * 2.0) * 2.0, time);\n"
"return col;\n"
"}\n"
"\n"
"vec3 scene2(float time)\n"
"{\n"
"vec2 fixedCoord = fixCoords(coord);\n"
"vec3 sphearePos = pounchingSphere(time);\n"
"if(distance(fixedCoord, sphearePos.xy) < 0.4f)\n"
"return sphereColor(fixedCoord, sphearePos, time, 0.4f);\n"
"else\n"
"return gridBack(fixedCoord, time);\n"
"}\n"
"\n"
"vec3 scene3(float time)\n"
"{\n"
"vec2 fix = fixCoords(coord);\n"
"vec3 start = vec3(fix, -3.0f);\n"
"vec3 dir = castRay(start);\n"
"\n"
"int steps = 0;\n"
"vec3 pos = start;\n"
"float dist = mangelSdf(pos, time);\n"
"while (dist > 0.01 && steps < 20)\n"
"{\n"
"steps++;\n"
"pos += dist * dir;\n"
"dist = mangelSdf(pos, time);\n"
"}\n"
"\n"
"return mangelSdfNormal(pos, 2.0/(height * 1.5), time);\n"
"}\n"
"\n"
"vec3 scene4(float time)\n"
"{\n"
"vec2 fix = fixCoords(coord);\n"
"vec3 start = vec3(fix, -3.0f);\n"
"vec3 dir = castRay(start);\n"
"float eps = 1.0/(height * 4.0);\n"
"int steps = 0;\n"
"vec3 pos = start;\n"
"float dist = sdf(pos, time);\n"
"while (dist > eps && steps < 30)\n"
"{\n"
"steps++;\n"
"pos += dist * dir;\n"
"dist = sdf(pos, time);\n"
"}\n"
"\n"
"vec3 col = vec3(0.,0.,0.);\n"
"if (dist < 0.005)\n"
"{\n"
"col = sdfNormal(pos, 2.0/(height * 1.5), time);\n"
"col += 0.2 * sky(col);\n"
"}\n"
"else\n"
"col = sky(dir);\n"
"col = clouds(start, dir, time, col, distance(start,pos));\n"
"col = clare(dir, col);\n"
"return col;\n"
"}\n"
"\n"
"// Scene selector\n"
"vec3 scene(float time)\n"
"{\n"
"if (time < scene1Start)\n"
"return fade(0.2f, scene1Start, time, black, scene1(time));\n"
"if (time < scene2Start - fadeLength)\n"
"return scene1(time);\n"
"if (time < scene2Start)\n"
"return fade(scene2Start - fadeLength, scene2Start, time, scene1(time), scene2(time - scene2Start));\n"
"if (time < scene3Start - fadeLength)\n"
"return scene2(time - scene2Start);\n"
"if (time < scene3Start)\n"
"return fade(scene3Start - fadeLength, scene3Start, time, scene2(time - scene2Start), scene3(time - scene3Start));\n"
"if (time < scene4Start - fadeLength)\n"
"return scene3(time - scene3Start);\n"
"if (time < scene4Start)\n"
"return fade(scene4Start - fadeLength, scene4Start, time, scene3(time - scene3Start), scene4(time - scene4Start));\n"
"return scene4(time - scene4Start);\n"
"}\n"
"\n"
"\n"
"// Get color from scene, turn time into seconds\n"
"// Clamp to visible spectrum\n"
"// Return with alpha\n"
"void main(){\n"
"vec3 rgb = scene(t / 1000.0);\n"
"rgb = clamp(rgb, 0.0, 1.0);\n"
"color = vec4(rgb, 1.0f);\n"
"}\n"
"\n"
;
