2011-06-24 16 views
1

OpenGLとSDLを使用してタイルに基づいてマップを描画する方法で作業していました。そして最後にコード化しましたが、基本的なプログラムを実行して25x16のタイルマップを描画し、CPUの使用をチェックすると、CPU消費量は25%ですが、マップを描画することなく1%のCPUで消費されます。タイルマップの使用OpenGLとSDLを使用した多くの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; 
} 

おかげで助けを求める手の前に。

+0

それほど悪くないです...他の3Dアプリケーションを実行し、レンダリング時にCPU使用率を調べてみてください。 – AJG85

+0

いくつかの基本的な3Dアプリケーションを実行し、20%のCPU、15%のCPU、最大30%のCPUを使用していますが、それは私のアプリケーションが2Dであることを心配していて、まだ完了していません。 CPU。だからそれは正常ですか? –

+0

時期尚早最適化は悪魔です。プロジェクトの完成時に最適化できるコード領域を決定するための設計、コード化、テスト、プロファイル。 – AJG85

答えて

1

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

多くの変更を加えたくない場合は、display listsを試してください。 OpenGLはあなたの呼び出しを最適化することができますが、それははるかに速く動作する保証はありません。

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

+0

しかし、すべてのタイルを1つのテクスチャにまとめると、タイルの一部を変更する必要があるため、すべてのループでそのテクスチャを再生成する必要があります。たとえば、主人公が地図の要素などを破壊すると、このタイルはそれ以上描画されません。そのため、すべてのタイルを1つのテクスチャにまとめると、少しコストがかかります。または間違っていますか?残念ながら、マップはほとんど変わらず、VBOや表示リストは私にはあまり役立ちません。答えをありがとう。 –

+0

@ oscar.rpr:私は[this](http://www.swingswingsubmarine.com/wp-content/uploads/2010/11/Woodland_Tileset.png)のようなものを意味していました。すべての画像は単一のテクスチャ上にあるので、 'glBindTexture'を呼び出す必要はありません。その代わりに 'glTexCoord2i'を使ってイメージの正しい部分を選択してください。 –

+0

テクスチャのみが変更されている場合は、テクスチャでUVを更新しない限り、VBOを変更する必要はありません。私の経験では、UVアップデートが一般的に最も速くアニメーション化されます。また、毎回地図のVBOを変更していない場合は、おそらくもっと速いでしょう。あなたはそれを調べるべきです。 –

関連する問題