|  | 
shader 
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);
*/
}
 |