Rendering Hair

Home ] Up ] [ Rendering Hair ] Displacement Mapping ] Visibility Maps ] Motion Blur ] Ray Tracing ] Programming ]

SIGGRAPH 2004 Course Slides
SIGGRAPH 2004 Sketch Slides

 

Introduction

For me, the greatest challenge in rendering hair is to capture its essential visual elements, such as geometric complexity, realistic sheen and self-shadowing, and to do so efficiently. There are many trade-offs involved: An approach that works well for short hair may prove visually inadequate for long, flowing hair. Similarly, a technique that works well for long hair or at close distances may be unreasonably slow for short or very distant hair.


Each hair on this tabby cat was rendered using our specialized hair rendering primitive. This provides the necessary level of geometric detail for a realistic close-up shot.

The visual effects for the movie Cats and Dogs required a whole new paradigm for rendering fur in Rhythm and Hues's renderer. Because it was important to achieve a photorealistic look for various types of fur (e.g. long, short, wet) and at extreme close-ups, we opted to model each strand of hair using a simple spline-based geometric model that incorporates specialized lighting and self-shadowing methods.

Hair Geometry

We represent each hair primitive as a set of positional control points, plus a hairtype identifier and a (u,v) pair for texturing. The positional control points define a three-dimensional Catmull-Rom spline, used in generating the ribbon of trapezoidal polygons along the hair’s path. The polygons are oriented to always squarely face the camera.

The ribbon of trapezoids comprising a hair primitive always faces the camera.

Our tessellation scheme, a simplified version of the work presented by Neulander and van de Panne1, uses an adaptive tessellation algorithm to control a hair’s polygon density based on its curvature, size, and camera distance. Hairs that are small on screen or are straight thus generate fewer polygons than ones that are large or wavy. Moreover, the number of hairs rendered can be set to vary according to camera distance. Hairs gradually fade in or out of existence, and as the hair count diminishes, the thickness of the remaining hairs is automatically boosted to preserve coverage. This provides a surprisingly coherent look even as the hair count significantly changes over an animation sequence.

hairBallAdapt.jpg (40509 bytes)

hairBallNonAdapt.jpg (40863 bytes)

The left animation varies both the number of hairs as well as the number of polygons per hair according to camera distance; the right one varies only the number of polygons per hair. The numbers displayed in red are:
hair count  /  poly count.

Click on thumbnail for animation.

The hairtype identifier allows properties common to a group of hairs to be factored out and specified independently of the hair geometry file. Attributes like color and opacity can be defined at any number of equidistant points along a hair, and are spline-interpolated during tessellation. Any value at any control point can be set as a per-hairtype constant, or a map can be specified to provide a lookup value at the hair's (u,v) index.

Shading Model

We use the cylinder-based shading model originally presented by Kajiya and Kay.2 Rather than using explicit surface normals for shading, this model employs the hair’s tangent vector, which is easily obtained from its spline path. This produces realistic shading and correctly handles back-lighting (the phenomenon where hairs along the edge of an object light up when the object is placed between the light and the camera). Moreover, unlike simple Phong derivatives, which attempt to interpolate rapidly varying normals over thin cylinders, our choice of shading model is not prone to spatial aliasing.

One limitation of the Kajiya model is that it fails to capture shading variation across the width of a hair primitive. However, this has not proven problematic: Although our hair primitives are often several pixels thick, each one conceptually represents multiple strands of much thinner hair, so Kajiya’s "infinitesimal cylinder" model is not severely violated.

Self-Shadowing

The importance of hair-to-hair shadowing to the realism of rendered hair cannot be overstated. Using traditional depth maps for this purpose would fail to capture the gradual shad-owing arising from multiple layers of partially transparent hair. Deep shadow maps3 are a better option, but they require considerable computation and storage. Our solution is to pre-compute and store self-shadowing information in each hair primitive’s control points. This information is later used to approximate the amount of "hair material" a light ray needs to penetrate in order to reach each control point. Such methods have been successfully used in the past1, 4.

A flattened representation of the self-shadowing model we use.

Essentially, we store a normal and depth value at each control point. Together, these define an imaginary sphere enclosing the control point, with various possible penetration distances fanning out from the control point to the sphere surface. An easy way to obtain the self-shadowing normal is to use the normal of the skin surface directly underneath a hair control point; however, this yields inaccurate results for longer hair. We devised a unique derivation for the self-shadowing data: All positional control points of all hairs, forming a dense point cloud, are inserted into a voxel grid. Then, a ray-marching algorithm determines, for each voxel, the ray that starts at the center of the voxel and escapes the point cloud while "encountering" (i.e. passing close to) the fewest points along the way. Using a voxel grid discretizes the results and allows us to efficiently estimate the number of points a ray encounters. We take care to mark voxels containing skin polygons, so as to prevent rays from escaping through the skin. After computing the self-shadowing normal and depth value for each voxel, we interpolate these values over all the control points. The resulting self-shadowing, being based on the actual hair geometry, gives excellent results with long hair and even captures effects like bunching and clumping. The following examples illustrate some of these effects.

hairTestTess.jpg (32956 bytes) hairTestShade.jpg (24980 bytes) hairTestSelfShad.jpg (24399 bytes)
Three renders of a hairball illustrating the hair tessellation, basic shading, and shading with self-shadowing.

 

cat.0001.gif (276641 bytes)cat.0002.gif (276851 bytes)cat.0003.gif (303605 bytes)cat.0004.gif (310180 bytes)cat.0005.gif (296518 bytes)cat.0006.gif (270441 bytes)cat.0007.gif (245820 bytes)
Our interactive hair preview tool shows the hair self-shadowing (without Kajiya shading) in real time.

 

0.0 ... 1.0 0.0 ... 0.2 0.2 ... 0.4 0.4 ... 0.6 0.6 ... 0.8 0.8 ... 1.0
catDpt.gif (311789 bytes) catDpt0.gif (251721 bytes) catDpt2.gif (184792 bytes) catDpt4.gif (145567 bytes) catDpt6.gif (106420 bytes) catDpt8.gif (50959 bytes)

The hair previewer can also show different depth ranges for hair (cyan is depth 0; red is depth 1).

Hair Culling

Another useful feature of the self-shadowing normal is that it facilitates what we call hair culling. Analogous to backface culling in traditional rendering, this concept is used to quickly eliminate hairs that face away from the camera. The direction in which a hair faces is precisely what the self-shadowing normal tells us. One difficulty with hair culling is that there is no guarantee that a backfacing hair is in fact hidden from view. A long hair could still protrude past the other (front-facing) hairs and be visible. Thus, hair culling works best for relatively short fur. However, even with longer hair, we can take advantage of hair culling by requiring hairs to face backward by a certain angular tolerance (up to 90 degrees) before they are culled. This is a simple extension of traditional backface culling, where the tolerance is zero. 

The most important consideration in hair culling is to prevent hairs from abruptly popping in and out of existence as their front- or backfacing status changes. To address this, we allow two angles to be specified. At the lower angle, a hair begins to fade. At the higher angle, the hair disappears. Between the two, the fading is linear. Past the higher angle, the hair is culled. In our experience, this simple trick has completely eliminated culling-related popping artifacts.

Images and Animation Clips:

lou.JPG (130397 bytes)

tinkles.JPG (137177 bytes)

ninjaCat.rll.jpg (160464 bytes)

ninjaFur.rll.jpg (275845 bytes)

fightMB.rll.jpg (221332 bytes)

tinklesMilk.jpg (172797 bytes)

tinklesWalk.jpg (143074 bytes)

mouseTT.jpg (25978 bytes)

louTT.jpg (34641 bytes)

tabby.yuv.jpg (34298 bytes)

These furry creatures have up to 11 million hair primitives, though a typical render uses much fewer than that. Hairs that are outside of the camera's view are efficiently clipped by the renderer before they are even tessellated into polygonal geometry. Close-up shots, like the one of Mr. Tinkles (the white Persian) above, use the highest hair density, but they also result in many hairs being clipped away.

Future Work:

I see several avenues for future work in hair rendering. Foremost among them is the ability to locally control sheen and shadow color in an easy and predictable way,  while maintaining a quasi-photorealistic look. (I say "quasi-photorealistic" because true photorealism provides no control other than altering the physical parameters of the scene.) This is a difficult problem: For instance, hair sheen is governed by a fairly complex formula involving a hair point's tangent vector, view vector, and light vector. Combing the hair in a particular way has a drastic effect on the sheen which is very difficult to predict or control. Our digital artists have experimented with a simplistic hair sheen formula, whereby the sheen from an animal's skin (where it is much more predictable) is transferred, through mapping, onto the fur. Unfortunately, the resulting images fail to match the look of real fur. Perhaps an interactive lighting tool that renders hair sheen in real time will allow for easier combing and light positioning that achieves the desired look. Another way to help artists produce the desired sheen is by implementing area lights or global light maps, that will hopefully eliminate the need for tweaking a large number of spot lights. The challenge here will be to properly handle shadows, and to to so without the prodigious computational burden of ray tracing.

Yet another area for improvement is our self-shadowing technique. While our sphere-based model is extremely fast and memory efficient, it works only at a local level: That is, it captures the shadowing effect among neighboring hairs, but not distant hairs. Also, it provides no solution for shadows cast by hair onto other surfaces. To handle general-purpose hair shadowing, we currently use depth maps. Given the right amount of blur and attenuation, depth maps can usually do an acceptable job of rendering hair shadows, but they typically require a great deal of user intervention to produce the desired look. By implementing deep shadow maps3,  we would have a physically accurate model that correctly takes opacity into account and, most importantly, allows maps to be filtered in order to reduce aliasing. Because deep shadow maps tend to store much more information than traditional depth maps, we would need a good compression scheme, as discussed in the paper, to store and retrieve the visibility data in a way that is both space- and time-efficient. Also, we would most likely need to extend the published implementation to ensure that it properly supports motion blurred shadows cast onto moving objects.

References:

1. Ivan Neulander, Michiel van de Panne. Rendering Generalized Cylinders with Paintstrokes. In Graphics Interface ’98, June 1998.

2. James T. Kajiya, Timothy L. Kay. Rendering Fur with Three Dimensional Textures. In SIGGRAPH 89, July 1989.

3. Tom Lokovic, Eric Veach. Deep Shadow Maps. In SIGGRAPH 00, July 2000.

4. William T. Reeves, Ricki Blau. Approximate and Probabilistic Algorithms for Shading and Rendering Structured Particle Systems. In SIGGRAPH 85, July 1985.

Home Up Rendering Hair Displacement Mapping Visibility Maps Motion Blur Ray Tracing Programming