ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Demoscene: Bump Mapping effect ³ DuSTFaeRie/DDT ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Bump mapping I bet u already saw this effect in a lot of demos : in fact it is quite overused nowadays, as it is very easy to implement. But as i began usinh my computer in order to do other things than just playing lemmings, this fx fascinated me : i didn't have the sligh- test idea of how to do such a light cruising over a nice looking picture. I searched a bit around on the net, but didn't find any simple explanation. I then asked Cyg, a friend of mine on IRC (merci gars, j'aurais jamais capté sans ton aide précieuse ;), who taught me what a plane normal was, and how the effect worked. I know this is boring, so if it annoys u just jump to the next section where i begin explaining, but i want to tell all the story cause i love reading stuff like this. So i first implemented a C version, without any optimization, just to look if the fx worked. It ran about 30 FPS on my parent's P200, and about 5 on my very own DX33 (fortunately i bought a new computer, so i don't have to wait 30 seconds for the compiler to compile my shitty small sources). I then rewrote the main routine, and it did 71 FPS on my P200, just a bit above the refresh rate of the screen. Quite nice, i don't have to go any further. But i then discovered an implementation of the fx by Azure which went about 120 FPS on my P200 ! Wow ! But there were no comments to the source nor explanations. I examined the code as i learned disassembling virii, and rewrote my code using the same ideas, added some of my own, and after a few tries, it went 254 FPS on my P200. I managed to do it ! But the code is still very crappy. I also think my code was that fast cause Azure's routine is in rmode and mine is in pmode (lightning fast access to mem). So enough blabla, move over to the real thing ! An explanation of bump mapping :* I assume we are in mode 13h, as i'm too bad to use any other mode (whereas i did some progress by now, i can now use vesa !), and as everybody knows how to use it (or can learn it in about 10 seconds). So u have a texture (or a bitmap, but it is commonly called a texture, i dunno why, maybe because of the links with 3D program- ming), and u want that texture to look quite bumpy, that means that u can see the relief (can u say that in english ?) when a light source moves over it. In my explanation there will be only one color, but u just have to use shading to make a color version. It's fairly easy to implement. As there is only one color, the pixel color will represent the height of the points (just like a voxel landscape). An easy way to draw such a picture is to draw a gray shaded one). Before going any further, i'll tell u about an easy way to get the light value in a certain point. First, i hope u all agree on that, is that if the light falls vertically on a surface, there will be the most light reflected. The less the light falls verti- cally down on the surface, the less the light value is gonna be. Just try it out with your computer screen and a pocket lamp ;). In our case, the computer simulation, the light value has to be the greatest when the light falls vertically onto the screen (as if your head was a lamp). Now that u know this, we can move over to more complicated stuff. It's not complicated indeed, just basic vector maths stuff u must have learned in school, all u have to know is what a dot-product is. If u don't know, just ask your maths teacher, he'll know. In my case, i didn't even know what a normal vector was (a normal vector is just the unit (in our case) vector which is tangent to the plane). For example, in our case, the normal vector is the unit vector going from the computer to u perpendiculary to the screen. What does this have to do with bump mapping ? Easy, u get the normal vector to the texture in each point (i'll explain u how, don't worry) and get the dot-product of this vector with the normal vector to the screen. Then u multiply the result (which is inferior to one as both vectors where unit vectors) by the so-called diffuse lightvalue (the maximum light-value that can be reached) and u have the lightvalue at the point. Got it ? No ? I also had an example in the first version of the article but i'm too lazy to write it down. Just try it out by making a few examples with your desk and a lamp. This is the so called Gouraud Shading, which is also widely used in 3D. More about 3D in the next issue. I bet u now have a lot of questions : how do i get the normal vector to the texture ? the normal vector to the screen ? how do i make the dotproduct ? how do i move the light, cause u mentionned no light in your bad explanation :(. In fact it is all quite easy. We first have to define a coordinate system : the x axis goes from left to right, the y axis from top to bottom and the z axis from the computer to the user. Now we have defined a coordinate system, we can define the normal vector to the screen. It is a unit vector that goes from the screen to the user, so its coordinates are (0,0,1). Now comes the big question, how do we get the normal vector to the texture at point (x,y)? Easy, u first calculate the xdelta and the ydelta : normal.x = texture(x+1, y) - texture(x-1, y) normal.y = texture(x, y+1) - texture(x, y-1) We get the z coordinate using pythagora (remember ?) as the vector is a unit vector : normal.z = sqrt(normal.x * normal.x + normal.y * normal.y) Of course there is a lot of precalc to do ;). And how do we calculate the dotproduct ? Easy : dotproduct = x1 * x2 + y1 * y2 + z1 * z2 Due to the specialty of the screen normal vector : dotproduct = normal.z (isn't that cool ?) So the lightvalue at a certain point : lightvalue = normal.z * 255 (mode 13h, so only 256 colors :( ) U have it, u have bump mapping. Nope, we don't know how to move the light source !