Jump to content
xisto Community
t3jem1405241533

Programming In Glut (lesson 6) Texture filters and lighting

Recommended Posts

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 file
If 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 texture
Next 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 file
If 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 texture
Next 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 file
If 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 texture
Next 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 by t3jem (see edit history)

Share this post


Link to post
Share on other sites

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.