Blinn and Newell's (1976) texture mapping first mapped images over
surfaces to create the illusion of detail without adding geometry.
Blinn's bump maps (1978), today implemented using Cook's normal map
format (1984), allow flat surfaces to have not only the color but the
appropriate shading of the perceived detail geometry. Texture and
normal mapping are standard effects in modern games. Oliviera and
Bishop's Relief Textures (1999) are a method for pre-distorting
textures based on depth information. Although it has not caught on in
the games community, the idea fostered the current work on parallax
mapping and its improvements.
Figure 1: Comparision of four real-time
bump-mapping methods applied to a single quadrilateral.
Parallax mapping with offset limiting is restricted
to low-frequency bump maps. Steep bumps are rendered incorrectly
by the algorithm and appear as parallel sheets of texture instead
of bumps. Parallax mapping also has inherent swim, where
the texture appears to slide over the surface due to a missing (1 / N dot V)
factor, which Welsh intentionally removed the dot product to stablize the
algorithm at glancing angles where the dot product is nearly zero.
Nonetheless, parallax mapping with offset limiting is today considered
the state of the art for real-time bump mapping.
We implemented parallax mapping with offset limiting-- including a
recent forum suggestion by flipcode.org poster 'ReedBeta' of scaling
the offset by N dot V to reduce swim where the gradient is large-- in
the Brown University CAVE. The parallax effect is especially
convincing in this environment because the user is much more free to
move the viewpoint (his own head) in arbitrary directions. The CAVE
is stereo, so each eye sees a different image rendered with a
different view vector. This makes the the texture swim especially
pronounced as the texture is shifted between eyes and the surface
appears slightly out of focus.
Several methods have recently been proposed for improving parallax
mapping. Donnelly (2005)
describes a voxel ray tracer that uses 3D textures and a sphere
tracing data structure. Tatarchuk (2004, 2005)
and Policarpo (2004)
describe a methods closer to our own, whic operate on a traditional
packed normal/bump map. For many game applications the traditional 2D
formats are superior to 3D textures-- they are supported by an
existing art pipeline, the art assets already exist, 2D textures are
better accellerated by current graphics cards, and 2D texture require
less memory per surface area, enabling higher fidelity at the same space cost.
All of these recent ideas, including our own, are
essentially the same: implement a ray tracer inside a pixel program.
The crucial issues to resolve are performance and filtering to avoid
undersampling (missing ray intersections), and each employs a
different strategy. Our unique contributions are:
- Self-shadowing
- PS2.0 fallback in addition to a preferred PS3.0 implementation
- Use of MIP-map LOD bias for filtering
- Successful application to fur/grass rendering
- Correct depth-buffer values for bumpy surfaces
- First demonstration on a "real", difficult texture
- First implementation shown to be fast enough for immediate integration into games
The main difference between Steep Parallax Mapping and Real-Time
Relief Mapping is that Policarpo and Oliveira use binary search. That gives a
better appearance for smooth surfaces at slightly worse theoretical
performance (the branch isn't very predictable in hardware). For thin,
sharp features like hair and the raised text in the figures on our web
page, binary search can miss the first intersection entirely and give
incorrect results. Because this is a case we care about particularly,
we instead use mip-map LOD to guarantee sampling below the Nyquist
rate (MIP-maps aren't tuned for zero aliasing by default; for textures
one normally wants to balance between aliasing artifacts and
too-blurry). Since the texture reads are all adjacent and not
dependent, they are performed very quickly from cache and the net
result for our technique is high performance. The loop branch in our
shader is almost perfectly predictable.
We believe that our previous technique for casting stenciled shadows
from nailboards (2004)
can be combined with Steep Parallax Mapping so that the only remaining
cue that a surface is not actually bumpy is the silhouette.
Several tricks for creating correct silhouettes for convex objects, but
doing so for arbitrary shapes in an efficient manner remains an open
and hard problem.
Full shaders are below and in G3D.
The critical section appears on the I3D poster above; we have since
extended it with Tatarchuk's idea of letting numSteps =
lerp(60,10,tsE.z) and with glFragDepth = 1/(z + ray distance).