A Bump mapping egy olyan effekt, mint amikor egy valamiféle domborzatot megvilágítunk. Ami mélyebben van, vagy a fényforrástól távolabb, az sötétebb, ami magasabb, vagy a fényforráshoz közelebb van, az világosabb. Ennek a domborzatnak minden pontjának a mélysége el van tárolva.

Mondjuk a méret legyen 320x200. Van egy 320x200 elemű tömb, ahol a mélységek vannak. Ez a bump map. Persze ez eddig még egyszerű lenne, de nem is valami látványos. Megint segítségül hívjuk a pontbeli normálvektorokat. Egy adott pont fényintenzitása fordítottan arányos a pont normálvektora és a fény vektora által bezárt szöggel. Ugye ez már ismerős a Goroud Shading-ből.. 

Persze 320*200 pontra (64000) elég nagy falat normálvektort számolni. Ennyi pontra egyenként pontosan kiszámolni elég strapás lenne. De, ha valamit nem tudunk kiszámolni, hát megközelítjük. Az sem baj ha éppen nem olyan pontosan. Csak úgy éppen, hogy, tudjunk róla valamit. Többre úgy sem lenne processzoridő. Legalább azt kéne valahogy kideríteni, hogy az adott pont éppen egy olyan lejtőre illeszkedik-e, ami a fényforráss felől van, vagy ami ami, éppen egy takart lejtőn. Ehez csak annyit kell tudni, hogy a normálvektor a fény fele mutat, vagy attól el. Nézzünk egy példát:

Így néz ki a bump map:

Az (x,y) pont mélysége 3. Határozzuk meg a pont normálvektorának x és y összetevôjét. Nem kell félni, a matematikához nem sok köze lesz.

Tehát az (x,y) pont mellett bal oldalt a mélység (tömbösen :map[x-1,y]=) 2, jobb oldalt (map[x+1,y]=)4. Jobb oldalon nagyobb a mélység, tehát a normálvektor jobbra dől, ezért az X összetevője pozitív lesz. Az értéke függ a két mélység különbségétől, 4-2=2 (map[x+1,y]-map[x-1,y]=2). Az (x,y) feletti pont mélysége 2, az alatta levőé pedig 4. Alul a mélység nagyobb, ezért a normálvektor lefele dől. Tehát az y koordnáta pozitív, méghozzá arányos a két mélység különbségével, ami szintén 4-2=2 (map[x,y+1]-map[x,y-1]=2) (csak véletlenül !). Szóval fogjuk ezeket az értékeket, és valami olyasmiként kezeljük, mintha a felület pontbeli normálvektorának X és Y koordinátái lennének

nx=map[x+1,y]-map[x-1,y];
ny=map[x,y+1]-map[x,y-1];

A normálvektor meglenne. Egy kicsit szabálytalan módon, egy kicsit pontatlanul, egy kicsit kicsi, egy kicsit savanyú, de a miénk. Azonban a merényletnek ezzel még korántsincs vége. Mitől is függ a fényerő?

  • normálvektor
  • fényforrástól mért távolság

A normálvektor már megvan, nézzük a távolságot. Legyen a fényforrás képernyőre vetített koordinátája (Lx,Ly). Ekkor az X,Y pontnak a fényforrástól mért távolságának a négyzete : d2= (Lx-X)2+ (Ly-Y)2

Ez eddig teljesen okés. Csakhogy a négyzettel mi nem vagyunk kisegítve. Gyököt kéne vonni. Mind a 64000 pontnál? Merül fel a kérdés. Na igen. Ez az amit ki fogunk hagyni. Inkább egy loopkup table-t fogunk használni. Hasonló a phong map-hez. Fogjuk az X irányú távolságot, meg a normálvektor (vagy olyasmi) X összetevőjét, és vesszük a különbségüket. Ugyanezt eljátszva az Y-al lesz két értékünk, amivel a lookup table-en indexelünk.

tehát:
dx=Lx-x;
dy=Ly-y;
dx=nx-dx;
dy=ny-dy;
c=lookup[dx,dy]

Vagy valami hasonló.
A képlet megvan.(hogy hogyan azt ne firtassuk !)
Akkor nézzük meg c-ben:

void dobump(int lx,int ly) //lx,ly a fenyforras helye {
int x,y,ldx,ldy,dx,dy,nx,ny;for(x=1;x<319;x++) for(y=1;y<199;y++) {
ldx=lx-x; //a pont x tavolsaga a fenyforrastol ldy=ly-y; //a pont y tavolsaga a fenyforrastol if (-128<ldx && ldx<128 && -128<ldy && ldy<128) {
nx=map[y*320+x+1]-map[y*320+x-1]; //nx,ny a pont normalvektora  ny=map[(y+1)*320+x]-map[(y-1)*320+x];      //tavolsag es norm.vektor kulonbsege //legyen pozitív      dx=ldx>nx?ldx-nx:nx-ldx;                    dy=ldy>ny?ldy-ny:ny-ldy; //ne legyen 127-nel nagyobb if (dx>127) dx=127; if (dy>127) dy=127; //putpixel screen[y*320+x]=envmap[dx][dy];
}   
    } }

Igen, a képlet, és a program működik. Még csak annyit, ehhez olyan paletta kell, ami jól mutat. Ezt pedig nem olyan nehéz összehozni.

Ja, a program megint Watcom C-ben sikerült.