Appolloian with a twist II
Shader ported from: https://www.shadertoy.com/view/7d2fDW
Shader code
shader_type canvas_item;
const int MAX_MARCHES = 30;
const float TOLERANCE = 0.0001;
const float PI = 3.141592654;
const float TAU = (2.0*PI);
mat2 ROT(float a){
return mat2(vec2(cos(a),sin(a)),vec2(-sin(a),cos(a)));
}
// License: Unknown, author: nmz (twitter: @stormoid), found: https://www.shadertoy.com/view/NdfyRM
float sRGB1(float t) { return mix(1.055*pow(t, 1./2.4) - 0.055, 12.92*t, step(t, 0.0031308)); }
// License: Unknown, author: nmz (twitter: @stormoid), found: https://www.shadertoy.com/view/NdfyRM
vec3 sRGB(in vec3 c) { return vec3 (sRGB1(c.x), sRGB1(c.y), sRGB1(c.z)); }
// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
const vec4 hsv2rgb_K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 hsv2rgb(vec3 c) {
vec3 p = abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www);
return c.z * mix(hsv2rgb_K.xxx, clamp(p - hsv2rgb_K.xxx, 0.0, 1.0), c.y);
}
float apolloian(vec3 p, float s, out float h) {
float scale = 1.0;
for(int i=0; i < 5; ++i) {
p = -1.0 + 2.0*fract(0.5*p+0.5);
float r2 = dot(p,p);
float k = s/r2;
p *= k;
scale *= k;
}
vec3 ap = abs(p/scale);
float d = length(ap.xy);
d = min(d, ap.z);
float hh = 0.0;
if (d == ap.z){
hh += 0.5;
}
h = hh;
return d;
}
float df(vec2 p, out float h) {
const float fz = 1.0-0.0;
float z = 1.55*fz;
p /= z;
vec3 p3 = vec3(p,0.1);
p3.xz*=ROT(0.5*0.1*TIME);
p3.yz*=ROT(sqrt(0.5)*0.1*TIME);
float d = apolloian(p3, 1.0/fz, h);
d *= z;
return d;
}
float shadow(vec2 lp, vec2 ld, float mint, float maxt) {
const float ds = 1.0-0.4;
float t = mint;
float nd = 1E6;
float h;
const float soff = 0.05;
const float smul = 1.5;
for (int i=0; i < MAX_MARCHES; ++i) {
vec2 p = lp + ld*t;
float d = df(p, h);
if (d < TOLERANCE || t >= maxt) {
float sd = 1.0-exp(-smul*max(t/maxt-soff, 0.0));
return t >= maxt ? mix(sd, 1.0, smoothstep(0.0, 0.025, nd)) : sd;
}
nd = min(nd, d);
t += ds*d;
}
float sd = 1.0-exp(-smul*max(t/maxt-soff, 0.0));
return sd;
}
vec3 effect(vec2 p, vec2 q) {
float a = 0.1*TIME;
vec2 lightPos = vec2(0.0, 1.0);
lightPos *= (ROT(sqrt(0.5)*0.1*TIME));
vec2 lightDiff = lightPos - p;
float lightD2 = dot(lightDiff,lightDiff);
float lightLen = sqrt(lightD2);
vec2 lightDir = lightDiff / lightLen;
vec3 lightPos3 = vec3(lightPos, 0.0);
vec3 p3 = vec3(p, -1.0);
float lightLen3 = distance(lightPos3, p3);
vec3 lightDir3 = normalize(lightPos3-p3);
vec3 n3 = vec3(0.0, 0.0, 1.0);
float diff = max(dot(lightDir3, n3), 0.0);
float h;
float d = df(p, h);
float ss = shadow(p,lightDir, 0.005, lightLen);
vec3 bcol = hsv2rgb(vec3(fract(h-0.2*length(p)+0.25*TIME), 0.666, 1.0));
vec3 col = vec3(0.0);
col += mix(0., 1.0, diff)*0.5*mix(0.1, 1.0, ss)/(lightLen3*lightLen3);
col += exp(-300.0*abs(d))*sqrt(bcol);
col += exp(-40.0*max(lightLen-0.02, 0.0));
return col;
}
void fragment() {
vec2 q = FRAGCOORD.xy/(1.0 / SCREEN_PIXEL_SIZE).xy;
vec2 p = -1. + 2. * q;
p.x *= (1.0 / SCREEN_PIXEL_SIZE).x/(1.0 / SCREEN_PIXEL_SIZE).y;
vec3 col = effect(p, q);
col *= mix(0.0, 1.0, smoothstep(0.0, 4.0, TIME));
col = sRGB(col);
COLOR = vec4(col, 1.0);
}