mathr / blog / #

Calendar 2015 - Donut

Donut

I blogged about this before with an animation (Rolling Torus), the only thing missing now is the Fragmentarium source code, so here it is:

#define providesColor
#include "Soft-Raytracer.frag"

uniform float time;

const float pi = 3.141592653;
const float s = 2.0;
const float ri = s / (sqrt(s * s + 1.0) + 1.0);
const float ro = s / (sqrt(s * s + 1.0) - 1.0);
const float rc = 0.5 * (ro + ri);
const float rt = 0.5 * (ro - ri);

const vec3 rgb[5]  = vec3[](
  vec3(1.0, 0.7, 0.0),
  vec3(0.7, 1.0, 0.0),
  vec3(0.0, 0.7, 1.0),
  vec3(0.7, 0.0, 1.0),
  vec3(1.0, 0.0, 0.7));

float torus(vec3 z) {
  return length(z - rc * normalize(vec3(z.xy, 0.0))) - rt;
}

float plane(vec3 z) {
  return z.z;
}

vec3 spin(vec3 z) {
  float a = 2.0 * pi * time / 3.0;
  mat2 m = mat2(cos(a), sin(a), -sin(a), cos(a));
  z.xy = m * z.xy;
  return z.xzy - vec3(0.0,ro,0.0);
}

vec3 baseColor(vec3 q, vec3 n) {
  vec2 uv = vec2(0.0);
  if (q.z < 0.01) {
   uv = q.xy * sqrt(5.0);
  } else {
    vec3 p = spin(q);
    float k = -1.0;
    float l = 1.0;
    if (p.z > 0.0) { l = -l; }
    if (length(p.xy) > rc) { k = -k; }
    float a = (p.z * p.z * sqrt(s * s + 1.0) +
      k * sqrt(max(1.0 - p.z * p.z * s * s, 0.0))) / (p.z * p.z + 1.0);
    float y = l * acos(clamp(a, -1.0, 1.0)) / (2.0 * pi);
    float x = s * atan(p.x, p.y) / (2.0 * pi);
    if (x < 0.0) { x = s + x; }
    if (y < 0.0) { y = 1.0 + y; }
    x = 5.0 * x;
    y = 5.0 * y;
    uv = vec2(y, x);
    float b = atan(1.0, 2.0);
    mat2 m = mat2(cos(b), sin(b), -sin(b), cos(b)) * sqrt(5.0);
    uv = m * uv;
  }
  vec3 t;
  if (mod(uv.x, 1.0) < 0.25 || mod(uv.y, 1.0) < 0.25) {
    t = vec3(0.0);
  } else {
    int k = clamp(int(mod(floor(uv.x) + 2.0 * floor(uv.y), 5.0)), 0, 4);
    t = rgb[k];
  }
  return vec3(t);
}

float  DE(vec3 z) {
  return min(torus(spin(z)), plane(z));
}

#preset default
FOV = 0.3
Eye = -5,-5,2.25
Target = -0.593772,1.17202,1.5097
Up = 0,0,1
EquiRectangular = false
FocalPlane = 5
Aperture = 0.01062
Gamma = 1
ToneMapping = 1
Exposure = 1
Brightness = 1
Contrast = 1
Saturation = 1
GaussianWeight = 5.2308
AntiAliasScale = 1.7333
Detail = -5.47582
DetailAO = -3.26669
FudgeFactor = 1
MaxRaySteps = 317
BoundingSphere = 12
Dither = 1
NormalBackStep = 1
AO = 0,0,0,0.32456
Specular = 0.2
SpecularExp = 24.051
SpotLight = 0.737255,0.686275,0.533333,1.8841
SpotLightPos = 10,-5.0684,8.0822
SpotLightSize = 2.3
CamLight = 0.792157,0.556863,0.682353,0.6579
CamLightMin = 3e-05
Glow = 0,0.917647,1,0
GlowMax = 16
Fog = 0
Shadow = 0.82906 NotLocked
Sun = -1.29354,1.01588
SunSize = 0.001
Reflection = 0 NotLocked
BaseColor = 1,1,1
OrbitStrength = 1
X = 0.5,0.6,0.6,0.7
Y = 1,0.6,0,0.4
Z = 0.8,0.78,1,0.5
R = 0.4,0.7,1,0.12
BackgroundColor = 0.501961,0.501961,0.501961
GradientBackground = 1.66665
CycleColors = false
Cycles = 0.1
EnableFloor = false NotLocked
FloorNormal = 0,0,0
FloorHeight = 0
FloorColor = 1,1,1
#endpreset