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 az environment mappingbôl. És az is, hogy ha a fényforrás merôleges a képsíkra, akkor a pontok normálvektorának Z koordinátájával nem kell törôdni.
Na mondjuk ez itt nem lesz igaz, mert most pont ez a lényeg. Most a normálvektor Z koordinátája megegyezik(/arányos) magával a mélységgel. Csak az X meg az Y kell. Persze 320*200 pontra (64000) ez is elég nagy falat. Ennyi pontra egyenként pontosan kiszámolni ezeket 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:
Sôt ! Antimamtematika. Úgyhogy, ha valaki érez még némi szánalmat a matematika iránt, vagy esetleg valamilyen szinten m?veli is, az ugorjon inkább a programra.!
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. Méghozzá arányos a két mélység különbségével, 4-2=2 (map[x+1,y]-map[x-1,y]=2)vel. 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 !). Az meg már nem oszt, nem szoroz, hogy a normálvektor értékei csak arányosak ezekkel az értékekkel, ennyi baromság után már fel sem fog tűnni senkinek, hogyha mondjuk azt modjuk, hogy legyenek egyenlők ezekkel az értékekkel. Tehát:
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ô ?
A normálvektor már megvan, nézzük a távolságot. Legyen a fényforrás koordinátája (Lx,Ly) (a z-vel nem törôdünk). 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. Most tegyünk valami olyat, amiért egy matek zh-n már rég megvágnának. Vonjunk gyököt tagonként! Akkor asszongya: d=(Lx-x)+(Ly-y). Ez már mingyárt más. Egyszerüsítsünk egy kicsit.
dx=Lx-x;
dy=Ly-y;
d=dx+dy;
Minden megvan. Akkor most már határozzuk meg a pont színét. Tehát a távolsággal fordítottan arányos, meg a normálvektort is bele kéne nyomatni:
c=-dx+nx-dy+ny;
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
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];
dx=ldx>nx?ldx-nx:nx-ldx; //tavolsag es norm.vektor
kulonbsege
(legyen pozitív)
dy=ldy>ny?ldy-ny:ny-ldy;
if (dx>127) dx=127; //ne legyen 127-nel negyobb
if (dy>127) dy=127;
dx=127-dx; //azert vonjuk ki 127-bôl, mert így
a kettô összege nem
lehet nagyobb 255-nel
dy=127-dy;
screen[y*320+x]=dx+dy; //putpixel
}
}
}
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, semmi különös ok nem volt rá, csak az, hogy a program Borland-dal egyszerűen Abnormal Program Termination-el mindig kiszállt. Aki megtalálja, hogy miért, annak fizetek egy sört. (Ez a hibás kód persze nem lesz fent a mellékleten, tőlem el lehet kérni).