/*
* Renamed to JMredapple.sl for RMR -- tal AT renderman DOT org 7/18/99
*
* redapple.sl - A nice shader for reddy-green apples.
*
* Copyright (C) Jonathan Merritt, 1999.
* Feel free to use this shader to create apples anywhere and
* everywhere.
*
* This shader creates a nice skin for red-green apples. It _is_ tuned
* for specific geometry, but can very easily be adjusted to fit any
* apple you care to lay it on. Apples are requred to have the "s"
* texture parameter running equatorialy around them (like latitude
* lines), and "t" running from pole to pole (like longditude). Apples
* look best from the side, but work ok from the top, so long as you
* don't mind the simple lerping I used to fade to green at the poles.
*
* Look out for the "txtscale" parameter: some noise calculations are
* done using shader space, instead of "s" and "t" parameters (I think
* my apple's parameters are stretched a bit?), so if you use
* different size apples, make sure to change txtscale appropriately.
*
* I think this shader is really cool. If you think so too, you can
* email me your praises, notification of my credits in big motion
* pictures, job offers at Pixar, etc... to: jmerritt AT warpax DOT com :-)
*
* Have FUN!!! :-)
*/
/*#define USE_LG_RAYTRACE */
#ifdef USE_LG_RAYTRACE
#include "rayserver.h"
#include "raytrace.h"
#endif
#ifndef snoise
#define snoise(x) (2*noise(x)-1) /* 1-D signed noise */
#endif
#define TSCALE .05
surface
JMredapple (
float Ks = .25; /* Specular reflection coeff. */
float Kd = .5; /* Diffuse reflection coeff. */
float Ka = 1; /* Ambient light coeff. */
float Kr = .05; /* Mirror-like reflection coeff. */
float roughness = .1; /* Specular roughness param. */
float label = 0; /* Non-uniformity param. */
float redness = 1; /* Amount of 'redness' - higher */
/* values give redder apples. */
/* 2 = almost complete red. */
float txtscale = .05; /* Ugly kludge (see above...) */
color specularcolor = 1; /* Specular reflection color */
)
{
/*
* Shader variables
*/
vector Nf, V, Rdir;
point PP, newP;
float base_turb, blotch_turb, disp_turb;
float small_noise, blotch, speck, disp = 0, blackness;
color cs, small_speckle, base_color, reflect;
/*
* Some nice colors for our red apple
*/
color red = color(0.52,0.00,0.00);
color dred = color(0.40,0.00,0.00);
color green = color(0.76,0.80,0.37);
color brown = color(0.70,0.78,0.34);
color black = color(0.00,0.00,0.00);
/*
* Standard settings
*/
PP = transform("shader", P);
V = normalize(-I);
/*
* Pick the base color for the apple.
*
* The base color consists of patches of pure green,
* and patches of finely speckled red and green. These
* are set up so that the poles of the apple (as "t"
* goes to 1 or 0) are colored more and more green.
*
* The apple geometry is such that lines of constant
* "t" are lines of longditude (from pole to pole).
* The constants T1 - T4 specify locations of the
* start of 'greenness' toward the poles.
*/
#define BASE_SF 1.2 /* s-factor for big noise */
#define BASE_TF 3 /* t-factor for big noise */
#define BASE_NF 100 /* scaling factor for small noise */
#define BASE_NOISE_AMP 0.2 /* small noise color mix amplitude */
#define BASE_GRC 0.4 /* shift factor for more red */
#define T1 0.0 /* t < T1 is pure green */
#define T2 0.18 /* lerp s.t. T1->T2 => green->red */
#define T3 0.8 /* T2->T3 => red can exist here */
#define T4 1.0 /* lerp s.t. T3->T4 => red->green */
/* t > T4 is pure green */
base_turb = noise(BASE_SF*sin(2*PI*s) + PI + label,
BASE_TF*t + label);
base_turb = pow(base_turb, (1/redness));
small_noise = snoise(BASE_NF*PP*txtscale/TSCALE);
small_speckle = mix(red, green, BASE_GRC+
(small_noise*BASE_NOISE_AMP));
if (t < T1)
base_turb = 0;
else if (t >= T1 && t < T2)
base_turb *= (t-T1)/(T2-T1);
else if (t >= T3 && t < T4)
base_turb *= (T4-t)/(T4-T3);
else if (t >= T4)
base_turb = 0;
base_color = spline(base_turb, green, green,
small_speckle, small_speckle,
small_speckle);
/*
* Pick the blotch color.
*
* The blotch color is finally determined by mixing,
* using the blotching coefficient "blotch". This
* section sets that coefficient, using a funky yet
* really simple noise routine.
*/
#define BLOTCH_SF 20 /* s-factor for blotches */
#define BLOTCH_TF 15 /* t-factor for blotches */
#define BLOTCH_TCF 2.5 /* scaling kludge */
#define BLOTCH_DELTA 0.1 /* 'nother scaling kludge */
#define BLOTCH_SPECK_COEFF 0.3 /* blotch specking coeff */
blotch_turb = noise(BLOTCH_SF*sin(2*PI*(s+.1234)) + PI + label,
BLOTCH_TF*t + label) + BLOTCH_DELTA;
blotch = pow(blotch_turb, 1.3) * BLOTCH_TCF *
pow(base_turb, 2);
blotch = blotch * (1+small_noise) +
small_noise * BLOTCH_SPECK_COEFF;
if (blotch > 1) blotch = 1;
/*
* Set the brown specking.
*
* The apple has brown speckles on it, set by mixing
* using the speckling coefficient "speck". These
* specks are very dot-like in nature, and this
* dottiness technique is stolen from LG's starfield
* shader.
*/
#define SPECK_NF 50 /* A noise scaling factor */
#define SPECK_CUTOFF .45 /* Cutoff for 'tops' of specks */
speck = pow(smoothstep(SPECK_CUTOFF, 1,
noise(SPECK_NF*PP*txtscale/TSCALE)), 3);
/*
* Determine where the apple goes black at the poles.
* This simulates the spots where the stalk would be
* attached, and where the wierd bit at the very bottom
* is.
*/
#define BEDGE .01
#define BWIDTH .01
blackness = 1-(smoothstep(BEDGE, BEDGE+BWIDTH, t)*
smoothstep(BEDGE, BEDGE+BWIDTH, 1-t));
/*
* Combine what we have so far to set the surface
* color.
*/
cs = mix(base_color, dred, blotch);
cs = mix(cs, brown, speck);
cs = mix(cs, black, blackness);
/*
* Set the shading surface normal.
*
* Here we set the surface normal to fix up the specular
* highlights. We'd like them perturbed by the small
* noise, affected a little by the brown specks, and
* also dented a bit (alas, no real apples are perfectly
* un-dented).
*/
#define DISP_SF 10 /* s-factor for dent noise */
#define DISP_TF 30 /* t-factor for dent noise */
#define DISP_DENT_AMP (1/15) /* dent amplitude */
#define DISP_SMNOISE_AMP (1/1000) /* small noise amplitude */
#define DISP_SPECK_AMP (1/40) /* speckle disp. amplitude */
disp += noise(DISP_SF*sin(2*PI*s) + PI + label,
DISP_TF*t + label) * DISP_DENT_AMP * txtscale / TSCALE;
disp += small_noise * DISP_SMNOISE_AMP * txtscale / TSCALE;
disp -= speck * DISP_SPECK_AMP * txtscale / TSCALE;
newP = calculatenormal(P + disp * normalize(N));
Nf = faceforward(normalize(newP), I);
/*
* 'Mirror' reflections
*
* Here, we raytrace for the slight mirrored reflections
* in the surface of an apple. They don't add much, but
* may be needed for the 'perfect' apple :-).
*
* Note: You'll need Larry Gritz's raytrace helper files
* for this bit!
*/
#ifdef USE_LG_RAYTRACE
if (Kr > .01) {
Rdir = normalize(reflect(normalize(I), Nf));
reflect = RayTrace(P, Rdir, 0, 1, 1);
} else {
reflect = 0;
}
#else
reflect = 0;
#endif
/*
* Combine everything to get Ci, in the standard form.
*/
Oi = Os;
Ci = Os * (cs * (Ka*ambient() + Kd*diffuse(Nf)) +
specularcolor * (Kr * reflect +
Ks * specular(Nf, V, roughness)));
}