You are on page 1of 20

KIT, MANGALORE

BUMP MAPPING

CHAPTER 1
1.1 INTRODUCTION
Computer graphics provides one of the most natural means of communicating with a computer .It includes the creation,storage,and manipulation of models and images of objects. Computer graphics mainly concerns with the pictorial synthesis of real and imaginary objects from their computer based models .It is more useful in the production of dynamically varying pictures which can show changes over time. Dynamically iterative graphics offers a wide range of user interface modes. In OpenGL Interface most of our application will be designed to access OpenGL directly through functions in three libraries. Functions in the main GL library have names that begin with the letter gl and are stored in library usually referred to GL . OpenGL Utility Toolkit GLUT,which provides the minimum functionality that should be expected in any modern windowing system.

Dept Of CS&E

Page 1

KIT, MANGALORE

BUMP MAPPING

1.2 PROJECT AIM


Program to demonstrate how to add lighting and material properties to a bump mapping : BUMP In geometry, a bump (pl. tori) is a surface of revolution generated by revolving a circle in three dimensional space about an axis coplanar with the circle. Real world examples of (approximately) toroidal objects include doughnuts, inner tubes, many lifebuoys, O-rings and Vortex rings.

Diagrammatical explanation of bump :

(a.) Bump Mapping

(b.) A bump is the product of two circles.

(c.)

(d.)

(e.)

(f.) This construction shows the bump divided into the maximum of seven regions,every one of which touches every other. Dept Of CS&E Page 2

KIT, MANGALORE

BUMP MAPPING

CHAPTER 2
2.1 LIGHT IN OPENGL
glEnable(int cap):- glEnable is used to enable lighting on the whole when you pass GL_LIGHTING parameter to it. gEnable is also responsible for enabling a particular light source in your 3D scene. This is done by calling glEnable(GL_LIGHTn); where n is the index number of the color you are enabling, ranging from 0 to 7 because OpenGL lets you specify a maximum of eight light sources. glDisable(int cap):- This function disables whatever properties were previously set with glEnable. glShadeModel(int mode); Selects the polygon shading model. Mode is the flag representing the shading mode. This flag can be set to either GL_FLAT or GL_SMOOTH. GL_SMOOTH shading is the default shading model, causes the computed colors of vertices to be interpolated as the primitive is rasterized, assigning different colors to each resulting pixel fragment. GL_FLAT shading selects the computed color of just one vertex and assigns it to all the pixel fragments generated by rasterizing a single primitive. In either case, the computed color of a vertex is the result of lighting, if lighting is enabled, or it is the current color at the time the vertex was specified, if lighting is disabled. glEnable(GL_LIGHT0); All of the provided 8 OpenGL light sources are enabled by default. And just for convenience, if you want to turn off an enabled light source, you would use the glDisable function: glDisable(GL_LIGHT0);

2.2. LIGHTNING PROPERTIES


THE TWO TYPES OF DEFINING LIGHT PROPERTIES IN OPENGL (LIGHT SOURCE and SURFACE MATERIAL) The first type of light properties is the one that describes a light source and the second type of light properties is the one that describes the light reflected by the material of an objects surface. The color of each light source is characterized by the color, in RGBA format, that it emits and is defined by using the function: glLight. The properties of the material the object is made of are defined by calling the function: glMaterial, and are characterized by the amount Dept Of CS&E Page 3

KIT, MANGALORE

BUMP MAPPING

of light that the material reflects. The surface material properties are also characterized by the RGBA color format.

2.3 SMOOTH AND FLAT SHADING


glShadeModel(GL_SMOOTH); After this call, all of the polygons will be smoothly shaded by using the Gourad-shading technique and according to the nearby light sources and polygon's material properties. In the traditional Gourad-shading technique the illumination is computed exactly at the vertices and the values are interpolated across the polygon.

2.4 DEFINING A LIGHT SOURCE


OpenGL allows a maximum of 8 light sources in a scene at once. Each of the light sources can be either enabled or disabled. All of the 8 light sources are initially disabled, and are enabled with a call to glEnable. For each of the 8 light sources OpenGL has a name in the following format: GL_LIGHTn Where n is the index number of the light source you are specifying. n can be a value ranging from 0 to 7. It should be obvious that to specify a light source number 1 you would use GL_LIGHT0. By order, the light source number 8 is specified as GL_LIGHT7. To define a light source, OpenGL presents the programmer with a basic set of functions, specification of which divides itself into these already familiar to us light groups: Ambient Light, Diffuse Light, Specular Light and Emissive Light. For each of these types of light OpenGL #defines four models: GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR and GL_EMISSIVE respectively. For each one of the light sources you need to call the glLightfv function with parameters which specify the what, and more importantly the how. To add a component of specular light to a light source, you would make the following function call: GLfloat specular[] = {1.0f, 1.0f, 1.0f , 1.0f}; glLightfv(GL_LIGHT0, GL_SPECULAR, specular); specular[] is a 4-parameter array. Dept Of CS&E Page 4

KIT, MANGALORE specular[] = { floatRed, floatGreen, floatBlue, floatAlpha};

BUMP MAPPING

The first three parameters are the RGB values which can range from anywhere between 0.0f and 1.0f. 0.0f being no color, and 1.0f being full color. 0.5f would identify an average between the very bright color and the very dim color. The same glLightfv mechanism is used to specify any of the other three shading models. For example, to set and enable the Ambient Light component of a light source so that it emits Ambient Light of moderately pale white color (R=0.5f, G=0.5f, B=0.5f) you could use the following call and parameters: GLfloat ambient[] = { 1.0f, 1.0f, 1.0f }; GlLightfv(GL_LIGHT0, GL_AMBIENT, ambient); But assigning ambient, diffuse and specular types of light to a light source is not usually enough. You also have to specify the position of the light source. And this is, similarly to defining light components, done with the glLight function in the following way: Glfloat position[] = { -1.5f, 1.0f, -4.0f, 1.0f }; GlLightfv(GL_LIGHT0, GL_POSITION, position);

Dept Of CS&E

Page 5

KIT, MANGALORE

BUMP MAPPING

CHAPTER 3
3.1 MATERIAL PROPERTIES
DEFINING SURFACE MATERIAL PROPERTIES : In OpenGL, by assigning a material property to an object (defined by RGB color format), you are theoretically assigning the color which is reflected by that object. When you enable lighting with glEnable(GL_LIGHTING) you are generally expected to be assigning material properties with the glMaterial command as shown in the following code sample: float mcolor[] = { 1.0f, 0.0f, 0.0f, 1.0f }; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mcolor); glMaterial postfixed by fv takes vector-based color coordinates. The

GL_AMBIENT_AND_DIFFUSE parameter specifies that mcolor will be applied to both ambient and diffuse components of the material. This is done for convenience because in most cases Ambient and Diffuse properties of a material should be set to the same color.

3.2 The SPECULAR REFLECTION component


The SPECULAR REFLETION component of the material defines the effect the material has on the reflected light. This functionality can be obtained by defining the GL_SPECULAR component of the objects material. This property adds a glossy surface to the object you are modeling.

3.3 USAGES
There are a number of keyboard commands that control the animation. They must be

typed into the graphics window, and are listed below:

3.4 CONTROLLING RESOLUTION OF THE BUMP MESH


Press W to increase the number wraps. Press w to decrease the number wraps. Press N to increase the number of segments per wrap. Page 6

Dept Of CS&E

KIT, MANGALORE Press n to decrease the number of segments per wrap. Press q to toggle between quadrangles and triangles.

BUMP MAPPING

3.5 CONTROLLING THE ANIMATION


Press the a key to toggle the animation off and on. Press the s key to perform a single step of the animation.

The left and right arrow keys: Controls the rate of rotation around the y-axis. The up and down arrow keys: Increase and decrease the rate of rotation around the x-axis. In order to reverse

rotational direction you must zero or reset the bump (0 or r). Press the r key to reset the bump back to initial Position, with no rotation. Press 0 (zero) to zero the rotation rates.

3.6 CONTROLLING LIGHTS


Press 1 or 2 to toggle the first or second light off and on. Press f to toggle between flat and smooth shading. Press l to toggle local modes on and off (local viewer and positional light, or non-local viewer and directional light).

3.7 COMMANDS SHOWING OPENGL FEATURES


Pressing p toggles between wireframe and polygon mode. Pressing f key toggles between flat and smooth shading.

Dept Of CS&E

Page 7

KIT, MANGALORE

BUMP MAPPING

CHAPTER 4
4.1. SOURCE CODE
#include <stdlib.h> #include <math.h> #include <limits.h> #include <GL/glut.h> // OpenGL Graphics Utility Library

void myKeyboardFunc( unsigned char key, int x, int y ); void mySpecialKeyFunc( int key, int x, int y ); void updateScene( void ); void initRendering(); void resizeWindow(int w, int h); void KeyUp(); void KeyDown(); void KeyLeft(); void KeyRight(); void ResetAnimation(); void ZeroRotation(); void ShadeModelToggle(); void FillModeToggle(); void QuadTriangleToggle(); void LocalToggle(); void Light0Toggle(); void Light1Toggle(); void WrapMore(); void WrapLess(); void NumPerWrapMore(); void NumPerWrapLess(); // Bump specific routines. void putVert(int i, int j); const float PI2 = 2.0f*3.1415926535; GLenum runMode = GL_TRUE; GLenum shadeModel = GL_FLAT; // Toggles between GL_FLAT and GL_SMOOTH

Dept Of CS&E

Page 8

KIT, MANGALORE
GLenum polygonMode = GL_LINE; // Variables controlling the animation float RotX = 0.0f; float RotY = 0.0f; float RotIncrementX = 0.0; float RotIncrementY = 0.0; const float RotIncFactor = 1.5; // Rotational position around x-axis // Rotational position around y-axis // Rotational increment, x-axis // Rotational increment, y-axis // Factor change in rot rate per key stroke // Toggles between GL_LINE and GL_FILL

BUMP MAPPING

// Variables controlling the fineness of the polygonal mesh int NumWraps = 10; int NumPerWrap = 8; // Variables controlling the size of the bump float MajorRadius = 3.0; float MinorRadius = 1.0; // Mode flags int QuadMode = 1; GLenum LocalMode = GL_TRUE; int Light0Flag = 1; int Light1Flag = 1; // Lighting values float ambientLight[4] = {0.6, 0.6, 0.6, 1.0}; float Lt0amb[4] = {0.8, 0.8, 0.16, 1.0}; float Lt0diff[4] = {1.0, 1.0, 0.2, 1.0}; float Lt0spec[4] = {1.0, 1.0, 0.2, 1.0}; float Lt0pos[4] = {1.7*4.0, 0.0, 0.0, 1.0}; float Lt1amb[4] = {0.0, 0.0, 0.5, 1.0}; float Lt1diff[4] = {0.0, 0.0, 0.5, 1.0}; float Lt1spec[4] = {0.0, 0.0, 1.0, 1.0}; float Lt1pos[4] = {0.0, 1.2*4.0, 0.0, 1.0}; // Material values float Noemit[4] = {0.0, 0.0, 0.0, 1.0}; float Matspec[4] = {1.0, 1.0, 1.0, 1.0}; float Matnonspec[4] = {0.4, 0.05, 0.4, 1.0}; float Matshiny = 16.0; // 4 = MajorRadius + MinorRadius // Quad/Triangle toggling // Local viewer/non-local viewer mode // Is light #0 on? // Is light #1 on?

Dept Of CS&E

Page 9

KIT, MANGALORE
// glutKeyboardFunc is called below to set this function to handle // { switch ( key ) { case 'a': runMode = !runMode; break; case 's': runMode = GL_TRUE; updateScene(); runMode = GL_FALSE; break; case 27: // Escape key exit(1); case 'r': // Reset the animation (resets everything) ResetAnimation(); break; case '0': // Zero the rotation rates ZeroRotation(); break; case 'f': // Shade mode toggles from flat to smooth ShadeModelToggle(); break; case 'p': // Polygon mode toggles between fill and line FillModeToggle(); break; case 'w': break; case 'W': break; case 'n': // Decrement number of polys per wrap NumPerWrapLess(); break; case 'N': // Increment number of polys per wrap // Increment number of wraps around bump WrapMore(); // Decrement number of wraps around bump WrapLess(); all "normal" key presses. void myKeyboardFunc( unsigned char key, int x, int y )

BUMP MAPPING

NumPerWrapMore();

Dept Of CS&E

Page 10

KIT, MANGALORE
break; case 'q': // Toggle between triangles and Quadrilaterals QuadTriangleToggle(); break; case 'l': // Toggle between local and non-local viewer ('l' is for 'local') LocalToggle(); break; case '1': // Toggle light #0 on and off Light0Toggle(); break; case '2': // Toggle light #1 on and off Light1Toggle(); break; } } // glutSpecialFunc is called below to set this function to handle // // { switch ( key ) { case GLUT_KEY_UP: // Either increase upward rotation, or slow downward rotation KeyUp(); break; case GLUT_KEY_DOWN: // Either increase downwardward rotation, or slow upward rotation KeyDown(); break; case GLUT_KEY_LEFT: // Either increase left rotation, or slow down rightward rotation. KeyLeft(); break; case GLUT_KEY_RIGHT: // Either increase right rotation, or slow down leftward rotation. KeyRight(); break; } } all "special" key presses. See glut.h for the names of special keys.

BUMP MAPPING

void mySpecialKeyFunc( int key, int x, int y )

Dept Of CS&E

Page 11

KIT, MANGALORE

BUMP MAPPING

// The routines below are coded so that the only way to change from // one direction of rotation to the opposite direction is to first // reset the animation, void KeyUp() { if ( RotIncrementX == 0.0 ) { RotIncrementX = -0.1; } else if ( RotIncrementX < 0.0f) { RotIncrementX *= RotIncFactor; } else { RotIncrementX /= RotIncFactor; } } void KeyDown() { if ( RotIncrementX == 0.0 ) { RotIncrementX = 0.1; } else if ( RotIncrementX > 0.0f) { RotIncrementX *= RotIncFactor; } else { RotIncrementX /= RotIncFactor; } } void KeyLeft() { if ( RotIncrementY == 0.0 ) { RotIncrementY = -0.1; } else if ( RotIncrementY < 0.0) { RotIncrementY *= RotIncFactor; } else { // Initially, one-tenth degree rotation per update // Initially, one-tenth degree rotation per update // Initially, one-tenth degree rotation per update

Dept Of CS&E

Page 12

KIT, MANGALORE
RotIncrementY /= RotIncFactor; } } void KeyRight() { if ( RotIncrementY == 0.0 ) { RotIncrementY = 0.1; } else if ( RotIncrementY > 0.0) { RotIncrementY *= RotIncFactor; } else { RotIncrementY /= RotIncFactor; } } // Resets position and sets rotation rate back to zero. void ResetAnimation() { RotX = RotY = RotIncrementX = RotIncrementY = 0.0; } // Sets rotation rates back to zero. void ZeroRotation() { RotIncrementX = RotIncrementY = 0.0; } // Initially, one-tenth degree rotation per update

BUMP MAPPING

// Toggle between smooth and flat shading void ShadeModelToggle() { if ( shadeModel == GL_FLAT ) { shadeModel = GL_SMOOTH; } else {

Dept Of CS&E

Page 13

KIT, MANGALORE
shadeModel = GL_FLAT; } } // Toggle between line mode and fill mode for polygons. void FillModeToggle() { if ( polygonMode == GL_LINE ) { polygonMode = GL_FILL; } else { polygonMode = GL_LINE; } } // Toggle quadrilaterial and triangle mode void QuadTriangleToggle() { QuadMode = 1-QuadMode; } // Toggle from local to global mode void LocalToggle() { LocalMode = !LocalMode; if ( LocalMode ) { Lt0pos[3] = Lt1pos[3] = 1.0; } else { Lt0pos[3] = Lt1pos[3] = 0.0; } } // The next two routines toggle the lights on and off void Light0Toggle() { // Put lights at infinity too. // Put lights back at finite location.

BUMP MAPPING

Dept Of CS&E

Page 14

KIT, MANGALORE
Light0Flag = 1-Light0Flag; } void Light1Toggle() { Light1Flag = 1-Light1Flag; }

BUMP MAPPING

// Increment number of wraps void WrapMore() { NumWraps++; } // Decrement number of wraps void WrapLess() { if (NumWraps>4) { NumWraps--; } } // Increment number of segments per wrap void NumPerWrapMore() { NumPerWrap++; } // Decrement number segments per wrap void NumPerWrapLess() { if (NumPerWrap>4) { NumPerWrap--; } } /*

Dept Of CS&E

Page 15

KIT, MANGALORE
* issue vertex command for segment number j of wrap number i. */ void putVert(int i, int j) { float wrapFrac = (j%NumPerWrap)/(float)NumPerWrap; float phi = PI2*wrapFrac; float theta = PI2*(i%NumWraps+wrapFrac)/(float)NumWraps; float sinphi = sin(phi); float cosphi = cos(phi); float sintheta = sin(theta); float costheta = cos(theta); float y = MinorRadius*sinphi; float r = MajorRadius + MinorRadius*cosphi; float x = sintheta*r; float z = costheta*r; glNormal3f(sintheta*cosphi, sinphi, costheta*cosphi); glVertex3f(x,y,z); }

BUMP MAPPING

void updateScene( void ) { int i,j; // Clear the redering window glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glShadeModel( shadeModel ); // Set the shading to flat or smooth.

glPolygonMode(GL_FRONT_AND_BACK, polygonMode); // Set to be "wire" or "solid" glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, LocalMode); // Set up lights if ( Light0Flag==1 || Light1Flag==1 ) { // Emissive spheres have no other color. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Noemit); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Noemit); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0); } if ( Light0Flag==1 )

Dept Of CS&E

Page 16

KIT, MANGALORE
{ glPushMatrix(); glTranslatef(Lt0pos[0], Lt0pos[1], Lt0pos[2]); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Lt0spec); glutSolidSphere(0.2,5,5); glPopMatrix(); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, Lt0pos); } else { glDisable(GL_LIGHT0); } if ( Light1Flag==1 ) { glPushMatrix(); glTranslatef(Lt1pos[0], Lt1pos[1], Lt1pos[2]); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Lt1spec); glutSolidSphere(0.2,5,5); glPopMatrix(); glEnable(GL_LIGHT1); glLightfv(GL_LIGHT1, GL_POSITION, Lt1pos); } else { glDisable(GL_LIGHT1); } // Bump Materials glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Matnonspec); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Matspec); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, Matshiny); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Noemit); glPushMatrix(); // Save to use again next time.

BUMP MAPPING

// Update the orientation of the bump, if the animation is running. if ( runMode ) { RotY += RotIncrementY;

Dept Of CS&E

Page 17

KIT, MANGALORE
if ( fabs(RotY)>360.0 ) { RotY -= 360.0*((int)(RotY/360.0)); } RotX += RotIncrementX; if ( fabs(RotX)>360.0 ) { RotX -= 360.0*((int)(RotX/360.0)); } } // Set the orientation. glRotatef( RotX, 1.0, 0.0, 0.0); glRotatef( RotY, 0.0, 1.0, 0.0); // Draw the bump glColor3f( 1.0, 0.5, 1.0 ); glBegin( QuadMode==1 ? GL_QUAD_STRIP : GL_TRIANGLE_STRIP ); for (i=0; i<NumWraps; i++ ) { for (j=0; j<NumPerWrap; j++) { putVert(i,j); putVert(i+1,j); } } putVert(0,0); putVert(1,0); glEnd(); // Draw the reference pyramid glTranslatef( -MajorRadius-MinorRadius-0.3, 0.0, 0.0); glScalef( 0.2f, 0.2f, 0.2f ); glColor3f( 1.0f, 1.0f, 0.0f ); glBegin(GL_TRIANGLE_STRIP); glVertex3f( -0.5, 0.0, sqrt(3.0)*0.5 ); glVertex3f( -0.5, 0.0, -sqrt(3.0)*0.5 ); glVertex3f( 1.0, 0.0, 0.0); glVertex3f( 0.0, sqrt(2.0), 0.0); glVertex3f( -0.5, 0.0, sqrt(3.0)*0.5 ); glVertex3f( -0.5, 0.0, -sqrt(3.0)*0.5 ); glEnd();

BUMP MAPPING

Dept Of CS&E

Page 18

KIT, MANGALORE
glPopMatrix(); // Restore to original matrix as set in resizeWindow()

BUMP MAPPING

// Flush the pipeline, swap the buffers glFlush(); glutSwapBuffers(); } // Initialize OpenGL void initRendering() { glEnable( GL_DEPTH_TEST ); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight); // Light 0 (Position is set in updateScene) glLightfv(GL_LIGHT0, GL_AMBIENT, Lt0amb); glLightfv(GL_LIGHT0, GL_DIFFUSE, Lt0diff); glLightfv(GL_LIGHT0, GL_SPECULAR, Lt0spec); // Light 1 (Position is set in updateScene) glLightfv(GL_LIGHT1, GL_AMBIENT, Lt1amb); glLightfv(GL_LIGHT1, GL_DIFFUSE, Lt1diff); glLightfv(GL_LIGHT1, GL_SPECULAR, Lt1spec); } // Called when the window is resized // Sets up the projection view matrix (somewhat poorly, however) void resizeWindow(int w, int h) { float aspectRatio; glViewport( 0, 0, w, h ); h = (w == 0) ? 1 : h; aspectRatio = (float)w/(float)h; // Set up the proection view matrix glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 60.0, aspectRatio, 1.0, 30.0 ); // View port uses whole window // Ambient light // Enable lighting calculations // Turn on lights (unnecessary here, since also in Animate()

Dept Of CS&E

Page 19

KIT, MANGALORE

BUMP MAPPING

glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); // Move system 10 units away to be able to view from the origin. glTranslatef(0.0, 0.0, -10.0); // Tilt system 15 degrees downward in order to view from above // the xy-plane. glRotatef(15.0, 1.0,0.0,0.0); }

// Main routine // Set up OpenGL, hook up callbacks, and start the main loop int main( int argc, char** argv ) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ); // Window position (from top corner), and size (width and hieght) glutInitWindowPosition( 10, 60 ); glutInitWindowSize( 620, 160 ); glutCreateWindow( "BUMP MAPPING demo" ); // Initialize OpenGL rendering modes initRendering(); resizeWindow(620,160); // Set up callback functions for key presses glutKeyboardFunc( myKeyboardFunc ); glutSpecialFunc( mySpecialKeyFunc ); // Set up the callback function for resizing windows glutReshapeFunc( resizeWindow ); // Call this for background processing glutIdleFunc( updateScene ); // Call this whenever window needs redrawing glutDisplayFunc( updateScene ); // Start the main loop. glutMainLoop never returns. glutMainLoop( ); return(0); } // This line is never reached.

Dept Of CS&E

Page 20

You might also like