|
Features

Implementing Modular HLSL with RenderMonkey
Oren-Nayar
Diffuse Diffuse Shading
One
of the problems of the standard Lambertian model is that it considers
the reflecting surface as a smooth diffuse surface. Surfaces that
are really rough, like stone, dirt, and sandpaper exhibit much more
of a backscattering effect, particularly when the light source and
the view direction are in the same direction.
The
classic example is of a full moon shown in Figure 3. If you look
at the picture of the moon, it's pretty obvious that this doesn't
follow the Lambertian distribution - if it did the edges of the
moon would be in near darkness. In fact the edges look as bright
as the center of the moon. This is because the moon's surface is
rough - the surface is made of a jumble of dust and rock with diffuse
reflecting surfaces at all angles - thus the quantity of reflecting
surfaces is uniform no matter the orientation of the surface, hence
no matter the orientation of the surface to the viewer the amount
of light reflecting off of any point on the surface is nearly the
same.
In
an effort to better model rough surfaces, Oren and Nayar came up
with a generalized version of a Lambertian diffuse shading model
that tries to account for the roughness of the surface. They took
a theoretical model and simplified it to the terms that had the
most significant impact. The Oren-Nayar diffuse shading model looks
like this;

Now
this may look daunting, but it can be simplified to something we
can appreciate if we replace the original notation with the notation
we've already been using. p is a surface reflectivity property,
which we can replace with our surface color. E0 is a
light input energy term, which we can replace with our light color.
And the 0i term is just our familiar angle between the
vertex normal and the light direction. Making these exchanges give
us;

which
looks a little easier to compute. There are still some parameters
to explain.

Note
that if the roughness value is zero, the model is the same as the
Lambertian diffuse model. Since this model gives a closer visual
representation to rough surfaces such as sand, plaster, dirt, and
unglazed clay than Labertian shading, it's become a popular shading
model in most 3D graphics modeling packages. With HLSL, it's fairly
easy to write your own version of an Oren-Nayar diffuse shader.
The shader code below is based upon a RenderMan shader written by
Larry Gritz. Using this function will probably make the entire shader
is so long it requires that your hardware supports 2.0 shaders or
you run on the reference rasterizer.

In
most implementations this is paired up with a Phong or Blinn-Phong
specular term.
I
hope that you're getting the idea that it's pretty easy to write
snippets of code for specific purposes and place them in a library.
When I was writing my book on shaders I focused more on writing
it such that I had a variety of shader subroutines rather than just
a collection of stand-alone shaders. As you can see this approach
is very powerful and allows you to pick and choose the pieces that
make up the shader to customize the overall effect you want to realize.
Like
C, HLSL supports the #include
preprocessor directive, but only when compiling from a file - currently
RenderMonkey doesn't implement #include.
The filename specified can be either an absolute or relative path.
If it's a relative path then it's assumed to be relative to the
directory of the file issuing the #include.
Unlike C, there's no environmental variable support, so the angle
bracket include notation isn't supported, just the include file
name in quotation marks. It's easy to see that when function overloading
gets implemented it's going to be very easy to quickly write shader
code that's easy to customize. For now you can use the preprocessor
and some #ifdef / #else
/ #endif directives to #define
your own shading equations.
Shading Outside the Box
There's
no reason to be stuck with the lighting equation that we've been
working with. Shaders give you the ability to create whatever shading
effect you want and I encourage you to try creating you own lighting
equations, either by implementing academic models such as Oren-Nayar,
or creating your own. Cel shading is a simple example of non-photo-realistic
(NPR) rendering, but there are many, many artistic styles that are
starting to show up in computer graphics, just check out the SIGGRAPH
proceedings since 1999. You can also look to the real world for
inspiration as well. There's a beautiful example of this type of
shading done by ATI to demonstrate the Radeon 9700. In order to
duplicate the deep, color-shifting hues seen on metallic paint jobs
on cars, ATI created a demo that has (among other effects) a dual-specular
highlight term. This creates a highlight of one color surrounded
by a highlight of a different color as seen in a closeup of the
car's side mirror in Figure 4.
The
metallic flakes are from a noise map and the environment mapping
finishes off the effect.
As
shading hardware becomes more powerful and commonplace you'll start
to see more and more creative shading show up in games and then
in mainstream applications. The next release of the Windows OS is
rumored to be designed to natively support graphics hardware acceleration
for the entire desktop, and programmable shading is going to be
a big part of that. With the prices of DirectX 9 (and OpenGL 2.0)
capable hardware continually dropping, if your current project doesn't
incorporate shaders, you haven't investigated HLSL, or the low-level
shader language intimidated you, I hope this article has shown you
that not only is writing HLSL easy, but with tools like RenderMonkey
you can be writing shaders within minutes.
Article
Reviewers
The
author would like to thank the following individuals for reviewing
this article prior to publication: Wolfgang Engel, Randy Fernando,
Tadej Fius, Muhammad Haggag, Callan McInally, Jason Mitchell, Harald
Nowak, Guimo Rodriguez, and Natasha Tatarchuk.
Resources
RenderMonkey
The executable and documentation for RenderMonkey can be found at
www.ati.com/developer/sdk/radeonSDK/html/Tools/RenderMonkey.html
Cg
While not HLSL, it's pretty close. You can learn more about it at
http://developer.nvidia.com/Cg,
or www.cgshaders.org.
DirectX
9
The Microsoft DirectX 9 documentation is pretty sparse on HLSL,
but it's there for you to puzzle out.
Shader
Books
For DirectX shaders there's ShaderX by Engel, Real-Time
Shader Programming by Fosner. There's two ShaderX2 additional
books coming out soon as well. Cg is covered by The Cg Tutorial
by Fernando and Kilgard. Real-Time Shading by Olano, et.
al. is more about current shader research, but it's a useful source
of information if your interested in delving further into the state-of-the-art.
Illumination
Texts
Unfortunately most graphics texts gloss over all but the simplest
shading models. Most of the older ones can be found in Computer
Graphics by Foley, van Dam, et. al., with the newer ones in
Principles of Digital Image Synthesis, by Glassner. Quite
a few of the original papers can be found online as well. The
RenderMan Companion by Upstill and Advanced RenderMan
by Apodaca and Gritz are really useful sources of inspiration.
______________________________________________________
|