Copy Link
Add to Bookmark
Report

How to implement 2d bump mapping

DrWatson's profile picture
Published in 
atari
 · 21 Jan 2024

Hello fellow coders.

This is Sqrt(-1) speaking. Many demos nowadays feature 2d bump mapping (the effect in which highlight travels upon a bumpy surface (prolly with embossed writing or something on it) seen from above), so I decided to write something about it...

As you'll soon see, I convert my page into this kind of a text articles w/ sample programs and source codes. I hope you will be happy now. (To you whom got this article from else where, consider visiting www.sci.fi/~zaphod)

Ok, to the point.

To really do REAL 2d bump mapping one has to calculate normals for every pixel in bump map (an image representing "heights" of pixels) and for each pixel take dot product of light source and this normal (the normal of the surface (ie. bumpy screen) is <0,0,-1>, ie. directly to the viewer, so it doesn't affect bump mapping).

This, of course, is awfully slow. And it does not look that good either.

The answer is simple. If we know X and Y of normal, we can calculate it's Z (as normals are unit vectors. So Z is simply 1 - \sqrt{(X^2 + Y^2)} ). Therefore, we can calculate the lighting value for each X and Y and store it into a map (which, normally is 256x256). This kind of a map is called enviroment map (enviroment maps are used to simulate reflecting objects with simple mapping).

Here's some pseudocode to calculate enviroment map:

for (int y=0;y<256;y++) 
for (int x=0;x<256;x++)
{
float nX=(x-128)/128;
float nY=(y-128)/128;
float nZ=1-sqrt(nX*nX + nY*nY);
if (nZ<0) nZ=0;
enviromentmap[x][y]=nZ*256; // 256 shades...
};

Of course you can use Phong illumination model as well...

So, by picking value at enviromentmap[normalx+128][normaly+128] (if normals are in 9.7 fixed point format) we get the correct lighting info for lightsource at <0,0,-infinity> . This, althought correct, is not what we want. We want light-source to move and be infinitely close to the surface.

Normalx is simply difference of heights in neighbour pixel on X axis... ie.

normalx = bumpmap[x+1][y] - bumpmap[x-1][y]

and for normaly, we ofcourse do

normaly = bumpmap[x][y+1] - bumpmap[x][y-1]

And now, gals and guys, comes the damned easy part :)

We simply pick value from

enviromentmap[(normalx-(lightx-currentx))][(normalx-(lightx-currentx))]

Of course, you have to check that values are within range...

So, here's a simple pseudocode for 2d bump mapper:

for (int y=0;y<200;y++) 
for (int x=0;x<320;x++)
{
int nX=bumpmap[x+1][y]-bumpmap[x-1][y];
int nY=bumpmap[x][y+1]-bumpmap[x][y-1];
int lX=x-lightx;
int lY=y-lighty;
nX-=lX;
nY-=lY;
nX+=128;
nY+=128;
if (nX<0 || nX>255) nX=0;
if (nY<0 || nY>255) nY=0;
screen[x][y]=enviromentmap[nX][nY];
};

Hope this helps you...

And don't ask me why the sample proggy is called "dan"... I keep it in a directory called "danfort"...

To compile the proddy with DJGPP, write:

cmp dan 
gxx -o dan.exe *.o

That's it.

If you need to contact me, email. zaphod@sci.fi

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT