Advertisement

Problem with textures...

Started by June 25, 2004 07:06 PM
6 comments, last by Alray 20 years, 5 months ago
Hello all, first time posting. The thing is I've got a homework for my programming class. I'm supposed to model a 3D maze, and be able to walk through it, and escape. The maze is created randomly through a function and return a 50x50 matrix, with 0s for Walls and 1s for Floor. So I decided, to create this sort of algorithm switch(maze[j]){ case WALL:{ DrawWall("some coordinates"); break; } case FLOOR:{ DrawFloor("more coordinates"); break; } } DrawWall just draws a cube and DrawFloor a square. Now this is the heart of the problem. I decided to go a little bit further in my modeling and I wanted to use some textures. The textures display fine, BUT they make the program SLOW as a crippled old turtle. I know games with much better graphics work much faster than my program. I used NeHe's method of using textures, so I don't really know if there's an option to make them load faster or something. I'm using 256x256 pixels BMPs. So are there any techniques I'm missing, or commands? Any input is really appreciated!! Thanks in advance!
maybe post some code...? you are just loading in a texture ONCE, no matter how many times you use it, right?
Advertisement
Mmm I guess I could... it will be a little long, but ok.
(If someone knows of a tag I'd appreciate it if you tell me)

//Sorry but the code is in spanish...
//This is the drawing code for cubes and floors

#include "dibujar.h"extern int laberinto[50][50];extern GLuint texture[2];extern double theta;extern double phi;void DibujarLaberinto(int Size){	int i,j;	for(j=0;j<Size;j++){		for(i=0;i<Size;i++){					switch(laberinto[j]){						case MURO:{						DibujarCubo(i,j,i+1,j+1);					  break;					  }			case VACIO:{					   DibujarSuelo(i,j,i+1,j+1);					   }									}		}		}}GLvoid DibujarCubo(int x1, int y1, int x2, int y2){	glDisable(GL_TEXTURE_2D);	glBegin(GL_QUADS);							//Lo que va en el suelo	{		glNormal3f( 0.0f, 0.0f, -1.0f);				glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3d(x1,y1,0);		glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3d(x2,y1,0);		glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3d( x2, y2,0);		glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3d( x1,y2,0);	}	glEnd();		glEnable(GL_TEXTURE_2D);	glBindTexture(GL_TEXTURE_2D, texture[1]);	glBegin(GL_QUADS);							//Pared Oeste	{			glNormal3f( -1.0f, 0.0f, 0.0f);				glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3d(x1,y1,0);		glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3d(x1,y2,0);		glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3d( x1, y2,y2-y1);		glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3d( x1,y1,y2-y1);	}	glEnd();	glBegin(GL_QUADS);							//Pared Este	{			glNormal3f( 1.0f, 0.0f, 0.0f);				glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3d(x2,y1,0);		glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3d(x2,y2,0);		glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3d( x2, y2,y2-y1);		glColor3f(1.0f,1.0f,1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3d( x2,y1,y2-y1);	}	glEnd();	glBegin(GL_QUADS);						//Pared Norte	{			glNormal3f( 0.0f, -1.0f, 0.0f);				glColor3f(1.0f,1.0f,1.0f);glTexCoord2f(0.0f, 0.0f);glVertex3d(x1,y1,0);		glColor3f(1.0f,1.0f,1.0f);glTexCoord2f(1.0f, 0.0f);glVertex3d(x2,y1,0);		glColor3f(1.0f,1.0f,1.0f);glTexCoord2f(1.0f, 1.0f);glVertex3d( x2, y1,y2-y1);		glColor3f(1.0f,1.0f,1.0f);glTexCoord2f(0.0f, 1.0f);glVertex3d( x1,y1,y2-y1);	}	glEnd();	glBegin(GL_QUADS);						//Pared Sur	{	glNormal3f( 0.0f, 1.0f, 0.0f);				glColor3f(1.0f,1.0f,1.0f);glTexCoord2f(0.0f, 0.0f);glVertex3d(x1,y2,0);		glColor3f(1.0f,1.0f,1.0f);glTexCoord2f(1.0f, 0.0f);glVertex3d(x2,y2,0);		glColor3f(1.0f,1.0f,1.0f);glTexCoord2f(1.0f, 1.0f);glVertex3d( x2, y2,y2-y1);		glColor3f(1.0f,1.0f,1.0f);glTexCoord2f(0.0f, 1.0f);glVertex3d( x1,y2,y2-y1);	}	glEnd();	glBegin(GL_QUADS);							//Lo que va en el techo	{		glNormal3f( 0.0f, 0.0f, 1.0f);				glColor3f(1.0f,1.0f,0.0f);glTexCoord2f(0.0f, 0.0f);glVertex3d(x1,y1,y2-y1);		glColor3f(1.0f,0.8f,0.0f);glTexCoord2f(1.0f, 0.0f);glVertex3d(x2,y1,y2-y1);		glColor3f(1.0f,0.6f,0.0f);glTexCoord2f(1.0f, 1.0f);glVertex3d( x2, y2,y2-y1);		glColor3f(1.0f,0.4f,0.0f);glTexCoord2f(0.0f, 1.0f);glVertex3d( x1,y2,y2-y1);	}	glEnd();}GLvoid DibujarSuelo(int x1, int y1, int x2, int y2){		glEnable(GL_TEXTURE_2D);	glBindTexture(GL_TEXTURE_2D, texture[0]);	glBegin(GL_QUADS);							//Lo que va en el suelo	{		glNormal3f( 0.0f, 0.0f, 1.0f);				glColor3f(1.0f,1.0f,1.0f);		glTexCoord2f(0.0f, 1.0f);	glVertex3d(x1,y1,0);		glColor3f(1.0f,1.0f,1.0f);		glTexCoord2f(1.0f, 1.0f); glVertex3d(x2,y1,0);		glColor3f(1.0f,1.0f,1.0f);		glTexCoord2f(1.0f, 0.0f); glVertex3d( x2, y2,0);		glColor3f(1.0f,1.0f,1.0f);		glTexCoord2f(0.0f, 0.0f);  	glVertex3d( x1,y2,0);	}	glEnd();}

//And here comes the important part of the main code
AUX_RGBImageRec *LoadBMP(char *Filename)				// Loads A Bitmap Image{	FILE *File=NULL;									// File Handle	if (!Filename)										// Make Sure A Filename Was Given	{		return NULL;									// If Not Return NULL	}	File=fopen(Filename,"r");							// Check To See If The File Exists	if (File)											// Does The File Exist?	{		fclose(File);									// Close The Handle		return auxDIBImageLoad(Filename);				// Load The Bitmap And Return A Pointer	}	return NULL;										// If Load Failed Return NULL}int LoadGLTextures(char string[], int numero)									// Load Bitmaps And Convert To Textures{	int Status=FALSE;									// Status Indicator	AUX_RGBImageRec *TextureImage[1];					// Create Storage Space For The Texture	memset(TextureImage,0,sizeof(void *)*1);           	// Set The Pointer To NULL	// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit	if (TextureImage[0]=LoadBMP(string))	{		Status=TRUE;									// Set The Status To TRUE		glGenTextures(1, &texture[numero]);					// Create The Texture		// Typical Texture Generation Using Data From The Bitmap		glBindTexture(GL_TEXTURE_2D, texture[numero]);		glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);	}	if (TextureImage[0])									// If Texture Exists	{		if (TextureImage[0]->data)							// If Texture Image Exists		{			free(TextureImage[0]->data);					// Free The Texture Image Memory		}		free(TextureImage[0]);								// Free The Image Structure	}	return Status;										// Return The Status}GLvoid ReSizeGLScene(GLsizei width, GLsizei height)		// Resize And Initialize The GL Window{	if (height==0)										// Prevent A Divide By Zero By	{		height=1;										// Making Height Equal One	}	glViewport(0,0,width,height);						// Reset The Current Viewport	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix	glLoadIdentity();									// Reset The Projection Matrix	// Calculate The Aspect Ratio Of The Window	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,1000.0f);	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix	glLoadIdentity();									// Reset The Modelview Matrix}int InitGL(GLvoid)										// All Setup For OpenGL Goes Here{	if (!LoadGLTextures("Data/grass.bmp",0)||!LoadGLTextures("Data/wall.bmp",1)){							// Jump To Texture Loading Routine ( NEW )			return FALSE;							// If Texture Didn't Load Return FALSE ( NEW )	}	glEnable(GL_TEXTURE_2D);						// Enable Texture Mapping ( NEW )	glShadeModel(GL_SMOOTH);							// Enable Smooth Shading	glClearColor(0.0f, 0.0f, 0.0f, 0.1f);				// Black Background	glClearDepth(1.0f);									// Depth Buffer Setup	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing	glDepthFunc(GL_LEQUAL);								// The Type Of Depth Testing To Do	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);				// Setup The Ambient Light	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);				// Setup The Diffuse Light	glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);			// Position The Light	glEnable(GL_LIGHT1);							// Enable Light One	glEnable(GL_LIGHTING);		// Enable Lighting	return TRUE;										// Initialization Went OK}int DrawGLScene(GLvoid)									// Here's Where We Do All The Drawing{	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer	glLoadIdentity();									// Reset The Current Modelview Matrix	if(jugador.EstoySaltando()){			jugador.Saltar(direccion);		}	if(!ChequearSuelo(jugador.DameX(),jugador.DameY(),jugador.DameZ())){		jugador.CambiarZ(-0.1);	}	switch(tipocamara){			case PLAYER:{			gluLookAt(jugador.DameX(), jugador.DameY(), jugador.DameZ(),jugador.DameX()+cos(theta),jugador.DameY()+sin(theta),jugador.DameZ()-cos(phi),0,0,1);			break;		}		case GOD:{			gluLookAt(jugador.DameX(), jugador.DameY(), jugador.DameZ()+7,jugador.DameX(), jugador.DameY(),-1,1,0,0);			break;		}		case GHOSTY:{			gluLookAt(jugador.DameX()-cos(theta), jugador.DameY()-sin(theta), jugador.DameZ()+1,jugador.DameX(), jugador.DameY(),jugador.DameZ(),cos(theta),sin(theta),1);			break;		}		}	PosMouse();	DibujarLaberinto(50);	if(tipocamara!=PLAYER){		DibujarHeroe(jugador.DameX(), jugador.DameY(), jugador.DameZ());	}	return TRUE;										// Everything Went OK}



//I really did not want to post it like this, I'd rather post the project for download if it's possible

[Edited by - Alray on June 27, 2004 12:05:22 PM]
[source] and [/source] tags would make that code a lot more plesant to read. I like how half the code is in English and the other half is in (I'm guessing) Spanish [wink].

A couple of things:


  1. You're texturing everything, right? If so, turn on texturing at the beginning of the program and leave it on. Generally speaking, changing states 2500+ times per frame (50 x 50) will absolutely kill your performance. If this isn't an option, you should try spliting up your main loop so that it only checks for one object at a time. This isn't a bad idea anyway to limit the number of times you switch textures. Basically, this allows you pull your state changing operations (including texture binding) out so they only get called once per type of object, if that. Trust me when I say that you can loop through the array multiple times a lot faster than making all of those state changes between iterations.

  2. You only need to call glColor* when you actually change the color. All those superfluous calls in the cube-drawing function are going to bog you down unnecessarily.


I hope that that helps you a little bit.
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
Ok, it's good to know that.

Yeah, one part of the code in NeHe's tutorial window initialization bit, and the other part is my actual drawing code, (of course there's more code, involving jumps, moving independent of frame rate, most of the Quake style movement functionality).

So, now that you mention it, what would be REALLY expensive operations for the computer in OpenGL?

All they taught us was how to create some polygons and that's about it, haha. Thanks for your response!
glClear is probably the slowest function available, although if you need to use it there's no real substitute (so don't worry about it). Next comes glEnable/glDisable and glBindTexture. Their relative orders change depending on what you pass in to glEnable/glDisable. These don't cost nearly as much performance as glClear (unless you enable something your card can't accelerate), but calling them a lot of times each frame will definitely slow you down a fair bit. Usually reorganizing your code to limit the number of changes you make to the GL state machine will significantly improve performance.
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
Advertisement
You don't need to call a separate glBegin( GL_QUADS ); and glEnd();
pair for every quad you draw. Once you have called glBegin( GL_QUADS ); once OpenGL will take the first four vertices given to it and turn them into a quad, and then the next four, and so forth until it hits a glEnd(). Therefore you only need to call the
glBegin(GL_QUADS); //Pared Oeste and the glEnd() at the very bottom of your drawing function and it will still have the same effect. Note though that you will need a seperate glBegin, glEnd pair for the first, untextured quad, as you cannot bind a texture inside a glBegin, glEnd pair.
Thank you very much!! A friend tried my new program at his Pentium III 800 MHz with not a really good graphic card, and he said it was running TOO fast! :D
Well I guess it should be, theoretically you can move 6 cubes per second!

In the end I ended up splitting DibujarLaberinto() like this:

void DibujarLaberinto(int Size){	int i,j;	glEnable(GL_TEXTURE_2D);	glBindTexture(GL_TEXTURE_2D, texture[1]);	for(j=0;j<Size;j++){		for(i=0;i<Size;i++){					switch(laberinto[j]){						case MURO:{						DibujarCubo(i,j,i+1,j+1);					  break;					  }			}		}		}	glBindTexture(GL_TEXTURE_2D, texture[0]);	for(j=0;j<Size;j++){		for(i=0;i<Size;i++){					switch(laberinto[j]){						case VACIO:{					   DibujarSuelo(i,j,i+1,j+1);					   }									}		}		}}


I need to run through the matrix twice but that's no biggie. It run smooth!

Thank you all again!! Will be posting again about some lighting issues after my Calculus Exam!! (I'm this close to failing...)

This topic is closed to new replies.

Advertisement