/************************************************************************** * TLSmoke.sl -- This is really Larry's noisysmoke.sl. I only took out the * random() as it made my animation look to funky -- tal 9/4/96 * * Description: * This is a volume shader for smoke. Trapezoidal integration is * used to integrate the GADD to find scattering and extinction. * * Parameters: * density - overall smoke density control * integstart, integend - bounds along the viewing ray direction of the * integration of atmospheric effects. * stepsize - step size for integration * use_lighting - if nonzero, light visibility along the ray will be taken * into account. * use_noise - makes the smoke noisy (nonuniform) when nonzero * freq, octaves, smokevary - control the fBm of the noisy smoke * lightscale - multiplier for light scattered toward viewer in volume * debug - if nonzero, copious output will be sent to stderr. * * Author: Larry Gritz * * History: * 9/4/96 tal -- took out random call and renamed to TLSmoke * * $Revision: 1.3 $ $Date: 1996-03-01 17:07:40-08 $ * * $Log: noisysmoke.sl,v $ * Revision 1.3 1996-03-01 17:07:40-08 lg * Eliminated duplicate local variable declarations * * Revision 1.2 1996-02-29 18:04:26-08 lg * Compute only one octave of noise when not lit (big speedup) * * Revision 1.1 1996-02-05 11:03:45-08 lg * Initial RCS revision * **************************************************************************/ #define snoise(p) (2*noise(p)-1) /* Here is where we define the GADD. */ #define GADD(PP,PW,li,g) \ if (use_lighting > 0) { \ li = 0; \ illuminance (PW, point(0,0,1), PI) { li += Cl; } \ } else { li = 1; } \ if (use_noise != 0) { \ Psmoke = PP*freq; \ smoke = snoise (Psmoke); \ /* Optimize: one octave only if not lit */ \ if (comp(li,0)+comp(li,1)+comp(li,2) > 0.01) { \ f=1; \ for (i=1; i<octaves; i+=1) { \ f *= 0.5; Psmoke *= 2; \ smoke += f*snoise(Psmoke); \ } \ } \ g = density * smoothstep(-1,1,smokevary*smoke); \ } else g = density; \ volume TLSmoke (float density = 60; float integstart = 0, integend = 100; float stepsize = 0.1; float debug = 0; float use_lighting = 1; float use_noise = 1; color scatter = 1; /* for sky, try (1, 2.25, 21) */ float octaves = 3, freq = 1, smokevary = 1; float lightscale = 15; ) { #ifdef BMRT point Worigin = P + I; point incident = vtransform ("shader", -I); #else /* PRMan and BMRT have I reverse of each other, conflict in spec */ point Worigin = P - I; point incident = vtransform ("shader", I); #endif point origin = transform ("shader", Worigin); point IN, WIN; float d, sigma, tau; color Cv = 0, Ov = 0; /* net color & opacity of volume */ color dC, dO; /* differential color & opacity */ float ss, dtau, last_dtau, end; float nsteps = 0; /* record number of integration steps */ color li, last_li, lighttau; point PP, PW, Psmoke; color scat; float f, i, smoke; end = min (length (incident), integend) - 0.0001; /* Integrate forwards from the start point */ d = integstart + /*random()* */ stepsize; if (d < end) { IN = normalize (incident); WIN = vtransform ("shader", "current", IN); PP = origin + d * IN; PW = Worigin + d * WIN; GADD (PP, PW, li, dtau) ss = min (stepsize, end-d); d += ss; nsteps += 1; while (d <= end) { last_dtau = dtau; last_li = li; PP = origin + d*IN; PW = Worigin + d*WIN; GADD (PP, PW, li, dtau) /* Our goal now is to find dC and dO, the color and opacity * of the portion of the volume covered by this step. */ tau = .5 * ss * (dtau + last_dtau); lighttau = .5 * ss * (li*dtau + last_li*last_dtau); scat = -tau * scatter; dO = 1 - color (exp(comp(scat,0)), exp(comp(scat,1)), exp(comp(scat,2))); dC = lighttau * dO; /* Now we adjust Cv/Ov to account for dC and dO */ Cv += (1-Ov)*dC; Ov += (1-Ov)*dO; ss = max (min (ss, end-d), 0.005); d += ss; nsteps += 1; } } /* Ci & Oi are the color (premultiplied by opacity) and opacity of * the background element. * Now Cv is the light contributed by the volume itself, and Ov is the * opacity of the volume, i.e. (1-Ov)*Ci is the light from the background * which makes it through the volume. */ Ci = lightscale*Cv + (1-Ov)*Ci; Oi = Ov + (1-Ov)*Oi; if (debug > 0) { printf ("nsteps = %f, t1 = %f, end = %f\n", nsteps, integstart, end); printf (" Cv = %c, Ov = %c\n", Cv, Ov); } }