/* swirl2.sl ======== A PoVMan shader file to produce swirled patterns. Author: ------ Written by Michael Andrews, 9th July 2001 Version 0.2 alpha It uses the voronoi_f1f2_3d() function from the voronoi.sl released with PoVMan. Purpose: ------- This shader was designed to be used as a displace warp to swirl a texture. The RGB colours correspond to the XYZ displacement. Problems: -------- The coordinate space transforms ... I have no idea which to use. The current transforms seem to work at the origin but not when translated. Parameters: ---------- point Dir: either a point, a vector or not used depending on 'Type'. float Rot: maximum number of swirl rotations. float Type: chooses how the axis of rotation for the swirls is determined. 0: Axis = Dir 1: Axis = P - Dir 2: Axis = Ng float Power: alters the 'centralness' of the swirls; higher number, tighter at centre. float Steps: how many parts to break the axis rotation into; more give a smoother swirl; 5 works well. */ void voronoi_f1f2_3d(point PP; float jitter; output float f1; output point pos1; output float f2; output point pos2;) { point thiscell = point(floor(xcomp(PP))+0.5, floor(ycomp(PP))+0.5, floor(zcomp(PP))+0.5); f1 = f2 = 1000; uniform float i, j, k; for (i=-1; i<=1; i += 1){ for (j=-1; j<=1; j += 1){ for (k=-1; k<=1; k += 1){ point testcell = thiscell+vector(i,j,k); point pos = testcell + jitter*(vector cellnoise(testcell)-0.5); vector offset = pos - PP; float dist = offset.offset; if (dist < f1){ f2 = f1; pos2 = pos1; f1 = dist; pos1 = pos; } else if (dist < f2){ f2 = dist; pos2 = pos; } } } } f1 = sqrt(f1); f2 = sqrt(f2); } surface swirl_pattern(point Dir=(0,0,1); float Rot=0, Type=0, Power=1, Steps=1) { point P2; float f1, f2, R; uniform float i; point pos1, pos2; point PP = P; vector Axis; // Need to move into shader coordinate space. Correct transforms here? // Determine axis direction from 'Type', may add other types later. // Do I need to use different transforms for the different types? P2 = PP = transform("object", "shader", P); if (Type == 0){ Axis = normalize(vtransform("world", "shader", vector(Dir))); } else if (Type == 1){ Axis = normalize(vector(PP - transform("object", "shader", Dir))); } else if (Type == 2){ Axis = normalize(vector(ntransform("object", "shader", Ng))); } // Start of iteration loop. for (i = 0; i < Steps; i += 1) { // Find voronoi info. voronoi_f1f2_3d(P2, 1, f1, pos1, f2, pos2); // Calculate rotation amount. R = Rot * 2 * PI * pow(max(0,1-f1) * (f2-f1), 0.5*Power) / Steps; // Rotate point about Axis. P2 = rotate(P2, R, pos1, pos1+Axis); } // Convert the offset back into original coordinates? // Which coordinate space does the displacement warp use? Ci = color(vtransform ("shader", "object", vector(P2 - PP))); }