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;
}

HOME

NEW

LINKS

GALLERY

ARTICLES

PLUG-INS

RENDERMAN

Switch to Frame View




Copyright © 1997 by WebNation
All trademarks are the property of their respective holders