Problem with textures...
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!
June 25, 2004 07:52 PM
maybe post some code...? you are just loading in a texture ONCE, no matter how many times you use it, right?
Mmm I guess I could... it will be a little long, but ok.
(If someone knows of a
(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:
I hope that that helps you a little bit.
A couple of things:
- 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.
- 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!
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______________________________________________________________________________________
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.
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:
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...)
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
Popular Topics
Advertisement