Gamasutra: The Art & Business of Making Gamesspacer
"Ups and Downs" of Bump Mapping with DirectX 6
arrowPress Releases
January 23, 2019
Games Press
View All     RSS

If you enjoy reading this site, you might also want to check out these UBM Tech sites:


"Ups and Downs" of Bump Mapping with DirectX 6

June 4, 1999 Article Start Previous Page 5 of 7 Next

Listing 2. Code snippet showing DirectX 6 bump mapping.


//Pseudo code for creating a height differential map from a height map

//you would also have to handle a special case for the last row and column of the bitmap

for (y=0;y

for (x=0;x

HeightDifferentialMap(x,y).dU = HeightMap(x,y).dU - HeightMap(x+1,y).dU

HeightDifferentialMap(x,y).dU = HeightMap(x,y).dU - HeightMap(x,y+1).dU



//DEVCAPS bits check (assumes you got the CAPS already)

if( pd3dDevDescription->dwTextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP )

DoSomething();//this device supports bump mapping


DontDoAnything();//this device does not support bump mapping


//Setup of the bump map surface (assumes a direct draw surface descripton, ddsd, structure

// is set up already, and that pddsurface is a pointer to a DirectDrawSurface)



ddsd.ddsCaps.dwCaps2 = 0L;

// Pix format for DuDv88 bumpmap, could also do DuDvL556 or 888

ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);

ddsd.ddpfPixelFormat.dwFlags = DDPF_BUMPDUDV;

ddsd.ddpfPixelFormat.dwBumpBitCount = 16;

ddsd.ddpfPixelFormat.dwBumpDuBitMask = 0x000000ff;

ddsd.ddpfPixelFormat.dwBumpDvBitMask = 0x0000ff00;

ddsd.ddpfPixelFormat.dwBumpLuminanceBitMask = 0x00000000;

// Create the bumpmap's surface and texture objects

if( FAILED( pDD->CreateSurface( &ddsd, &(pddsurface), NULL ) ) )

return NULL;

if( FAILED(pddsurface ->QueryInterface( IID_IDirect3DTexture2, (VOID**)&pd3dtexBumpTexture ) ) )

//Set the Base Texture

lpD3DDevice->SetTexure(0, lpBaseTexture);

lpD3DDevice->SetTexureStageState(0, D3DTSS_TEXCOORDINDEX, 0);

lpD3DDevice->SetTexureStageState (0, D3DTSS_COLOROP, D3DTOP_MODULATE); //gouraud

lpD3DDevice->SetTexureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE);

lpD3DDevice->SetTexureStageState (0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);

lpD3DDevice->SetTexureStageState (0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);

lpD3DDevice->SetTexureStageState (0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);


// Set up the Bump Texture

lpD3DDevice->SetTexure(1, lpBumpTexture);


lpD3DDevice->SetTexureStageState (1, D3DTSS_TEXCOORDINDEX, 0);

lpD3DDevice->SetTexureStageState (1, D3DTSS_COLOROP, D3DTOP_BUMPENVMAP);

lpD3DDevice->SetTexureStageState (1, D3DTSS_COLORARG1, D3DTA_TEXTURE);

lpD3DDevice->SetTexureStageState (1, D3DTSS_COLORARG2, D3DTA_CURRENT);

lpD3DDevice->SetTexureStageState (1, D3DTSS_BUMPENVMAT00, DWORD(1.0f));

lpD3DDevice->SetTexureStageState (1, D3DTSS_BUMPENVMAT01, DWORD(0.0f));

lpD3DDevice->SetTexureStageState (1, D3DTSS_BUMPENVMAT10, DWORD(0.0f));

lpD3DDevice->SetTexureStageState (1, D3DTSS_BUMPENVMAT11, DWORD(1.0f));

lpD3DDevice->SetTexureStageState (1, D3DTSS_BUMPENVLSCALE, DWORD(1.0f));

lpD3DDevice->SetTexureStageState (1, D3DTSS_BUMPENVLOFFSET, DWORD(0.0f));

// Set up the Environment map texture

lpD3DDevice->SetTexure(2, lpEnvMapTexture);

lpD3DDevice->SetTexureStageState (2, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);

lpD3DDevice->SetTexureStageState (2, D3DTSS_TEXCOORDINDEX, 1);

lpD3DDevice->SetTexureStageState (2, D3DTSS_COLOROP, D3DTOP_ADD);

lpD3DDevice->SetTexureStageState (2, D3DTSS_COLORARG1, D3DTA_TEXTURE);

lpD3DDevice->SetTexureStageState (2, D3DTSS_COLORARG2, D3DTA_CURRENT);


The bump-map texture can support several pixel formats, and all of these formats are new to DirectX 6. The pixel formats are specified during the surface enumeration and creation by using the DDPF_BUMPDUDV flag and optionally the DDPF_BUMPLUMINANCE flag. These flags make it possible to expose three texture formats: two 16 bits-per-pixel formats (DuDv 88 and 556DuDvL), and one 32 bits-per-pixel format (888DuDvL). Du and Dv can be thought of as specifying the slope of the bump map in the U and V direction. The luminance factor specifies how to modify the RGB output of the bumped environment map.


The 2x2 bump-mapping matrix is used to rotate and scale the UV coordinates used to do the lookup into environment map. The formula used to offset the UV coordinates is as follows:

[U’,V’] = [U,V] + [bump(u),bump(v)] * [ M00 M01 ]

[ M10 M11 ]

which boils down to:

U’ = U + (bump(u)*M00 + bump(v)*M10)

V’ = V + (bump(u)*M01 + bump(v)*M11)

Where U and V are the coordinates for the current pixel being rendered, bump(u), and bump(v) are the values fetched from the bump map (at U,V), and U’ and V’ are the resulting coordinates used to fetch texels from the environment map for rendering.

When using a texture pixel format for the bump map that contains a luminance component, the D3DTSS_BUMPENVSCALE and D3DTSS_BUMPENVOFFSET arguments are also taken into account. After the matrix multiplication above, the pixel color is modified as follows:

L’ = bumpmap(L) * BumpEnvScale + BumpEnvOffset

Stage output = EnvironmentMap(U’,V’) * L’ * Polygon diffuse color

Article Start Previous Page 5 of 7 Next

Related Jobs

Within — Los Angeles, California, United States

Graphics Engineer
Disbelief — Cambridge, Massachusetts, United States

Junior Programmer, Cambridge, MA
Disbelief — Chicago, Illinois, United States

Junior Programmer, Chicago
Disbelief — Chicago, Illinois, United States

Senior Programmer, Chicago

Loading Comments

loader image