a_spiral(color bakcolor = 1,
color pencolor = 0,
float center_s = 0.5,
float center_t = 0.5,
float coeff = 0.03 [[string help = "Smaller values create more turns"]],
float blur = 0.03 [[string help = "Adjust to avoid artifacts"]],
float s = 0 [[int lockgeom = 0]],
float t = 0 [[int lockgeom = 0]],
output color resultRGB = 0)
resultRGB = 1;
float R, theta;
// Convert the s,t location of the shading point to polar coordinates.
float xdiff = s - center_s, ydiff = t - center_t;
R = sqrt(xdiff * xdiff + ydiff * ydiff);
theta = atan2(ydiff, xdiff); // -PI to PI radians
if(theta < 0.0)
theta += M_2PI; // 0 to 2PI radians
// Remap theta from 0 to 2PI radians to the range 0.0 to 1.0
float percent_theta = theta/M_2PI;
// The unitRadius defines the maximum size of the spiral when
// theta is 2PI radians ie. 360 degrees. Unless it's size is
// tweaked by the blur factor "cycles" increments before theta
// reaches 2PI and the spiral will have breaks ie. artifacts.
float unitRadius = coeff * M_2PI + mix(-blur,blur,percent_theta);
// If the radial distance of shading point is, say, 1.5 the unit
// radius is somewhere within the 2nd "turn" of the spiral.
float turns = floor(R/unitRadius);
theta = theta + turns * M_2PI;
// Use "turns" to calculate the full rotational angle.
theta = coeff * theta;
// Determine how close the shading point is to the "true" spiral
float blend = smoothstep(0, blur, abs(theta - R));
resultRGB = mix(pencolor, bakcolor, blend);
// Uncomment the next couple of lines if you wish to view the
// unitRadius. Because it is calculated with the addition of a
// value based on blur and theta, the unitRadius defines a circle
// with a gap, the size of which is twice the width of blur.
if(abs(R - unitRadius) < 0.002)
resultRGB = color(1,0,0);