I been working in a method to draw a map based on tiles with OpenGL and SDL. And I finally coded but when I execute the basic program where it draw a tile map of 25×16, and I check the use of CPU, it says that consume 25% but without drawing the map consume by much 1% of CPU.
So exists another method to draw the map or why is the use of CPU so high.
This is the code for drawing the map.
void CMapManager::drawMap(Map *map)
{
vector<ImagePtr> tempImages = CGameApplication::getInstance()->getGameApp()->getImages();
GLuint texture = tempImages.at(1)->getTexture();
glColor3f(1.0f, 1.0f, 1.0f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture( GL_TEXTURE_2D, texture );
glBegin( GL_QUADS );
for (int i = 0; i < map->getHeight(); i++)
{
for (int j = 0; j < map->getWidth(); j++)
{
ImagePtr imgDraw = tempImages.at(map->getMapTiles()[i][j]->getTypeTile());
glTexCoord2i( 0, 0 );
glVertex3f( imgDraw->getPosX() + (imgDraw->getWidth()*j), imgDraw->getPosY() + (imgDraw->getHeight()*i), 0.f );
//Bottom-left vertex (corner)
glTexCoord2i( 1, 0 );
glVertex3f( imgDraw->getOffsetX() + (imgDraw->getWidth()*j), imgDraw->getPosY() + (imgDraw->getHeight()*i), 0.f );
//Bottom-right vertex (corner)
glTexCoord2i( 1, 1 );
glVertex3f( imgDraw->getOffsetX() + (imgDraw->getWidth()*j), imgDraw->getOffsetY() + (imgDraw->getHeight()*i), 0.f );
//Top-right vertex (corner)
glTexCoord2i( 0, 1 );
glVertex3f( imgDraw->getPosX() + (imgDraw->getWidth()*j), imgDraw->getOffsetY() + (imgDraw->getHeight()*i), 0.f );
}
}
glEnd();
glDisable(GL_BLEND);
}
And in this method I call the function:
void CGameApplication::renderApplication()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_TEXTURE_2D);
vector<ImagePtr> tempImages = GApp->getImages();
vector<ImagePtr>::iterator iterImage;
for (iterImage = tempImages.begin(); iterImage != tempImages.end(); ++iterImage)
{
CImageM->drawSprites( (*iterImage)->getTexture(), (*iterImage)->getPosX(), (*iterImage)->getPosY(),
(*iterImage)->getOffsetX(), (*iterImage)->getOffsetY() );
}
vector<TextPtr> tempTexts = GApp->getTexts();
vector<TextPtr>::iterator iterText;
for (iterText = tempTexts.begin(); iterText != tempTexts.end(); ++iterText)
{
CTextM->drawFonts( (*iterText) );
}
CMapM->drawMap(GApp->getCurrentMap());
glDisable(GL_TEXTURE_2D);
}
I already set a Timer that after this function:
GameApplication->getCKeyboardHandler()->inputLogic();
GameApplication->renderApplication();
SDL_GL_SwapBuffers();
GameApplication->getGameApp()->getTimer()->delay();
And the delay function is:
void Timer::delay()
{
if( this->getTicks() < 1000 / FRAMES_PER_SECOND )
{
SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - this->getTicks() );
}
}
The const FRAMES_PER_SECOND it’s 5 in this moment.
And the function for convert image to GL texture is:
GLuint CImageManager::imageToGLTexture(std::string name)
{
GLuint texture;
SDL_Surface *surface;
GLenum texture_format;
GLint nOfColors;
if ( (surface = IMG_Load(name.c_str())) ) {
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
// get the number of channels in the SDL surface
nOfColors = surface->format->BytesPerPixel;
if (nOfColors == 4) // contains an alpha channel
{
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGBA;
else
texture_format = GL_BGRA_EXT;
}
else if (nOfColors == 3) // no alpha channel
{
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGB;
else
texture_format = GL_BGR_EXT;
}
else {
printf("warning: the image is not truecolor.. this will probably break\n");
// this error should not go unhandled
}
SDL_SetAlpha(surface, 0, 0);
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// Edit the texture object's image data using the information SDL_Surface gives us
glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, surface->pixels );
}
else {
printf("SDL could not load the image: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
if ( surface ) {
SDL_FreeSurface( surface );
}
return texture;
}
Thanks before hand for the help.
After all, avoid state changes. Combine all your tiles into one texture and render using only one
glBegin/glEndblock.If you don’t want to make many changes try display lists. OpenGL will be able to optimize your calls but there is no guarantee it will run much faster.
If your map doesn’t change a lot use VBOs. It’s the fastest way.