1

我一直在研究一种基于 OpenGL 和 SDL 的瓷砖绘制地图的方法。我终于编码了,但是当我执行基本程序时,它绘制了一个 25x16 的平铺地图,并检查了 CPU 的使用情况,它说消耗 25%,但不绘制地图会消耗 1% 的 CPU。

因此存在另一种绘制地图的方法,或者为什么 CPU 的使用率如此之高。

这是绘制地图的代码。

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);

}

在这种方法中,我调用了该函数:

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);

}

我已经在这个函数之后设置了一个定时器:

    GameApplication->getCKeyboardHandler()->inputLogic();
    GameApplication->renderApplication();

    SDL_GL_SwapBuffers();

    GameApplication->getGameApp()->getTimer()->delay();

延迟函数为:

void Timer::delay()
{
    if( this->getTicks() < 1000 / FRAMES_PER_SECOND )
    {
        SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - this->getTicks() );
    }
}

const FRAMES_PER_SECOND 此刻为 5。

将图像转换为 GL 纹理的函数是:

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;
}

事先感谢您的帮助。

4

1 回答 1

1

毕竟,避免状态变化。将所有图块组合成一个纹理并仅使用一个glBegin/glEnd块进行渲染。

如果您不想进行很多更改,请尝试显示列表。OpenGL 将能够优化您的调用,但不能保证它会运行得更快。

如果您的地图没有太大变化,请使用 VBO。这是最快的方法。

于 2011-06-24T15:21:51.037 回答