t3jem1405241533 0 Report post Posted December 10, 2006 (edited) This tutorial demonstrates how to use texture filters and will let you see the differences of each filter. I will also be introducing lighting into this tutorial. We first have to create our "bitmap.h" header file with the functions we use to load our bitmaps, this is changed from the last tutorial to fit the needs of this one.The first thing to do is to link all of our OpenGL libraries and include our needed headers for the functions we will call. #pragma comment(lib, "opengl32.lib")//Link to the OpenGL libraries#pragma comment(lib, "glu32.lib")#pragma comment(lib, "glaux.lib")#include <windows.h> // Header File For Windows#include <gl\gl.h> // Header File For The OpenGL32 Library#include <gl\glu.h> // Header File For The GLu32 Library#include <gl\glaux.h> // Header File For The Glaux Library Next we define our first function with the same three arguments as the last tutorial (The texture array, file location, and place in array). This functon is going to load a linear filtered texture into our program. I will talk more about linear texturing in a little bit.bool linearbmp(UINT textureArray[], LPSTR strFileName, int ID)//define our arguments{ First, we want to make sure a file name was given, if it wasnt we return a false value to let the program know it failed, if a filename was given then we load our file into a new variable which we will use to manipulate the data into a readable format by our program. if(!strFileName) return false;//check for a filename AUX_RGBImageRec *pBitMap = auxDIBImageLoad(strFileName); //Load our fileIf there was no data loaded (usually in case of a false filename) then we exit the program if(pBitMap == NULL) exit(0);// If no data was loaded then exit the program.Now that we are done with all of our error checking we generate our texture and place it into our texture array; however, we are not done yet. glGenTextures(1, &textureArray[ID]);//Generate our textureNext we have to bind our texture to texture targets. Texture targets are just polygons that use the glVertex command. glBindTexture(GL_TEXTURE_2D, textureArray[ID]);//bind our texture to texture targets now for our filtering. We want to set our filtering in this function to use Linear filtering. Linear filtering will resize the image to the size needed throughout runtime, this uses the most CPU, but generates the best effect. We set linear filtering twice because the second argument in the function defines when we want to use the filter, "GL_TEXTURE_MIN_FILTER" is telling the program to use the set filter when the texture is near "...MAG_FILTER" tells the program to use the set filter when the texture is far. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//set linear filtering glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//set linear filtering now we finally finish the creation of our texture. The first argument tells the function we are using a 2D image, the second is the detail of the image (usually set to 0), the third is how many components are in use (red, green, blue), the fourth and fifth tell the application to find the size of the image itself (you can substitute for the actual size if you want, but it reduces compatibility with other images), the sixth argument is the size of the border, then we tell the application the type of image we are using (red, green, blue), then we let it know the data is in unsigned bytes, then we tell it where to get the data. glTexImage2D(GL_TEXTURE_2D, 0, 3, pBitMap->sizeX, pBitMap->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, pBitMap->data);//create our texture then we need to clear our variable to preven memory leaks if (pBitMap) //If pBitMap still has a value then we want to clear it. { if (pBitMap->data) { free(pBitMap->data); } free(pBitMap); } return true;} now we need to define our new function that will load images with the nearest filter.bool nearestbmp(UINT textureArray[], LPSTR strFileName, int ID)//define our new function{ First, we want to make sure a file name was given, if it wasnt we return a false value to let the program know it failed, if a filename was given then we load our file into a new variable which we will use to manipulate the data into a readable format by our program. if(!strFileName) return false;//check for a filename AUX_RGBImageRec *pBitMap = auxDIBImageLoad(strFileName); //Load our fileIf there was no data loaded (usually in case of a false filename) then we exit the program if(pBitMap == NULL) exit(0);// If no data was loaded then exit the program.Now that we are done with all of our error checking we generate our texture and place it into our texture array; however, we are not done yet. glGenTextures(1, &textureArray[ID]);//Generate our textureNext we have to bind our texture to texture targets. Texture targets are just polygons that use the glVertex command. glBindTexture(GL_TEXTURE_2D, textureArray[ID]);//bind our texture to texture targets now for our filtering. We want to set our filtering in this function to use nearest filtering. the nearest filtering setting uses the least amount of CPU, but begins to become pixelized when brought closer to the screen. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);//set linear filtering glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);//set linear filtering now we finally finish the creation of our texture. The first argument tells the function we are using a 2D image, the second is the detail of the image (usually set to 0), the third is how many components are in use (red, green, blue), the fourth and fifth tell the application to find the size of the image itself (you can substitute for the actual size if you want, but it reduces compatibility with other images), the sixth argument is the size of the border, then we tell the application the type of image we are using (red, green, blue), then we let it know the data is in unsigned bytes, then we tell it where to get the data. glTexImage2D(GL_TEXTURE_2D, 0, 3, pBitMap->sizeX, pBitMap->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, pBitMap->data);//create our texture then we need to clear our variable to preven memory leaks if (pBitMap) //If pBitMap still has a value then we want to clear it. { if (pBitMap->data) { free(pBitMap->data); } free(pBitMap); } return true;} We now define our function that will load mipmap images, it has the same arguments as the previous two functions.bool mipmapbmp(UINT textureArray[], LPSTR strFileName, int ID)//define our function{First, we want to make sure a file name was given, if it wasnt we return a false value to let the program know it failed, if a filename was given then we load our file into a new variable which we will use to manipulate the data into a readable format by our program. if(!strFileName) return false;//check for a filename AUX_RGBImageRec *pBitMap = auxDIBImageLoad(strFileName); //Load our fileIf there was no data loaded (usually in case of a false filename) then we exit the program if(pBitMap == NULL) exit(0);// If no data was loaded then exit the program.Now that we are done with all of our error checking we generate our texture and place it into our texture array; however, we are not done yet. glGenTextures(1, &textureArray[ID]);//Generate our textureNext we have to bind our texture to texture targets. Texture targets are just polygons that use the glVertex command. glBindTexture(GL_TEXTURE_2D, textureArray[ID]);//bind our texture to texture targets our filter for textures far from the camera will still be linear; however, when they are closer to the camera we will use mipmapping. Mipmapping loads the image then resizes it into lots of different sizes and during runtime decides which texture to use. This is the most efficient filter for the quality. Mipmapping also eliminates the need for the width and height of the image to be a power of two. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//set linear filter glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); //(NEW) set mipmapping filter and next we have to create our texture, the next function is much like glTexImage2d except that it creates the different textures needed for the mipmapping, it has all of the same arguments except for the detail argument which is ommited. gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pBitMap->sizeX, pBitMap->sizeY, GL_RGB, GL_UNSIGNED_BYTE, pBitMap->data); //(NEW)create our mipmap texture then we need to clear our variable to preven memory leaks if (pBitMap) //If pBitMap still has a value then we want to clear it. { if (pBitMap->data) { free(pBitMap->data); } free(pBitMap); } return true;} The next section of code is the main body of the program.we start by loading our header files, we need to load our bitmap.h file to so we can use the functions defined in it#include<glut.h>#include"bmpload.h"//Load the header file we created above next we create an array to hold 3 textures, 1 for each filter. We then create a rotation variable and speed variable to keep track of the cube's spin and speed, lastly we initialize a variable to keep track of which filter we are using.GLuint textures[3];//create our texture arrayfloat rotation = 0;//initialize rotation variablefloat rotspeed = 0;//initialize speed variableint filter=0;//(NEW) initialize filter variable now we create our init function that will initialize our opengl settings, it will also include the lighting settings.void init(){ we need to create three arrays. Each array will hold a different value for our light. The first array will define the ambient color, this is the color the object will look, we have to use this setting instead of glcolor3f(), but to define the colors for all light values it is the same. The second array will define the diffuse color, this is the color of the bright areas of the object or the color of the light. The last array is the position of the light, this is the same as glVertex3f, but it has an added variable in it which should just be set to 1. GLfloat ambient[]= {0.5f,0.5f,0.5f,1.0f}; // (NEW) define the object color GLfloat diffuse[]= {1.0f,1.0f,1.0f,1.0f}; // (NEW) define the light color GLfloat position[]= {10,5,-5,1}; // (NEW) set the light position next we have to put our settings into effect. We have to initialize our settings with the glLightfv() function. The first parameter is which light the setting will effect (there are 8 lights), the second argument is the setting to affect and the last is your variable holding the setting. There are five different settings, but we will only go over three in this tutorial. glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); //(NEW) set the ambient value glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); //(NEW) set the diffuse value glLightfv(GL_LIGHT1, GL_POSITION,position); //(NEW) set the position next we have to enable two things, lighting and light1. Enable light1 enables the light we have just set up and enabling lighting enables all lighting. glEnable(GL_LIGHT1);//(NEW) enable light1 glEnable(GL_LIGHTING);//(NEW) enable lighting next we setup our clear color and our screen size. glClearColor(0,0,0,0); glOrtho(-10,10,-10,10,-10,10);//setup screen size. now we load our textures using the functions we created in our "bitmap.h" file. We load our texture with the linear filter, nearest filter, and mipmap filter into our texture array in that order. The we finally enable depth testing and finish with our init function. linearbmp(textures, "image.bmp",0);// (NEW) load a linear texture nearestbmp(textures, "image.bmp",1);// (NEW) load a nearest texture mipmapbmp(textures, "image.bmp",2);// (NEW) load a mipmap texture glEnable(GL_DEPTH_TEST);//3D objects require depth testing to be on} now we start writing our display function which will draw all our objects to the screen. As always we will start by clearing the screen.void display(){ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//clear the screen next we enable texturing and then bind the texture we want based on the filter selected. glEnable(GL_TEXTURE_2D);//Enable 2D texturing glBindTexture(GL_TEXTURE_2D, textures[filter]);//bind our texture Now we create a matrix for our transformation, we will rotate the cube based on the amount of the rotation variable, with this you can watch the light changing on the faces of the cube. glPushMatrix(); glRotatef(rotation, 0.5,-.6,.2);//rotate our cube Next we create our cube. The only difference in creating our cube this time is the glNormal3f() function. This function defines a ray that points outward at a 90 degree angle from the middle of the polygon you are defining it for. glNormal3f() tells the program how to light the polygon depending on its angle to the light, you can use it point by point or you can use one glnormal3f() call per face. For this tutorial we will call it once per face. glBegin(GL_QUADS);// begin drawing our cube glNormal3f(0,0,-1);//(NEW) set our normal glTexCoord2f(0,1); glVertex3f(-4,4,-4); glTexCoord2f(1,1); glVertex3f(4,4,-4); glTexCoord2f(1,0); glVertex3f(4,-4,-4); glTexCoord2f(0,0); glVertex3f(-4,-4,-4); //This is the back face glNormal3f(0,0,1);//(NEW) glTexCoord2f(0,1); glVertex3f(-4,4,4); glTexCoord2f(1,1); glVertex3f(4,4,4); glTexCoord2f(1,0); glVertex3f(4,-4,4); glTexCoord2f(0,0); glVertex3f(-4,-4,4); //This is the left face glNormal3f(-1,0,0);//(NEW) glTexCoord2f(0,1); glVertex3f(-4,4,4); glTexCoord2f(1,1); glVertex3f(-4,4,-4); glTexCoord2f(1,0); glVertex3f(-4,-4,-4); glTexCoord2f(0,0); glVertex3f(-4,-4,4); //This is the right face glNormal3f(1,0,0);//(NEW) glTexCoord2f(0,1); glVertex3f(4,4,4); glTexCoord2f(1,1); glVertex3f(4,4,-4); glTexCoord2f(1,0); glVertex3f(4,-4,-4); glTexCoord2f(0,0); glVertex3f(4,-4,4); //This is the bottom face glNormal3f(0,-1,0);//(NEW) glTexCoord2f(0,1); glVertex3f(-4,-4,4); glTexCoord2f(1,1); glVertex3f(-4,-4,-4); glTexCoord2f(1,0); glVertex3f(4,-4,-4); glTexCoord2f(0,0); glVertex3f(4,-4,4); //This is the top face glNormal3f(0,1,0);//(NEW) glTexCoord2f(0,1); glVertex3f(-4,4,4); glTexCoord2f(1,1); glVertex3f(-4,4,-4); glTexCoord2f(1,0); glVertex3f(4,4,-4); glTexCoord2f(0,0); glVertex3f(4,4,4); glEnd(); now we close our matrix, disable texturing (in good habit to prevent odd effects in future applications), tell the program to draw everything to the screen, tell the program to start drawing again, and finally we add our rotation speed variable to our rotation variable. glPopMatrix(); glDisable(GL_TEXTURE_2D);//disable texturing glFlush(); glutPostRedisplay(); rotation += rotspeed;} next we define our keyboard function which will use keyboard commands to tell the program what to do.void keyboard(unsigned char key, int x, int y){we start our switch statements to tell the program what to do according to the key presses.when we press 'L' or 'R' then it will adjust the speed of the spinning cube. pressing 1-3 will change the filter we use on the cube switch(key)//start are switch statements { case 'L':case'l'://Increase the speed of the spinning cube. rotspeed += 0.05; break; case 'R':case'r'://Increase the speed of the spinning cube rotspeed -= 0.05; break; case '1'://choose the filter using our # keys filter = 0; break; case '2': filter = 1; break; case '3': filter = 2; break; default: break;//Don't do anything if any other keys are pressed }}we now finally finish our program with our main function that has been unchanged.void main(int argc, char ** argv){ glutInit(&argc, argv); glutInitWindowSize(800,600); glutInitWindowPosition(10,50); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);//Depth buffer required for 3D objects glutCreateWindow("Lesson 6"); init(); glutDisplayFunc(display); glutKeyboardFunc(keyboard);//This tells our program which function to send keyboard events to. glutMainLoop();} There are 7 different lights you can use at once GL_LIGHT1, GL_LIGHT2... You can enable all of them at once.There are a few more settings for lighting, but we will get into that later on in the tutorials. I hope this tutorial was helpful, and if you have any questions feel free to leave a reply. Edited January 24, 2007 by t3jem (see edit history) Share this post Link to post Share on other sites
iGuest 3 Report post Posted February 1, 2008 I very like your help on Programming in Glut Programming In Glut (lesson 6) Replying to t3jem I read all your 6 lessons in glut. And I want to know is next leesson 7? I can't find it. Your explatations are ideal, I thing you are the best teacher. PS. Sorry about my bad English. I am Latvian, that is in Europe. -Davispuh Share this post Link to post Share on other sites