Gamasutra: The Art & Business of Making Gamesspacer
"Ups and Downs" of Bump Mapping with DirectX 6
View All     RSS
October 22, 2018
arrowPress Releases
October 22, 2018
Games Press
View All     RSS
  • Editor-In-Chief:
    Kris Graft
  • Editor:
    Alex Wawro
  • Contributors:
    Chris Kerr
    Alissa McAloon
    Emma Kidwell
    Bryant Francis
    Katherine Cross
  • Advertising:
    Libby Kruse

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

Plarium Michigan Studio LP
Plarium Michigan Studio LP — Portage, Michigan, United States

Senior Game Developer
Remedy Entertainment
Remedy Entertainment — Espoo, Finland

Senior Gameplay Programmer
YAGER Development GmbH
YAGER Development GmbH — Berlin, Germany

Lead Backend Engineer (f/m)
YAGER Development GmbH
YAGER Development GmbH — Berlin, Germany

Senior Dev Ops Engineer (f/m)

Loading Comments

loader image