Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Normal Mapping
In Chapter 7, we introduced t e x t u r e mapping, w h i c h enabled us to map fine
details from an image onto our triangles. However, our n o r m a l vectors are
s t i l l defined at the coarser v e r t e x level and interpolated over the triangle.
In this chapter, we study a popular method for specifying surface normals at
a higher resolution.
T h e N o r m a l M a p demo for this chapter is available in the download
files.
Objectives:
• To understand w h y we need n o r m a l mapping.
• To discover how n o r m a l maps are stored.
• To learn how n o r m a l maps can be created.
• To d e t e r m i n e the coordinate system the n o r m a l vectors in n o r m a l
maps are stored relative to, and how it relates to the object space
coordinate system of a 3D triangle.
• To learn how to i m p l e m e n t normal mapping in a v e r t e x and p i x e l
shader.
12.1 Motivation
Consider Figure 12.1 f r o m the Cube M a p demo of the preceding chapter
(see the download files). T h e specular highlights on the cone-shaped col-
umns do not look r i g h t — they look unnaturally smooth compared to the
bumpiness of the b r i c k t e x t u r e . T h i s is because the u n d e r l y i n g m e s h g e o m -
e t r y is smooth, and we have m e r e l y applied the image of bumpy bricks over
t h e smooth cylindrical surface. However, the l i g h t i n g calculations are p e r -
f o r m e d based on the m e s h g e o m e t r y (in particular, the interpolated v e r t e x
normals), and not the t e x t u r e image. T h u s the l i g h t i n g is not completely
consistent w i t h the t e x t u r e .
321
Part III: DirectSD Topics
12.2 N o r m a l Maps
A normal map is a t e x t u r e , but instead of storing R G B data at each texel, we
store a compressed x-eoordinate,y-coordinate, and z-coordinate in the red
component, green component, and blue component, respectively. These
coordinates define a n o r m a l vector; thus a n o r m a l map stores a normal vec-
t o r at each pixel. Figure 12.3 shows an example of how to visualize a normal
map.
So how do we compress a. unit vector into this format? F i r s t note that, for a
u n i t vector, each coordinate always lies in the range [ - 1 , 1], If we shift, and
scale this range to [0, 1] and m u l t i p l y by 255 and truncate the decimal, the
result w i l l be an integer in the range 0 to 255. T h a t is, if x is a coordinate in
the range [ - 1 , 1], t h e n the integer part of f(x) is an integer in the range 0
to 255, w h e r e / is defined by
/ ( x ) = (0.5x+0.5)-255
Part III: Direct3D Topics
/" W = Zoo
1
^ : - 1
the color vector normal T will have normalized components (>;g, b) such that
0<>;g,b< 1. T h u s , the method has already done part of the uncompressing
w o r k for us (namely the divide by 255, w h i c h transforms an integer in t h e
range 0 to 255 to the floating-point i n t e r v a l [0, 1]). We complete the t r a n s -
formation by s h i f t i n g and scaling each component in [0, lj to [ - 1 , 1] w i t h
the function£: [0, 1] -» [ - 1 , 1] defined by:
g(x) = 2x-1
12.3 Texture/Tangent S p a c e
Consider a 3D t e x t u r e mapped triangle. For the sake of discussion, suppose
that there is no distortion in the t e x t u r e mapping; in other words, mapping
the t e x t u r e triangle onto the 3D triangle requires only a r i g i d body transfor-
mation (translation and rotation). Now, suppose that the t e x t u r e is like a
decal. So we pick up the decal, translate i t , and rotate it onto the 3D t r i a n -
gle. Figure 12.4 shows how the t e x t u r e space axes relate to the 3D t r i a n g l e :
T h e y are tangent to the triangle and lie in the plane of the triangle. T h e t e x -
t u r e coordinates of the triangle are, of course, relative to the t e x t u r e space
coordinate system. Incorporating the triangle face n o r m a l N, we obtain a 3D
TBN-hasis in the plane of the triangle that we call texture space or tangent
space. Note that the tangent space generally varies f r o m triangle to triangle
(see Figure 12.5).
clear that
e () = A;/ T + ( I Av(lB
e } = Au T + A t ' j B
L
e
0,x e
0,y e
0 . :
Au 0 Av {)
X T
y
T z
e
l,x e
l,y e
\,z Au L Af j Br Bz
7
'0,x e
0,y e
0,z
AMJ AV 1
1 Av l
'0,x e
0,y e
0,z
a b
In t h e above, we used the fact that the inverse of a m a t r i x A= is
c d
given by:
1 d -b
A - 1
-
ad—be —c a
N o t e that the vectors T and B are generally not unit length in object space,
and if there is t e x t u r e d i s t o r t i o n , they w i l l not be o r t h o n o r m a l either.
T h e T, B, and N vectors are commonly referred to as the tangent,
binomial (or bitangent), and normal vectors, respectively.
struct Vertex
D3DXVEGT0R3 pos;
D3DXVECTOR3 tangent; :
D3DXVECT0R3 normal;
D3DXVECT0R2 texC;
h
For our N o r m a l M a p demo, w e w i l l continue to use the Quad, Box, Cyl i nder,
and Sphere classes. We have updated these classes t o include a tangent
328 Part III: Direct3D Topics
12.5 T r a n s f o r m i n g b e t w e e n Tangent
Space a n d O b j e c t Space
At t h i s point, we have an o r t h o n o r m a l T B N - b a s i s at each v e r t e x in a m e s h .
Moreover, w e have the coordinates o f the T B N vectors relative t o the
object, space of the mesh. So n o w that we have the coordinates of t h e
T B N - b a s i s relative to the object space coordinate system, we can t r a n s f o r m
coordinates f r o m tangent space to object space w i t h the m a t r i x :
T T Y
M 'bject B X
B Y B Z
N , N .
T R B V AT,
B,
1 1
world ~ (n tcmgmt Mobject ) M m r U
A n d note that
'[' — r r; r; x
linclude "lighthelper.fx"
cbuffer cbPerFrame
{ ' . • ; • . ' ;• . y ; \ » ;
: ..-
Light gLight; :
floats gEyePosW;
. }; ; ' .• •. • • • • • ••• • •••• • ' , .'
cbuffer cbPerObject
{ . : '. • . •: • :
•• • .
float4x4 gWorld;
f 1 oat4x4 gWVP;
float4x4 gTexMtx;
float4 gReflectMtrl;
bool gCubeMapEnabT ed;
};
Part III: DirectSD Topics
SamplerState gTriLinearSam
{
Filter = MIN_MAG_MIP_LIN EAR;
Addressll = Wrap; ,
AddressV = Wrap;
struct VS IN
struct VS OUT
VS_0UT vOut;
return vOut;
1
float4 PS(VS_0UT pin) : SVJarget
{
float4 diffuse = gDiffuseMap.Sample( gTriLinearSam, pln.texC );
clip(diffuse.a - 0.15f);
// build orthonormal b a s i s
f l o a t s N = normalize(pin.normalW);
f l o a t s T = norma Iize(pin.tangentW - dot(pIn.tangentW, N)*N);
f l o a t s B = cross(N,T);
// Compute the l i t color for this pixel using normal from normal map
Surf acelnfo v * {pln.posW, bumpedNormalW, diffuse,: spee); :
[branch]
iff gCubeMapEnabled )
{ , • ' /• • : ' '
techniquelO NormalMapTech
{
pass' PO • •
floats N = normalize(pIn.normalW);
float3 T = normalize(pln.tangentW - dot(pin.tangentW, N)*N);
332 Part lit: Direct3D Topics
T - p r o j ( T ) is the portion of T
N
orthogonal to N.
T - (N • T ) N
12.7 S u m m a r y
• T h e strategy of normal mapping is to t e x t u r e our polygons w i t h n o r m a l
maps. We then have per-pixel normals, w h i c h capture the fine details of
a surface like bumps, scratches, and crevices. We t h e n use these
per-pixel normals from the n o r m a l map in our l i g h t i n g calculations,
instead of the interpolated v e r t e x normals.
• A normal map is a t e x t u r e , but instead of storing RGB data at each
texel, we store a compressed ^-coordinate, y-coordinate, and
z-coordinate in the r e d component, green component, and blue
component, respectively. We use various tools to generate n o r m a l
maps, such as the ones located at http://developer.nvidia.conV
objecVnv_textirre_tools.html, http://www.crazybump.com/, and
http://developer.nvidia.com/object/melody_home.html.
• T h e coordinates of the normals in a normal map are relative to the
t e x t u r e space coordinate system. Consequently, to do l i g h t i n g
calculations, we need to transform the n o r m a l from the t e x t u r e space
to the w o r l d space so that the lights and normals are in the same
coordinate system. T h e TBN-bases built at each v e r t e x facilitate the
transformation from t e x t u r e space to w o r l d space.
Chapter 12: Normal Mapping 333
12.8 E x e r c i s e s
1. Download the N V I D I A n o r m a l map p l u g - i n Chttpr/'/devel-
oper.nvidia.comA)bject/nv_texture_tools.html) and experiment w i t h
m a k i n g different n o r m a ! maps w i t h i t . T r y y o u r n o r m a l maps out i n this
chapter's demo application.
2. Investigate D3DXlOComputeNormalMap and use it to create a normal map
f r o m a heightmap. Essentially, a heightmap is a grayscale image that
defines the heights of a surface (see §16.1). Use D3DXlQSaveTexture-
ToFi 1 e to export y o u r normal map to file as a Windows bitmap image
(D3DX10_IFF_BMP).