Preview
precision highp float;
#define SHADERTOY 0
#define PI 3.141592654
#define saturate(a) clamp(a, 0., 1.)
#define range(a, b) (step(a, floor(time2)) * step(floor(time2), b))
const int maxIteration = 128;
const float fmaxIteration = float(maxIteration);
uniform float time;
uniform vec2 resolution;
float time0, time1, time2, zoom, a;
int iter;
float box(vec3 p, float b) {
vec3 d = abs(p) - b;
return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0));
}
mat2 rot(float a) {
float c = cos(a), s = sin(a);
return mat2(c, -s, s, c);
}
vec3 hue(float hue) {
vec3 rgb = fract(hue + vec3(0., 2. / 3., 1. / 3.));
rgb = abs(rgb * 2. - 1.);
return clamp(rgb * 3. - 1., 0., 1.);
}
vec3 hsvToRgb(vec3 hsv) { return ((hue(hsv.x) - 1.) * hsv.y + 1.) * hsv.z; }
float hash11(float p) {
vec3 p3 = fract(vec3(p) * .1031);
p3 += dot(p3, p3.yzx + 19.19);
return fract((p3.x + p3.y) * p3.z);
}
mat2 rot1, rot2, rot3, rot4;
vec2 ifs(vec3 p) {
float d1 = 999., d2 = 999.;
float range = .8, radius = .5 * (1. + zoom);
const float maxIter = 8.;
for (int i = int(maxIter); i > 0; i--) {
if (i <= iter) {
break;
}
float ratio = float(i) / maxIter;
float bx = box(p, radius * ratio);
d1 = mix(d1, min(d1, bx), float(i > iter + 1));
d2 = min(d2, bx);
ratio *= ratio;
p.xz = abs(p.xz) - range * ratio * .7;
p.xz *= rot1;
p.yz *= rot3;
p.yx *= rot2;
p.yz = abs(p.yz) - range * ratio * .7;
p.xz *= rot1;
p.yz *= rot4;
p.yx *= rot2;
}
return vec2(d1, d2);
}
float map(vec3 p) {
vec2 d = ifs(p);
return mix(mix(d.y, d.x, a), mix(d.x, d.y, a), step(time0, 5.5));
}
float calcAo(vec3 p, vec3 n) {
float sca = 1.0, occ = 0.0;
for (float i = 0.; i < 5.; i++) {
float hr = 0.05 + i * 0.08;
float dd = map(n * hr + p);
occ += (hr - dd) * sca;
sca *= 0.5;
}
return saturate(1.0 - occ);
}
vec3 intersect(vec3 ro, vec3 ray) {
float t = 0.0;
for (int i = 0; i < maxIteration; i++) {
float res = abs(map(ro + ray * t));
if (res < 0.005) return vec3(t, res, i);
t += res;
}
return vec3(-1.0);
}
vec3 normal(vec3 pos, float e) {
vec2 eps = vec2(1.0, -1.0) * 0.5773 * e;
return normalize(eps.xyy * map(pos + eps.xyy) +
eps.yyx * map(pos + eps.yyx) +
eps.yxy * map(pos + eps.yxy) +
eps.xxx * map(pos + eps.xxx));
}
mat3 createCamera(vec3 ro, vec3 ta, float cr) {
vec3 cw = normalize(ta - ro);
vec3 cp = vec3(sin(cr), cos(cr), 0.0);
vec3 cu = normalize(cross(cw, cp));
vec3 cv = normalize(cross(cu, cw));
return mat3(cu, cv, cw);
}
float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); }
float noise(vec2 x) {
vec2 i = floor(x), f = fract(x);
float a = hash(i);
float b = hash(i + vec2(1.0, 0.0));
float c = hash(i + vec2(0.0, 1.0));
float d = hash(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
}
float fbm(vec2 p) {
const mat2 m2 = mat2(0.8, -0.6, 0.6, 0.8);
p.xy += 0.1 * time1;
float f = 0.5000 * noise(p); p = m2 * p * 2.02;
f += 0.2500 * noise(p); p = m2 * p * 2.03;
f += 0.1250 * noise(p); p = m2 * p * 2.01;
f += 0.0625 * noise(p);
return f / 0.9375;
}
vec3 sky(vec3 ro, vec3 ray) {
vec3 col = vec3(0.);
float rd = ray.y + 0.3;
col = mix(col, vec3(2.0, 0.25, 2.0), 0.5 * smoothstep(0.5, 0.8, fbm((ro.xz + ray.xz * (250000.0 - ro.y) / rd) * 0.000008)));
col = mix(col, vec3(0.), pow(1.0 - max(rd, 0.0), 4.0));
col = mix(vec3(0.), col, saturate(time1 * 3. - 4.));
col = mix(col, vec3(0.), saturate(time1 - 5.25));
return col * 1.3;
}
#define edge(start, end, sStart, sEnd, ecol) if (range(start, end) > 0.) { showEdge = 1.; float offs = pos.y - mix(sStart, sEnd, 0.025 + saturate(time2 - start)); edgeColor = ecol; edgeIntensity = mix(0., edgeIntensity, saturate(1. - abs(offs))); col = mix(col, objectColor, saturate(1. - (offs + 1.5))); }
vec3 render(vec2 p) {
float t = time0 * 0.7 - 1.;
float offs = mix(1., hash11(max(1., floor(t * 4.))), smoothstep(0., .5, time0));
vec3 ro = vec3(cos(t * 3.5) * 11., sin(t * 3.9) * 4.5, sin(t * 1.5) * 10.) * 0.7;
t = time1 * 0.7;
offs = mix(mix(1., hash11(max(1., floor(t * 4.))), step(0., time1)), 1., step(4.6, time1));
ro = mix(ro, vec3(cos(t * 1.5) * 11. * offs, sin(t * 2.) * 4. * offs * 2., sin(t * 1.5) * 20. * offs) * 0.9, smoothstep(0.7, 1., time1));
ro = mix(ro, vec3(cos(t * 1.5) * 11., sin(t * 3.9) * 4., sin(t * 1.5) * 10.), smoothstep(4.6, 5.5, time1));
ro = mix(ro, vec3(5., 3., 5.), saturate(time1 - 6.7));
vec3 ta = vec3(0.0, 0.0, (sin(t * 0.55) * 0.5 + 0.5) * 2.0);
ta = mix(ta, vec3(0.), saturate(time1 - 6.7));
mat3 cm = createCamera(ro, ta, 0.);
vec3 ray = cm * normalize(vec3(p, 4.0));
vec3 res = intersect(ro, ray);
if (res.y < -0.5) {
return sky(ro, ray);
}
vec3 pos = ro + ray * res.x;
vec3 nor = normal(pos, 0.008);
float glowIntensity = saturate(pow(abs(1. - abs(dot(nor, ray))), 1.));
vec3 objectColor = (vec3(.003, .001, .0095)
* pow(1. / res.z * 1.5, -1.8) + glowIntensity * vec3(.1, .25, .3)) * res.x * 0.3
* calcAo(pos, nor)
+ sky(ro, normalize(reflect(ray, nor))) * .4 * (1. - zoom);
float a = smoothstep(0.3, 0.7, pow(fract(time0 * 3.), 0.4));
float edgeThreshold = mix(0.02, 0.03, (1. - a) * (1. - zoom));
float edgeIntensity = smoothstep(edgeThreshold - 0.01, edgeThreshold, length(nor - normal(pos, .015)));
float noShade = range(-10., 3.);
vec3 col = mix(objectColor, vec3(0.), noShade);
float showEdge = 0.;
vec3 edgeColor = vec3(1.);
vec3 rainbow = hue(pos.z / 2.);
edge(3., 3.5, -2., 2.2, hue(abs(offs) / 5. + .5) * 2.)
edge(6., 6.5, -3.5, 2., rainbow)
edge(5., 5.5, -3.5, 2., rainbow)
edge(10., 10.5, -3.5, 2., rainbow)
edge(11.5, 12., -3.5, 2.4, rainbow)
if (time2 > 16.5) {
showEdge = 1.;
offs = pos.y - mix(-3.5, 4., saturate(time2 - 16.5));
col = mix(objectColor, vec3(0.), saturate(1. - offs));
edgeIntensity = mix(0., edgeIntensity, saturate(1. - (offs + .6)));
}
col += edgeColor * edgeIntensity * step(1., zoom + noShade + showEdge);
col = mix(col, 1. - col, zoom);
return col;
}
vec2 shake(float t) {
float s = t * 50.0;
return (vec2(hash11(s), hash11(s + 11.0)) * 2.0 - 1.0) * exp(-5.0 * t) * 0.2;
}
vec3 vignette(vec2 p) {
p *= 1.0 - p.yx;
return vec3(1.2, 1.1, .85) * pow(16. * p.x * p.y * (1. - p.x) * (1. - p.y), 0.125);
}
void entryPoint(in vec2 coord, in vec2 resolution, in float time, out vec4 color) {
vec2 p = (coord.xy * 2.0 - resolution.xy) / min(resolution.x, resolution.y);
time -= 3.;
time0 = mod(time * 0.4, 11.);
time1 = time0 - 11. / 4.;
time2 = time1 * 0.7 * 4.;
float t = time0 * 3.;
iter = int(mix(clamp(14. - floor(t), 0., 7.), min(8., floor(t) - 24.), step(24., floor(t))));
a = mix(1., smoothstep(0.3, 0.7, pow(fract(t), 0.4)), step(7.5, t));
t = time1 * 3.;
float angle = step(1.2, time1) * (floor(t + 0.5) + smoothstep(0.3, 0.7, pow(fract(t + 0.5), 0.4)));
rot1 = rot(0.785397);
rot2 = rot(1.7079);
rot3 = rot(angle * 1.2 + 424. + step(7.035716, time0) * 3.);
rot4 = rot(angle * 1.2 + 226.);
zoom = range(8., 9.) + range(11., 11.5);
p = mix(p, vec2(1. + hash11(p.y) * 10., p.y), saturate(time0 - 10.33) * 5.);
p += shake(fract(time1 * 2.)) * 0.10;
p *= 1.0 + 5. * pow(length(p), 1.5) * zoom;
vec3 col = render(p);
col *= vignette(coord.xy / resolution.xy);
col = mix(col, vec3(0.), saturate(time0 - 10.33) * 10. + step(time, 0.));
color = vec4(col, 1.0);
}
void
#if SHADERTOY == 1
mainImage(out vec4 fragColor, in vec2 fragCoord) { entryPoint(fragCoord.xy, iResolution.xy, iTime, fragColor); }
#else
main(void) { entryPoint(gl_FragCoord.xy, resolution.xy, time, gl_FragColor); }
#endif