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

結局のところ、状態の変化は避けてください。すべてのタイルを1つのテクスチャに結合し、1つのglBegin/glEndブロックのみを使用してレンダリングします。

多くの変更を加えたくない場合は、ディスプレイリストを試してください。OpenGLは通話を最適化できますが、はるかに高速に実行される保証はありません。

マップがあまり変わらない場合は、VBOを使用してください。それが最速の方法です。

于 2011-06-24T15:21:51.037 に答える