Shaders
texbomb - A texture bombing shader
/* texbomb.sl - dsward@webnation.com
* docs available at <http://www.webnation.com/vidirep/>
*
* Bombed, rotated textures with color variations, transparency mapping.
* The surface is subdivided into a grid and multiple instances of the
* texture are psuedorandomly distributed on the surface.
* Textures may jitter into neighboring cells.
*
* based on Steve May's Renderman notes at http://www.cgrg.ohio-state.edu/~smay/RManNotes
* and _Texturing and Modeling, A Procedural Approach_ by Darwyn Peachey, et al, ISBN 0-12-228760-6
*
* Parameters -
* scale: a positive integer, sets dimensions of bombing grid,
* e.g. scale = 4 sets a 4-by-4 grid on the surface
* frequency: 0.0 to 1.0
* e.g. frequency = 0.5 applies texture to half the cells in grid
* layers: for multiple bombing passes
* e.g. layers = 2 bombs the grid twice
* noise_scale: sampling interval of the noise() function
* rot_min, rot_max: range of possible texture rotations, in degrees
* texture_name: file name of the color texture map, e. g. "leaf.tex"
* alpha_name: file name of the transparency map, e. g. "leaf.texa"
* uses grayscale values, 0.0 = transparent, 1.0 = opaque
* vary_color: maximum color variation for RGB color channels
* e. g. vary_color = color(0.5, 0, 0) varys red channel plus or minus 0.5
* shading_method:
* shading_method = 0 - constant shading
* shading_method = 1 - plastic shading
* uses Ka, Kd, Ks, roughness, specular_color
* shading_method = 2 - matte shading
* uses Ka, Kd
* Ka, Kd, Ks, roughness, specular_color: the usual meanings
*
* Revision history -
* December 12, 1996 - First release
* December 30, 1996 - Calculate max_jitter to prevent cropping at tile boundaries.
*
*
*/
/* Steve May's functions for uniform distributed noise, tiling, rotation and blending */
#define udn(x,lo,hi) (smoothstep(.25, .75, noise(x)) * ((hi) - (lo)) + (lo))
#define whichtile(x,freq) (floor((x) * (freq)))
#define rotate2d(x,y,rad,ox,oy,rx,ry) \
rx = ((x) - (ox)) * cos(rad) - ((y) - (oy)) * sin(rad) + (ox); \
ry = ((x) - (ox)) * sin(rad) + ((y) - (oy)) * cos(rad) + (oy)
#define blend(a,b,x) ((a) * (1 - (x)) + (b) * (x))
surface texbomb(
float scale = 4;
float frequency = 0.5;
float layers = 1;
float noise_scale = 10;
float rot_min = 0;
float rot_max = 360;
string texture_name="";
string alpha_name="";
color vary_color = color(0, 0, 0);
float shading_method = 0;
float Ka = 1;
float Kd = 0.5;
float Ks = 0.5;
float roughness = 0.1;
color specular_color = 1)
{
color surface_color, layer_color;
color surface_opac, layer_opac;
float ss, tt, tmps, tmpt;
float home_row, home_col;
float layer_idx, col_idx, row_idx;
float cell_size;
float half_cell;
float col, row;
float noi;
float swidth, twidth;
point Nf, V;
float ds,dsu,dsv,dt,dtu,dtv;
float rel_s, rel_t;
float jitter_s, jitter_t;
float center_s, center_t;
float sMin, sMax, tMin, tMax;
float inBounds;
float max_jitter;
surface_color = Cs;
surface_opac = 0;
layer_color = Cs;
layer_opac = 0;
home_col = whichtile(s, scale);
home_row = whichtile(t, scale);
cell_size = 1 / scale;
half_cell = cell_size / 2;
for (layer_idx = 0; layer_idx < layers; layer_idx += 1)
{
/* scan current cell and neighbors, 9 cells total */
for (col_idx = -1; col_idx <= 1; col_idx += 1)
{
for (row_idx = -1; row_idx <= 1; row_idx += 1)
{
/* determine row and column index, wraparound */
rel_s = s;
rel_t = t;
col = home_col + col_idx;
if (col < 0)
{
rel_s = s + 1;
col = scale - 1;
}
if (col >= scale)
{
rel_s = s - 1;
col = 0;
}
row = home_row + row_idx;
if (row < 0)
{
rel_t = t + 1;
row = scale - 1;
}
if (row >= scale)
{
rel_t = t - 1;
row = 0;
}
/* base seed to udn on current layer, row and column of tile */
noi = noise(point (col * noise_scale + 0.5, row * noise_scale + 0.5,
layer_idx * noise_scale + 0.5));
/* generate tile based on noise < frequency */
if (udn(noi * 313, 0, 1) < frequency)
{
/* calculate jitter */
max_jitter = cell_size * 0.8;
jitter_s = udn(noi * 1183, -max_jitter, max_jitter);
jitter_t = udn(noi * 999, -max_jitter, max_jitter);
/* calculate center of texture on surface */
center_s = (col * cell_size) + half_cell + jitter_s;
center_t = (row * cell_size) + half_cell + jitter_t;
/* rotate around center of texture */
rotate2d(rel_s, rel_t,
radians(udn(noi * 777, rot_min, rot_max)),
center_s, center_t,
tmps, tmpt);
/* calculate boundaries for texture in this layer */
sMin = center_s - half_cell;
sMax = center_s + half_cell;
tMin = center_t - half_cell;
tMax = center_t + half_cell;
/* determine if the current point on the surface is in the texture area */
inBounds = 1;
if (tmps <= sMin) inBounds = 0;
if (tmps >= sMax) inBounds = 0;
if (tmpt <= tMin) inBounds = 0;
if (tmpt >= tMax) inBounds = 0;
if (inBounds == 1)
{
/* calculate texture coordinates */
ss = (tmps - sMin) * scale;
tt = (tmpt - tMin) * scale;
/* see Pixar's texmap.sl for explanation of area sampling */
swidth = abs(Du(ss) * du) + abs(Dv(ss) * dv);
twidth = abs(Du(tt) * du) + abs(Dv(tt) * dv);
dsu = abs(Du(ss)*du);
if((2*dsu) > swidth) dsu = swidth - dsu;
dsv = abs(Dv(ss)*dv);
if((2*dsv) > swidth) dsv = swidth - dsv;
ds = dsu + dsv;
dtu = abs(Du(tt)*du);
if((2*dtu) > twidth) dtu = twidth - dtu;
dtv = abs(Dv(tt)*dv);
if((2*dtv) > twidth) dtv = twidth - dtv;
dt = dtu + dtv;
if (texture_name != "")
{
/* get color from texture map*/
layer_color = color texture(texture_name, ss,tt, ss+ds,tt, ss,tt+dt, ss+ds,tt+dt);
}
else
{
layer_color = surface_color;
}
/* mix in the color variation for this layer */
layer_color = color(
comp(layer_color, 0) + udn(noi * 1234, -comp(vary_color, 0), comp(vary_color, 0)),
comp(layer_color, 1) + udn(noi * 2345, -comp(vary_color, 1), comp(vary_color, 1)),
comp(layer_color, 2) + udn(noi * 3456, -comp(vary_color, 2), comp(vary_color, 2)));
if (alpha_name != "")
{
/* get opacity from texture map*/
layer_opac = color texture(alpha_name, ss,tt, ss+ds,tt, ss,tt+dt, ss+ds,tt+dt);
}
else
{
layer_opac = color 1;
}
/* overlay the color and opacity for this layer */
surface_color = blend(surface_color, layer_color, layer_opac);
surface_opac = max(surface_opac, layer_opac);
}
}
}
}
}
/* output */
/* output - default is constant shading method */
if (shading_method == 0)
{
surface_color = surface_opac * surface_color;
}
if (shading_method == 1)
{
/* plastic method */
Nf = faceforward(normalize(N), I);
V = -normalize(I);
surface_color = surface_opac * (surface_color * (Ka * ambient() + Kd * diffuse(Nf)) +
specular_color * Ks * specular(Nf, V, roughness));
}
if (shading_method == 2)
{
/* matte method */
Nf = faceforward(normalize(N), I);
surface_color = surface_opac * (surface_color * (Ka * ambient() + Kd * diffuse(Nf)));
}
Ci = surface_color;
Oi = surface_opac;
}
All trademarks are the property of their respective holders