Welcome Guest ( Log In | Register )



 
Reply to this topicStart new topic
> Programming In Glut (lesson 6), Texture filters and lighting
t3jem
post Dec 10 2006, 06:17 AM
Post #1


Member [ Level 1 ]
Group Icon

Group: Members
Posts: 48
Joined: 23-November 06
Member No.: 17,478



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.
CODE

#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.
CODE

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.
CODE

    if(!strFileName)   return false;//check for a filename
    
    AUX_RGBImageRec *pBitMap = auxDIBImageLoad(strFileName); //Load our file

If there was no data loaded (usually in case of a false filename) then we exit the program
CODE

    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.
CODE

    glGenTextures(1, &textureArray[ID]);//Generate our texture

Next we have to bind our texture to texture targets. Texture targets are just polygons that use the glVertex command.
CODE

    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.
CODE

    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.
CODE

    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
CODE


    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.
CODE

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.
CODE

    if(!strFileName)   return false;//check for a filename
    
    AUX_RGBImageRec *pBitMap = auxDIBImageLoad(strFileName); //Load our file

If there was no data loaded (usually in case of a false filename) then we exit the program
CODE

    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.
CODE

    glGenTextures(1, &textureArray[ID]);//Generate our texture

Next we have to bind our texture to texture targets. Texture targets are just polygons that use the glVertex command.
CODE

    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.
CODE

    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.
CODE

    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
CODE


    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.
CODE

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.
CODE

    if(!strFileName)   return false;//check for a filename
    
    AUX_RGBImageRec *pBitMap = auxDIBImageLoad(strFileName); //Load our file

If there was no data loaded (usually in case of a false filename) then we exit the program
CODE

    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.
CODE

    glGenTextures(1, &textureArray[ID]);//Generate our texture

Next we have to bind our texture to texture targets. Texture targets are just polygons that use the glVertex command.
CODE

    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.

CODE

    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.
CODE

    

    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
CODE


    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
CODE

#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.
CODE

GLuint    textures[3];//create our texture array
float rotation = 0;//initialize rotation variable
float rotspeed = 0;//initialize speed variable
int 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.

CODE

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.
CODE

    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.
CODE

    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.
CODE

    glEnable(GL_LIGHT1);//(NEW) enable light1
    glEnable(GL_LIGHTING);//(NEW) enable lighting


next we setup our clear color and our screen size.
CODE

    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.
CODE


    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.

CODE

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.
CODE


    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.
CODE

    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.
CODE

    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.
CODE

    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.
CODE

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
CODE

    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.
CODE

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.

This post has been edited by t3jem: Jan 24 2007, 01:25 AM
Go to the top of the page
 
+Quote Post
iGuest
post Feb 1 2008, 11:51 AM
Post #2


Newbie [ Level 1 ]
Group Icon

Group: Members
Posts: 0
Joined: 1-November 07
Member No.: 25,869



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
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic

Collapse

> Similar Topics

Topics Topics
  1. Programming In Glut (lesson 1)(3)
  2. Programming In Glut (lesson 2)(8)
  3. Programming In Glut (lesson 3)(1)
  4. Programming In Glut (lesson 4)(7)
  5. Installing Glut To Dev C++(3)


 



- Lo-Fi Version Time is now: 11th October 2008 - 06:20 PM