Inflection mapping in Fragmentarium with complex dual-numbers for automatic differentiation for distance estimate:
#include "Progressive2D.frag"
vec2 cMul(vec2 a, vec2 b)
{
return vec2(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
}
vec2 cSqr(vec2 a)
{
return cMul(a, a);
}
vec4 cMul(vec4 a, vec4 b)
{
return vec4(cMul(a.xy, b.xy), cMul(a.xy, b.zw) + cMul(a.zw, b.xy));
}
vec4 cSqr(vec4 a)
{
return cMul(a, a);
}
const vec2 cs[8] = vec2[8]
( vec2(-1.5, 0.0)
, vec2(-2.0, 0.0)
, vec2(-1.5, 0.0)
, vec2(-2.0, 0.0)
, vec2(-1.5, 0.0)
, vec2(-2.0, 0.0)
, vec2(-1.5, 0.0)
, vec2(-2.0, 0.0)
);
vec3 color(vec2 c0)
{
float px = length(vec4(dFdx(c0), dFdy(c0)));
vec4 c = vec4(c0, px, 0.0);
for (int i = 8-1; i >= 0; --i)
{
vec4 f = vec4(cs[i], 0.0, 0.0);
vec4 d = c - f;
c = f + cSqr(d);
}
int n = 0;
vec4 z = vec4(0.0, 0.0, 0.0, 0.0);
for (n = 0; n < 1000; ++n)
{
if (dot(z.xy, z.xy) >= 65536.0)
break;
z = cSqr(z) + c;
}
if (dot(z.xy, z.xy) < 65536.0)
return vec3(1.0, 0.0, 0.0);
float r = length(z.xy);
float dr = length(z.zw);
float de = 2.0 * r * log(r) / dr;
float g = tanh(clamp(de, 0.0, 4.0));
if (isnan(de) || isinf(de) || isnan(g) || isinf(g))
g = 1.0;
return vec3(g);
}