/* I took wave's lead and renamed starfield to KMCyclone.sl -- tal AT renderman DOT org */
/*
* cyclone.sl - surface for a semi-opaque cloud layer to be put on an
* earth-like planetary model to model clouds and a cyclone.
*
* DESCRIPTION:
* When put on a sphere, sets the color & opacity of the sphere to
* make it look like the clouds surrounding an Earth-like planet, with
* a big cyclone.
* The shader works by creating a fractal turbulence function over
* the surface, then modulating the opacity based on this function in
* a way that looks like clouds on a planetary scale.
*
*
* PARAMETERS:
* Ka, Kd - the usual meaning
* cloudcolor - the color of the clouds, usually white
* max_radius
* twist - controls the twisting of the clouds due to the cyclone.
* offset, scale - control the linear scaling of the cloud value.
* omega, octaves - controls the fractal characteristics of the clouds
*
*
* HINTS:
* See the "planetclouds" shader for hints which apply equally well
* to this shader.
*
*
* AUTHOR: Ken Musgrave
* Conversion to Shading Language and other minor changes by Larry Gritz.
*
* REFERENCES:
* _Texturing and Modeling: A Procedural Approach_, by David S. Ebert, ed.,
* F. Kenton Musgrave, Darwyn Peachey, Ken Perlin, and Steven Worley.
* Academic Press, 1994. ISBN 0-12-228760-6.
*
* HISTORY:
* ???? - original texture developed by Ken Musgrave.
* Feb 1994 - Conversion to Shading Language by L. Gritz
*
* last modified 1 March 1994 by lg
*/
#define TWOPI (2*PI)
/* Use signed Perlin noise */
#define snoise(x) ((2*noise(x))-1)
#define DNoise(p) (2*(point noise(p)) - point(1,1,1))
#define VLNoise(Pt,scale) (snoise(DNoise(Pt)+(scale*Pt)))
#define VERY_SMALL 0.001
surface
KMCyclone (float Ka = 0.5, Kd = 0.75;
float max_radius = 1;
float twist = 0.5;
float scale = .7, offset = .5;
float omega = 0.675;
float octaves = 4;)
{
float radius, dist, angle, sine, cosine, eye_weight, value;
point Pt; /* Point in texture space */
point PN; /* Normalized vector in texture space */
point PP; /* Point after distortion */
float l, o, a, i; /* Loop control for fractal sum */
/* Transform to texture coordinates */
Pt = transform ("shader", P);
/* Rotate hit point to "cyclone space" */
PN = normalize (Pt);
radius = sqrt (xcomp(PN)*xcomp(PN) + ycomp(PN)*ycomp(PN));
if (radius < max_radius) { /* inside of cyclone */
/* invert distance from center */
dist = pow (max_radius - radius, 3);
angle = PI + twist * TWOPI * (max_radius-dist) / max_radius;
sine = sin (angle);
cosine = cos (angle);
PP = point (xcomp(Pt)*cosine - ycomp(Pt)*sine,
xcomp(Pt)*sine + ycomp(Pt)*cosine,
zcomp(Pt));
/* Subtract out "eye" of storm */
if (radius < 0.05*max_radius) { /* if in "eye" */
eye_weight = (.1*max_radius - radius) * 10; /* normalize */
/* invert and make nonlinear */
eye_weight = pow (1 - eye_weight, 4);
}
else eye_weight = 1;
}
else PP = Pt;
if (eye_weight > 0) { /* if in "storm" area */
/* Compute VLfBm */
l = 1; o = 1; a = 0;
for (i = 0; i < octaves && o >= VERY_SMALL; i += 1) {
a += o * VLNoise (PP * l, 1);
l *= 2;
o *= omega;
}
value = abs (eye_weight * (offset + scale * a));
}
else value = 0;
/* Thin the density of the clouds */
Oi = value * Os;
/* Shade like matte, but with color scaled by cloud opacity */
Ci = Oi * (Ka * ambient() + Kd * diffuse(faceforward(normalize(N),I)));
}