/*author Stephen Hopkins, shopkins@usc.edu
bark displacement usage:
--------------------------------------
-a displacement bound needs to be added to the shader, use attributes->renderman->add displacement attr
this value can be set a little bit above the barckThickness. Increase the value if square holes/artifacts occur in the displacement
-sFreq and tFreq should be kept at a ratio of at least 2 to 1 to maintain the vertical appearance of bark
the default values I set for these work well with a cylinder of radius ~1 inside maya.
-barkThickness is the maximum amount of displacement created by the bark
-holeDepth is the maximum amount of noise subtracted from the bark
-holeDistanceScale should remain untouched unless there seems to be little variation across the surface. Decreasing the distanceScale will amplify
everything else and may overflow the noise if set too low. Normally this is computed in the 1st pass, with a second pass rescaling
all the noise with this value, but I don't know how to do that with renderman.
*/
#define sqr(x) (x * x)
#define negOneToOne(x) (2. * x - 1.)
#define zeroToOne(x) ((x + 1.) / 2.)
#include "worley.c"
float bias(float b; float x){
return pow(x, log(b)/log(0.5));
}
//convert vector 0 to 1 -> -1 to 1
void negOneToOneVector(output vector v){
setxcomp(v, negOneToOne(xcomp(v)));
setycomp(v, negOneToOne(ycomp(v)));
setzcomp(v, negOneToOne(zcomp(v)));
}
displacement barkDisp(float sFreq = 4, tFreq = 1.5, barkThickness = 0.21, barkDistanceScale = 0.8, holeDepth = .25, holeDistanceScale = .8){
vector freq = (sFreq, tFreq, sFreq);
point wp = transform("object", P);
wp *= freq;
//bark pieces
//1 * F1 - 1 * F0
float barkScalars[2] = {1, -1};
float barkIndices[2] = {1, 0};
float maxPointsPerCell = 3;
float wa1 = 1, wa2 = .5, wa3 = .15;
float barkDistanceScale = 0.8;
float w = 0;
float w1 = wa1 * negOneToOne(clamp(worleyNoise(wp / wa1, maxPointsPerCell, 2, barkScalars, barkIndices, "mink") / barkDistanceScale, 0, 1));
float w2 = wa2 * negOneToOne(clamp(worleyNoise(wp / wa2, maxPointsPerCell, 2, barkScalars, barkIndices, "mink") / barkDistanceScale, 0, 1));
float w3 = wa3 * negOneToOne(clamp(worleyNoise(wp / wa3, maxPointsPerCell, 2, barkScalars, barkIndices, "mink") / barkDistanceScale, 0, 1));
w += w1 + w2 + w3;
w /= wa1 + wa2 + wa3;
w = zeroToOne(w);
//holes
//1 * F0
float holeScalars[1] = {1};
float holeIndices[1] = {0};
float holeFreq = sFreq * 2.5;
point hp = transform("object", P) * holeFreq;
float ha1 = 1;
float ha2 = .5;
float ha3 = .25;
float h = 0;
float h1 = ha1 * negOneToOne(clamp(worleyNoise(hp, 6 / ha1, 1, holeScalars, holeIndices, "") / holeDistanceScale, 0, 1));
float h2 = ha2 * negOneToOne(clamp(worleyNoise(hp / ha2, 6, 1, holeScalars, holeIndices, "") / holeDistanceScale, 0, 1));
float h3 = ha3 * negOneToOne(clamp(worleyNoise(hp / ha3, 6, 1, holeScalars, holeIndices, "") / holeDistanceScale, 0, 1));
h += h1 + h2 + h3;
h /= ha1 + ha2 + ha3;
h = zeroToOne(h);
float holes = - holeDepth * (1 - h);// * barkThickness;
w += holes;
vector nn = faceforward(normalize(N), I);
vector displace = nn * w * barkThickness;
P += displace;
N = calculatenormal(P);
}