Bump Mapping


Bump mapping modifies the normal returned by method Primitive->GetNormal according to the luma component(Y from YCbCr) around a given point. From the original normal vector, we create two vectors s1,s2 perpendicular to normal and to each other. We get four points, which are from original point in direction s1,-s1,s2,-s2. From color in these points we get the luma component(Y) a then we can modify s1 and s2 by differences in Y. New normal is perpendicular to these modified s1,s2.

Below we can see spheres with same textures with (on the left side) and without (on the right side) bump mapping.

Bump Mapping WoodBump Mapping Wood
Bump Mapping MarbleBump Mapping Marble
Source code (core part):

// from Sphere.hxx (InfinitePlane.hxx)

Vec3f GetNormal(Ray &ray)

{

       Vec3f normal = Vec3f(ray.org + ray.t * ray.dir - center);

       Normalize(normal);

 

       if (bumpMap) {

             Vec3f point = ray.org + ray.t * ray.dir;

            

             // 2 vectors perpendicular to normal and to each other

             Vec3f s1, s2;

             double MIN_DOUBLE = 0.0001;

             if (fabs(normal.z()) >MIN_DOUBLE)

                    s1 = Vec3f(-1, 1, (normal.x()-normal.y()) / normal.z() );

             else if (fabs(normal.y()) > MIN_DOUBLE)

                    s1 = Vec3f(-1, (normal.x()-normal.z()) / normal.y(), 1);

             else  // y and z are 0

                    s1 = Vec3f(0, 0, 1);

 

             s2 = normal.cross(s1);

             Normalize(s1);

             Normalize(s2);

 

             // distance in which we compare colors

             double delta = 0.01;

             double grad, grad2;

            

             Vec3f p1 = point+s1*delta;

             Vec3f p2 = point-s1*delta;

             Vec3f p3 = point+s2*delta;

             Vec3f p4 = point-s2*delta;

 

             // compute colors around our point to find out new normal

             Vec3f color1 = shader->GetColor(0, 0, p1, this);

             Vec3f color2 = shader->GetColor(0, 0, p2, this);

             Vec3f color3 = shader->GetColor(0, 0, p3, this);

             Vec3f color4 = shader->GetColor(0, 0, p4, this);

 

             // gradient of color in direction s1, s2 through the point

             grad = getYFromYCbCr(color1) - getYFromYCbCr(color2);

             grad2 = getYFromYCbCr(color3) - getYFromYCbCr(color4);

                          

             // change vectors according to gradients

             s1 += grad  * normal;

             s2 += grad2 * normal;

 

             // new normal vector is perpendicular to changed s1, s2

             Vec3f newNormal = s1.cross(s2);

 

             // check if we dont got opposite vector from vector product

             if ( fabs(acos( normal.dot(newNormal) / (normal.length()*newNormal.length()))) > M_PI/2 )

                    newNormal = - newNormal;

                                 

             Normalize(newNormal);

             return newNormal;         

       }

 

       return normal;                

};

References: