Introduction
By Adam Lake and Kiefer Kuah
Intel® Software Solutions Group (SSG)
This paper reviews the state of the art in real-time rendering of fur. It also provides a working implementation using a real-time fin and shell technique, using the Intel® Integrated Performance Primitives (Intel® IPP) running on mainstream graphics hardware-the Intel® 915G Express Chipset.
Making characters look real has been a driving goal of computer graphicists. To complete this task a number of issues come to mind: character animation, facial animation, shading and lighting, physics, and a host of other effects studied for over 30 years. One of the most important and challenging aspects has been the simulation and rendering of fur. Numerous researchers have looked into this issue with varying degrees of success: first with the goal of off-line rendering realism, but more recently at real-time performance. We review the state of the art in real-time rendering of fur and provide a working implementation using a real-time fin and shell technique, using the Intel® Integrated Performance Primitives (Intel® IPP) running on mainstream graphics hardware—the Intel® 915G Express Chipset. The Intel 915G express chipset is DirectX* 9 capable hardware supporting Vertex Shader 3.0 and Pixel Shader 2.0. Our fur rendering technique is fully parameterized: material properties such as color and thickness can be adjusted as well as the number of fins and shells used for rendering.
Figure 1. An example rendered in real-time with the technique presented in this paper
The figure above is an example rendered in real-time with the technique presented in this paper, showing its applicability not just to fur but also to simulate small feathers on this bird model.
The following section describes the previous work in the field, including the most recent real-time academic implementations. The subsequent sections discuss the theory behind our implementation and provides details on the fur rendering technique. It also describes the future work in the area of real-time fur rendering.
Previous Work
As mentioned in the Introduction, a number of researchers have investigated fur rendering. James Kajiya records one of the earliest attempts at accurately depicting fur in his paper, Rendering Fur with Three Dimensional Models. Additionally, this paper has the first known reference to the word “texel” in literature. Interestingly, James Kajiya actually used it differently than it is commonly used today: rather than using it for shorthand to refer to any dimensional texture’s texture element, Kajiya defined it specifically as “a 3-dimensional texture map in which both a surface frame—normal, tangent, and binormal—and the parameters of a lighting model are distributed freely throughout a volume.” Our work attempts to approximate the ray tracing technique presented in this paper by using an approximation for real-time rendering of fur.
Another recent paper — Fake Fur Rendering by Dan Goldman, intended for non real-time rendering for Industrial Light and Magic to simulate the fur for 101 Dalmatians*. Dan describes an algorithm that is faster than their ‘realfur’ technique but is suitable when the animals are far away from the camera. The results look very good, however not directly suitable to a real-time implementation given today’s technology.
Overview and Implementation
Figure 2. A simple sampling technique in two dimensions
The figure above demonstrates a simple sampling technique in two dimensions, on the left is the intentionally exaggerated fur that we would like to model. In the middle is the set of shells we use to sample the hairs. On the right is the final set of shells. Locations that have a line segment above the shell line are samples which represent fur. These locations will contain material parameters for lighting and shading the fur. And the alpha will be set to opaque or semi-transparent. Sections which have no fur to sample will be transparent (alpha channel will be set to 0).
Our technique is inspired by the texture, shell and fin generation as described in Jerome Lengyel’s paper
Real-Time Fur over Arbitrary Surfaces. First, we generate textures for the shells and fins using the Intel IPP. Next, the geometry for fins was created. Finally, we rendered the image into the framebuffer. As the geometry is rendered into the framebuffer, the vertex shader calculates the position of shell vertices. The use of fins and shells is motivated by the fact that they are very aesthetically appealing ways of approximating the ray-tracing implementations
4 and proves suitable for the short, straight hair we were trying to simulate.
Texture creation has to happen the first time the application is run to procedurally generate the textures used for the shells. Next, the textures for the fins are generated. Each texture is written out to a file. There is no need to run these algorithms if the files already exist. Each time the application is run we generate the geometry for the fins before rendering. The shell geometry is created by moving the original vertex positions outward along the normal in the vertex shader. In the following sections we will give details on steps 1-4. Step 5, rendering, is a straightforward implementation that runs on mainstream graphics hardware using DirectX9 vertex and pixel shaders. In summary, our approach has the following five components:
- Generate Textures for Shells, using Intel IPP
- Generate Textures for Fins
- Generate Geometry for Fins
- Generate Geometry for Shells
- Render using components [1-4]
Textures for Shells
Figure 3. Five shells sampled from a Gaussian distribution
In the above figure, five shells are sampled from a Gaussian distribution using a Gaussian-based threshold function. Shell 0 is the left most shell. Notice as we move the shells up, more of the noise is filtered out. Thus, effectively simulating the thinning of fur as we move away from the skin.
Textures for Fins
The fin textures are generated by sampling the set of textures written out for each shell layer. We pick an edge and sample the texture along that edge. If we determine this to be hair we render the hair color into the texture. The hair color extends from this position in the texture until the next shell layer. If we determine that this is an empty space, we render nothing. This process is continued through the set of texture samples. This texture is used for each edge regardless of the edge.
Figure 4. Application of the shell textures
In the figure above we can see the result of the application of the shell textures in Figure 2. No fins are used in this figure.
Geometry for Shells
When the application begins we create geometry for each of the shells. The number of shells and the distance between the shells is model dependent. Each shell is created with two triangles to form a quadrilateral by the vertices of the mesh that the fur is being applied. To obtain the vertex positions of each quadrilateral the vertex positions are translated outward in the direction of the surface normal in the vertex shader. The distance between each shell is uniform in our demo but can be varied in your application.
Geometry for Fins
Fin geometry is created along the edges of each polygon by creating a quadrilateral oriented perpendicular to the edge in object space. The edge geometry is created at load time and used for each frame. Each quadrilateral consists of two triangles and is texture mapped using the texture map created as previously described.
Run-time
Since we have created the geometry and textures before run-time, rendering is straightforward. At run-time, we first render the geometry of the model, and then render the geometry, texture mapping with the textures created in the previous sections. We set alpha to 0.5 for each shell. We need no special vertex or pixel shader code for rendering the shells, each quadrilateral has a single texture map representing ‘fur’ or ‘empty-space’, by the value in the alpha channel. The vertices of the mesh are pushed out along the normal direction for each shell when rendering. This translation is done in the vertex shader. The best way to see this is to take a look at the example code included with this article.
Noise function
The Intel IPP is a set of routines optimized for running on x86 CPUs. While they are optimized for high performance, the primary motivation for their selection was the speed of development: the routines were easy to incorporate and reduced the opportunities for bugs in our example implementation. In particular, the function we chose to use was:
ippiAddRandGauss_Direct_8u_C1IR(&bTem[0][0], w, roi, 0, 100, &n);
Future Work
Several areas of future work come to mind. One is to implement the lapped texture technique as described in Jerome Lengyel’s paper Real-Time Fur over Arbitrary Surfaces. Another is to support the ability to handle physical forces being applied to our fur simulation. How might we handle when another object presses against our fur? How would we handle wind? Also, it would be interesting to add support for fur that curls. Thinking about shading, we would like to explore the addition of parameters to simulate wetness.
Acknowledgements
Kim Pallister, Harish Nag, and Pete Baker for giving us the time to do this work. David Reagin, John Van Drasek, and Cody Northrop for technical review.
Additional References
- JC Chong. Fur Rendering and Dynamics Using Discrete Shells. Simon Fraser University: CMPT 461 Final Project.
- Jerome Lengyel, Emil Praun, Adam Finkelstein, and Hugues Hoppe. Real-Time Fur over Arbitrary Surfaces. Symposium in Interactive 3D Graphics, 2001. Pages 227-232.
- Dan Goldman. Fake Fur Rendering. SIGGRAPH 1997. Pages 127-134.
- James Kajiya and Timothy Kay. Rendering Fur with Three Dimensional Models. ACM SIGGRAPH 89. Pages 271-280. 1989.
- Emil Praun, Adam Finkelstein, and Hugues Hoppe. Lapped Textures. SIGGRAPH 2000. Pages 465-470. 2000.
- Intel Performance Primitives for Intel® Architecture.
About the Authors
Adam Lake is a Sr. Software Engineer in the Software Solutions Group leading The Modern Game Technologies Project specializing in next generation computer graphics algorithms and architectures. Previous to working at Intel he obtained a Masters in Computer Science at the University of North Carolina at Chapel Hill studying computer graphics and virtual reality. Before studying at UNC-Chapel Hill he worked at Los Alamos National Laboratory in the Applied Theoretical Physics and Computational Science Methods (XCM) group. There, he worked on a computer-aided design application for physicists. He has several publications in computer graphics and has reviewed papers for SIGGRAPH, IEEE, and several book chapters on computer graphics. In his spare time he is a mountain biker, road cyclist, hiker, camper, avid reader, snowboarder, and Sunday driver.
Appendix A: Example Code for Shell Texture Generation
Click
here to view Appendix A
Appendix B: Example Code for Fin Generation
Click
here to view Appendix B
Appendix C: RandGauss_Direct()
RandGauss_Direct5
Generates pseudo-random samples with a Gaussian distribution in the direct mode.