Figured out the single helix version, by realizing that the line through a point to the nearest point on the surface must lie on a plane containing the axis of the helix. There are three candidate points, conceptualized as the two neighbouring arcs above and below, and the arc opposite:
```
#version 330 compatibility
#define providesColor
#include "MathUtils.frag"
#include "Complex.frag"
#include "DE-Raytracer.frag"
#group Helix
uniform float HelixD; slider[0.0,2.0,10.0]
uniform float HelixR; slider[0.0,1.0,10.0]
uniform float Helixr; slider[0.0,0.5,10.0]
uniform float time;
float DE(vec3 q)
{
q.z += time * 2.0 * PI * HelixD;
float dz = mod(q.z + HelixD * atan(q.y, q.x) + PI * HelixD, 2.0 * PI * HelixD) - PI * HelixD;
float xy = length(q.xy);
float d1 = length(vec2(xy - HelixR, dz - PI * HelixD));
float d2 = length(vec2(xy + HelixR, dz));
float d3 = length(vec2(xy - HelixR, dz + PI * HelixD));
return min(min(d1, d2), d3) - Helixr;
}
vec3 baseColor(vec3 q, vec3 n)
{
return vec3(0.5) + 0.5 * cross(n, normalize(vec3(-1.0, 1.0, -1.0)));
}
```
Managed to fractalize a variant based on a sheared stack of toruses (such that the ends join up into a helix). Still has assumptions about the rise per revolution being small, but it turned out well. Rendered with "Raymond", my physically-inspired raytracer, using a material similar to water but more extreme in both index of refraction and absorption coefficients.
Render at 3840x2160 with 256 subframes took about 1.5 hours. Exported from FragM in EXR format, colour balance adjusted in Darktable, cropped/framed in GNU IMP.
Just realized I made a mistake in my realization that happens to result in ok images when the rise per revolution is small. Correcting: the line is perpendicular to the tangent of the curve which is not parallel to the axis when the curve is "tilted" as in a helix...