Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Advanced_Renderman_Book[torrents.ru]

.pdf
Скачиваний:
1741
Добавлен:
30.05.2015
Размер:
38.84 Mб
Скачать

324 12 A Gallery of Procedural Shaders

Figure 12.14 Example use of the lensflare shader. See also color plate 12.14.

a disk with a smooth outer falloff (which we call a "blot"), and a disk with less intensity in the middle (which for no apparent reason we call a "bloon"). The final shader shows the implementation of all these features and contains parameters that allow the user to choose the total number of spots as well as the relative proportions of disks, rings, blots, and bloons.

Don't spend much time trying to justify the physical processes that lie behind these effects-there really aren't any. Our shader vaguely mimics some artifacts from real lens flare but also makes up several that don't occur in real lens systems.

You should be aware that lens flare effects are a cliche (an expression that once was fresh but has become dull and stereotyped through frequent repetition). They were clever and interesting the first few times they were used, but now any clod can and does sprinkle lens flare in images where it doesn't belong. Lens flare, perhaps because it is so low-key and rare in real life but so over-the-top in CG images, can easily give a CG image a "cheesy," amateurish look. So use this shader (Listing 12.7) wisely-which means rarely, if at all, and without cranking the parameters to outrageous values. A moderately tasteful example of the final shader is shown in Figure 12.14, but frankly, even this image is pushing it.

32

12.7 Lens Flare and "Clipping Plane" Shaders

Listing 12.7 The lensflare.sl shader.

/***********************************************************************************

*lensflare.sl

*Description: This shader, when placed on a piece of geometry

*immediately in front of the camera, simulates lens flare.

*These effects happen in real cameras when the camera points

*toward a bright light source, resulting in interreflections

*within the optical elements of the lens system itself.

*Real lens flare is pretty plain looking and uninteresting;

*this shader takes some liberties but looks pretty good.

*Parameters:

*intensity - overall scale of intensity of all lens flare effects

*bloomintensity - overall intensity of the "bloom" effect. Setting this to 0

*removes the bloom effect altogether.

*bloomradius, bloomfalloff - control the size & shape of the bloom

*bloomstarry, bloomnpoints - control the "starry" appearance of the bloom

*effect (bloomstarry=0 means perfectly round bloom)

*starburstintensity - overall intensity of starburst effect (0=none)

*starburstradius, starburstnpoints, starburstfalloff - contro the size and

*shape of the starburst effect

*rainbowintensity - intensity of rainbow effect (0=none)

*rainbowradius, rainbowwidth - size of the rainbow

* nspots - number of "spots" splayed out on the axis joining the image

*(center with the light position

*disky, ringy, blotty, bloony - give the relative proportions of the 4

*different kinds of spots.

*spotintensity - overall intensity scale for the spots

*spotvarycolor - scale the color variation of the spots

*seed - random number seed for many of the computations

*WARNING: lens flare is notorious as a sign of cheesy, cheap

*computer graphics. Use this effect with extreme care!

************************************************************************************/

#include "patterns.h"

/* Helper function: compute the aspect ratio of the frame */ float aspectratio ( )

{

uniform point Pcorner0 = transform ("NDC", "screen", point<0,0,0));

uniform point Pcornerl = transform ("NDC", "screen", point(1,1,0));

return (xcomp(Pcornerl)-xcomp(Pcorner0)) / (ycomp(Pcornerl)-ycomp(Pcorner0));

}

326 12 A Gallery of Procedural Shaders

Listing 12.7 (continued)

/* Helper function: compute the camera's diagonal field of view */ float cameradiagfov ()

{

uniform vector corner = vector (transform("NDC","camera", point(1,1,0)));

uniform float halfangle = acos (normalize(corner) . vector(0,0,1)); return 2*halfangle;

}

color rainbow (float x, dx)

{

 

#define R

color(1,0,0)

#define 0

color(1,.5,0)

#define Y

color(1,1,0)

#define G

color(0,1,0)

#define B

color(0,0,1)

#define Ii

color(.375,0,0.75)

#define V

color(0.5,0,0.5)

return filteredpulse (0, 1, x, dx) * spline (x, V,V,Ii,B,G,Y,O,R,R);

}

surface

lensflare (float intensity = 1.0;

float bloomintensity = 1; float bloomradius = 0.5; float bloomstarry = 0.75; float bloomnpoints = 25; float bloomfalloff = 8;

float starburstintensity = 0.075; float starburstradius = 0.5; float starburstnpoints = 100; float starburstfalloff = 3;

float rainbowintensity = 0.03; float rainbowradius = 0.5; float rainbowwidth = 0.2;

float nspots = 50; float disky = 3; float ringy = 1; float blotty = 1; float bloony = 1;

float spotintensity = 0.08; float spotvarycolor = 0.5;

float seed = 143;

)

327

12.7 Lens Flare and "Clipping Plane" Shaders

Listing 12.7 (continued)

{

uniform float nrand = 0; uniform float urand ( ) {

extern uniform float nrand, seed; nrand += 1;

return cellnoise(nrand, seed);

}

Ci = 0;

Oi = 0;

uniform float aspect = abs(aspectratio()); uniform float lensfov = cameradiagfov();

point Pndc = (transform("NDC", P) - vector (.5, .5, 0))*2; Pndc *= vector(aspect, 1, 0);

float dPndc = filterwidthp(Pndc);

illuminance (P, vector "camera" (0,0,1), PI/2) {

float atten = acos(zcomp(normalize(vector transform("camera", P+L))));

atten = 1 - smoothstep(1, 2, abs(atten)/(lensfov/2));

float brightness = atten*intensity*(comp(C1,0)+comp(C1,1)+comp (C1,2))/3;

color Cflare = 0;

nrand = 0;

point Plight = (transform("NDC", P+L) - vector (.5, .5, 0))*2; Plight *= vector(aspect, 1, 0);

vector Lvec = Plight - Pndc;

float angle = atan (ycomp(Lvec), xcomp(Lvec)) + PI;

/*

*Handle the image of the lamp. There are 3 effects:

*the bloom, a small red ring flare, and the triple starburst.

*/

float dist = length(Plight - Pndc);

if (bloomintensity > 0) {

float radius = sqrt(brightness)*5*mix(.2, bloomradius, urand()); float bloom = pnoise (bloomnpoints*angle/(2*PI), bloomnpoints); bloom = mix (0.5, bloom, bloomstarry);

bloom = mix (1, bloom, smoothstep(0, 0.5, dist/radius));

bloom = pow(1-smoothstep(0.0, radius*bloom, dist),bloomfalloff); Cflare += bloom * (bloomintensity / intensity) / brightness;

}

328 12 A Gallery of Procedural Shaders

Listing 12.7 (continued)

/* Starburst */

if (starburstintensity > 0) {

float radius = sqrt(brightness)*5*mix(.2, starburstradius, urand()); float star = float pnoise (starburstnpoints*angle/(2*PI),

starburstnpoints);

star = pow(1-smoothstep(0.0, radius*star, dist), starburstfalloff); Cflare += star * (starburstintensity / intensity) / brightness;

}

/* Rainbow */

if (rainbowintensity > 0) {

Cflare += brightness*(rainbowintensity / intensity) * rainbow((dist/rainbowradius-1)/rainbowwidth,

(dPndc/rainbowradius)/rainbowwidth);

}

/*

*Now emit the random rings themselves

*/

vector axis = normalize(vector Plight); uniform float i;

nrand = 20; /* Reset on purpose! */ for (i = 0; i < nspots; i += 1) {

uniform float alongaxis = urand();

point cntr = point (mix(-1.7, 1.7, alongaxis) * axis); float axisdist = distance (cntr, Pndc);

float radius = mix (0.04, .1,

pow(urand(),2)) * distance(cntr,Plight);

color Or = C1;

clr *= 1 + spotvarycolor * (color cellnoise(i) - 0.5); float bright = 1 - (2 * radius);

bright *= bright;

uniform float alltypes = (disky+ringy+blotty+bloony); uniform float type = urand()*alltypes;

float int = 0;

if (type < disky) { /* Flat disk */

int = 1 - filterstep(radius, axisdist-dPndc/2, axisdist+dPndc/2);

} else if (type < (disky+ringy)) { /* Ring */

int = filteredpulse (radius, radius+0.05*axisdist, axisdist, dPndc);

}else if (type < (disky+ringy+blotty)) { /* Soft spot */ int = 1 - smoothstep (0, radius, axisdist);

}else { /* Spot with soft hole in middle */

int = smoothstep(0, radius, axisdist) -

329

12.8 Cartoon Shaders

Listing 12.7 (continued)

filterstep(radius, axisdist-dPndc/2, axisdist+dPndc/2);

}

Cflare += spotintensity * bright * clr * Cs * int;

}

Ci += Cflare * C1 * atten;

}

Ci *= intensity;

}

So why, with all these caveats about lens flare, do we present it at all? Because (1) it shows how easy it may be in RenderMan to implement something that is nominally impossible, given the right inspiration and a little shader hackery; and (2) it shows, just in case you remain unconvinced, that there is often no need to be slavishly bound to physical processes as long as the result is coherent in a way that convinces the observer of its reality. This lens flare thus achieves photosurrealism, and we still hope to inspire others along this line.

12.8Cartoon Shaders

We will conclude this chapter with a totally different kind of shader that produces a decidedly nonphotorealistic appearance. We will attempt to simulate a cartoony look, as you would see in a traditional cel-painted animation. This has become a popular topic lately, as most or all recent 2D cel animations incorporate 3D elements into certain sequences. The trick is to avoid a jarring juxtaposition of styles when the 3D elements are combined with the real paintings by giving the 3D elements a look similar to the 2D artwork.

The approach we will take is surely naive, and much more robust methods with more controls would be required for a final shader used in a feature film. However, our shader will do the basic job and should give a sense for the technique, and possibly serve as a starting point for a more complete implementation. In addition, Chapter 16 covers additional and more complete techniques for "nonphotorealistic" rendering.

Our simplistic approach will concentrate on two primary features of the cel painting appearance. First, we note that cel paintings do not show continuous gradation of color, as do 3D renderings. Rather, there are typically only three flat colors: specular highlights, diffusely lit, and shadowed. Second, objects and characters in cel paintings are typically given thick, dark outlines.

LocIllumGlossy
(right).

330 12 A Gallery of Procedural Shaders

Figure 12.1 5 Working toward a cel-painting appearance. A red plastic teapot (left). Using and LocIllumCelDiffuse illumination models to create a "flat" look

Recall the LocIllumGlossy model that we described in Section 9.5.3. With the parameters set correctly, this provided a specular highlight that ramped up to full intensity quickly and was flat in the center. This will serve well as our model for highlights in our cel-paintings. We can also construct an analogous local illumination function for diffuse light:

color LocIllumCelDiffuse ( normal N;

{

color C = 0; extern point P;

illuminance (P, N, PI/2) {

extern vector L; extern color Cl; float nondiff = 0;

lightsource ("__nondiffuse", nondiff); if (nondiff < 1)

C += C1 * ((1-nondiff) * smoothstep(0,O.1,N.normalize(L)));

}

return C;

}

This LocIllumCelDiffuse function operates similarly to a standard diffuse( ), but thresholds the light value with a smoothstep. Figure 12.15 shows a teapot with an ordinary plastic reflection model and one lit with the LocIllumGlossy and LocIllumCelDiffuse illumination models.

Our next, and somewhat trickier, task is to draw outlines around the silhouette edges of the object. We will base our approach on the observation that exactly at silhouette edges, N and I are perpendicular, and therefore the dot product of N and I will be zero. In our first attempt, we will mix between the object color and a black outline by simply thresholding this dot product:

float angle = abs(normalize(N) . normalize<I));

12.8Cartoon Shaders

Figure 12.16 Adding outlines to our cel shader. Using angle only makes for uneven outlines (left). Using derivatives to make the outline widths more even (right).

float border = 1 - step (0.3, angle); Ci = mix (Ci, color 0, border);

This produces the image in Figure 12.16 (left). As you can see, though there is clearly some outlining effect, it isn't quite right. The outlines are sometimes missing, sometimes too thick, and generally uneven. This is because where curvature is high, the value of N . I changes rapidly, thus making a thin sliver of the portion where it is less than the threshold. But where the curvature is low and the orientation is just right, very large portions of screen space can be below the threshold value. We will correct for this unevenness by using the derivative of angle a to scale the angle, and also we use filterstep to antialias the edges of the outline (see Figure 12.16 (right)):

float angle = abs<normalize(N) . normalize(I)); float dangle = filterwidth(angle);

float border = 1 - filterstep (5, angle/dangle); Ci = mix (Ci, color 0, border);

Listing 12.8 shows our simple yet complete implementation of a shader that simulates the cel painting appearance. Figure 12.17 shows this cel shader applied to a 3D character. As simple as this approach is, it is clear that the look is very similar to a cel painting. There are, however, several tips and obvious areas for improvement:

You should not light such "pseudo-2D" scenes as richly as a more realistic 3D scene. Very few lights (one key, one fill, and one ambient) is plenty, and simpler lighting setups will help achieve the flat look.

Identifying outlines by examining the dot product works reasonably well for "outside silhouettes." Interior silhouettes, folds, or other feature lines are trickier. In addition, the technique doesn't do well on polygonal or other objects that don't have rounded corners. The round corners on all objects are critical for the successful appearance of the outline method.

332 12 A Gallery of Procedural Shaders

Figure 12.17 Our celshader applied to a previously modeled 3D character. (© Pixar Animation Studios.) See also color plate 12.17.

Listing 12.8 cel.sl is a naive (but functional) shader that creates a cartoony cel-painted appearance.

/*****************************************************************************

*cel.sl

*

*Description: generate flatly shaded objects that look like cartoon

*"cel" paintings.

*Parameters for the color and pattern:

*Parameters for illumination model:

*Ka, Kd, Ks, roughness - the usual meaning

*outlinethickness - scales the thickness of the silhouette outlines

****************************************************************************/

#include "filterwidth.h" #include "material.h"

333

12.8 Cartoon Shaders

Listing 12.8 (continued)

color LocIllumCelDiffuse ( normal N; )

(

color C = 0; extern point P;

illuminance (P, N, PI/2) {

/* Must declare because extern L & C1 because we're in a function */

extern vector L; extern color Cl; float nondiff = 0;

lightsource ("__nondiffuse", nondiff); if (nondiff < 1)

C += Cl * ((1-nondiff) asmoothstep(0,O.1,N.normalize(L)));

}

return C;

}

color MaterialCel (normal Nf; color Cs;

float Ka, Kd, Ks, roughness, specsharpness;)

{

extern vector I;

vector IN = normalize(I), V = -IN;

return Cs * (Ka*ambient() + Kd*LocIllumCelDiffuse(Nf))

+ Ks * LocIllumGlossy (Nf, V, roughness/10, specsharpness);

}

color CelOutline (normal N; float outlinethickness;)

{

extern float du, dv; extern color Ci, Oi; extern vector I;

float angle = abs(normalize(N) . normalize(I)); float dangle = filterwidth(angle);

float border = 1 - filterstep (5*outlinethickness, angle/dangle); Oi = mix (Oi, color 1, border);

return mix (Ci, color 0, border);

}

surface

cel ( float Ka = 1, Kd = 1, Ks = .5, roughness = 0.25; float outlinethickness = 1;)

{

normal Nf = faceforward(normalize(N),I);

Ci = MaterialCel (Nf, Cs, Ka, Kd, Ks, roughness, 0.25); Oi = Os; Ci *= Oi;

Ci = CelOutline (N, outlinethickness);

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]