Tile Map использует много ЦП с OpenGL и SDL - PullRequest
1 голос
/ 24 июня 2011

Я работал над методом рисования карты на основе плиток с OpenGL и SDL.И я наконец-то закодировал, но когда я выполняю базовую программу, где она рисует карту тайлов размером 25x16, и я проверяю использование ЦП, он говорит, что потребляет 25%, но без рисования карты потребляет гораздо больше 1% ЦП.

Так что существует еще один метод для рисования карты или почему использование процессора настолько высоко.

Это код для рисования карты.

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

Спасибо, прежде чем под рукой за помощь.

1 Ответ

1 голос
/ 24 июня 2011

В конце концов, избегайте изменений состояния. Объедините все свои плитки в одну текстуру и визуализируйте, используя только один glBegin / glEnd блок.

Если вы не хотите вносить много изменений, попробуйте отобразить списки . OpenGL сможет оптимизировать ваши звонки, но нет гарантии, что он будет работать намного быстрее.

Если ваша карта мало меняется, используйте VBO. Это самый быстрый способ.

...