#include "noises.h"
#include "filterwidth.h"
#include "raysphere.h"
//! Macro
/**
* A macro to normalize a given value to a specified range.
* \param mi - the minimum value of the range
* \param mx - the maximum value of the range
* \param value - the value to be normalized
* \return the normalized value
*/
#define normalizeRange(mi,mx,value) (value-mi)/(mx-mi)
//! The Bark2 Shader
/**
* This file contains the Bark2 displacement shader.
* @author Hannes Ricklefs - NCCA 2005
*/
//! A Function
/**
* Calculate the voronoi pattern. This function has been taken
* from the supporting material of the Advanced Renderman Book.
* It has been included to be more obvious to the author.
* \param P - position to test
* \param jitter - how much to jitter the cell center positions (1 is typical,
* smaller values make a more regular pattern, larger values
* make a more jagged pattern; use jitter >1 at your risk!).
* \param f1, f2 - distance to the nearest feature (f1 is closest, f2 is the
* distance to the 2nd closest)
* \param pos1, pos2 - the position of the nearest feature
*/
void
voronoi(point P;
float jitter;
output float f1; output point pos1;
output float f2; output point pos2;
)
{
//cellcenter
point thiscell = point (floor(xcomp(P))+0.5, floor(ycomp(P))+0.5,
floor(zcomp(P))+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);
//featurepos
point pos = testcell +
jitter * (vector cellnoise (testcell) -0.5);
vector offset = pos - P;
float dist = offset . offset; /* actually dist^2 */
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);
}
//! The displacement shader
/**
* This displacement shader provides the main functionality to create photo realitc looking
* tree bark. The main aspect is the use of a fractal voronoi pattern.
* The best approach in using this shader is to test different values for the crack_stretch vector
* as this vector provides the way of controlling the voronoi pattern. In order to stretch the pattern
* the user should apply a vector where the value of the direction to stretch in is less than the other
* two directions. Depending on the given geometry these values could range between 0.1 - 1 or 1 - 20.
* Once the desired displacement is achieved the user should use the provided normalrange.pl script to
* identify the range of displacement this pattern generate. The resulting min and max values should be
* passed into lowNormaliseRange and topNormaliseRange respectively.
*
* Inputs:
* \param Km - a scale value for the overall texture. Should be mostly in the range 0.05 - 0.2
* \param fBmoctaves - the octaves of the Fractional Brownian Motion in order to affect the cracks.
* \param fBmlacunarity - the lacunarity of the Fractional Brownian Motion in order to affect the cracks.
* \param fBmgain - the gain of the Fractional Brownian Motion in order to affect the cracks.
* \param turboctaves - the octaves of the Turbulence in order to add turbulence to the overall texture.
* \param turblcunarity - the lacunarity of the Turbulence in order to add turbulence to the overall texture.
* \param turbgain - the gain of the Turbulence in order to add turbulence to the overall texture.
* \param barksmoothness - scales the Fractional Motion applied to the cracks
* \param squarness_of_bark_patches - will be passed to the jitter of the voronoi function jitter> 1 at your own risk
* \param crack_detail - the amount of times the voronoi pattern should be applied, increase in high increases your render times
* \param lowNormaliseRange - the min value calculated by the displacement inorder to normalise the output hump.
* .The normlrange.pl script should be used to calculate the min value.
* \param topNormaliseRange - the max value calculated by the displacement inorder to normalise the output hump.
* .The normlrange.pl script should be used to calculate the max value.
* \param space - the space in which the shader should be be applied
* \param crack_strech - stretches the voronoi pattern by this vector
*
* Outputs:
* \param hump - the displacement normalise according to lowNormaliseRange and topNormaliseRange
* \param cellid - the cellid of the voronoi pattern at this point
*/
displacement Bark2( uniform float Km = 0.1;
float fBmoctaves=6,
fBmlac=2,
fBmgain=0.5,
turboctaves=4,
turblac=2,
turbgain=0.5,
barksmoothness=0.07,
squareness_of_bark_patches=1,
crack_detail=10,
lowNormaliseRange=0.712768,
topNormaliseRange=2.883801;
string space="shader";
vector crack_stretch=(0.5,0.25,0.5);
output varying float hump = 0;
output varying point cellid = 0) {
//Declare the positions for the nearest and second nearest feature.
point pos1, pos2;
//Declare the distance to the nearest and second nearest feature as
//well as the differance between the two.
float f1, f2, diff;
//Standard shader initialisation calls
normal n = normalize(N);
normal nf = faceforward(n,I);
point PP = transform(space,P);
//Transform the vector into the relevant space inorder to stretch the voronoi pattern
vector cs = vtransform(space,crack_stretch);
// Noise for the cracks
PP = PP + (barksmoothness*vfBm(2*PP,filterwidthp(PP),fBmoctaves,fBmlac,fBmgain));
//stretch the voronoi pattern
PP = point (comp(cs,0) * comp(PP,0), comp(cs,1) * comp(PP,1), comp(cs,2) * comp(PP,2));
//apply the voronoi function
voronoi(PP,squareness_of_bark_patches,f1,pos1,f2,pos2);
/* The voronoi cell */
cellid = pos1 * 10;
/* The difference */
diff = 1-(f2-f1);
//Values for the fractal voronoi pattern
float i = 0;
//The amplitude
float amp = 1.0;
/* fractal higher frequnecy and lower amplitude */
for(i = 0; i < crack_detail; i+=1) {
PP = transform(space,P);
/* Noise for the cracks */
PP = PP + (barksmoothness*vfBm(2*PP,filterwidthp(PP),fBmoctaves,fBmlac,fBmgain));
PP = point (comp(cs,0) * comp(PP,0), comp(cs,1) * comp(PP,1), comp(cs,2) * comp(PP,2));
voronoi(PP,squareness_of_bark_patches,f1,pos1,f2,pos2);
/* The difference */
diff = 1-(f2-f1);
/* turbulence for the humps */
hump += amp* (1-(smoothstep(0.77,0.95,diff)) + turbulence(PP,filterwidthp(PP),turboctaves,turblac,turbgain));
cs = cs * 1.56;
amp *= 0.6;
}
/* Recalculte the surface */
P = P + n * hump * Km ;
/* Normalize the output of hump for the color */
//printf ("%f\n",hump);
hump = normalizeRange(lowNormaliseRange,
topNormaliseRange,
hump);
//Recalculate the values
N = calculatenormal(P);
n = normalize(N);
nf = faceforward(n,I);
}