2011-06-24 32 views
1

我一直在使用OpenGL和SDL基於瓷磚繪製地圖的方法。最後,我編寫了代碼,但是當我執行繪製25x16瓦片地圖的基本程序時,我檢查了CPU的使用情況,它表示消耗25%,但沒有繪製地圖消耗CPU的1%。瓷磚地圖使用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的,它還沒有完成,這意味着它將使用更多中央處理器。所以這是正常的? –

+0

不成熟的優化是魔鬼。設計,編碼,測試和配置文件,以確定您的代碼在您的項目完成時可以優化哪些部分。 – AJG85

回答

1

畢竟,避免狀態變化。將所有瓷磚合併到一個紋理中,並僅使用一個塊進行渲染。

如果您不想進行多項更改,請嘗試display lists。 OpenGL將能夠優化您的通話,但不保證通話速度會更快。

如果你的地圖沒有改變很多,使用VBOs。這是最快的方法。

+0

但是,如果我將所有瓷磚合併到一個紋理中,則必須在每個循環中重新生成紋理,因爲某些瓷磚必須更改。例如,如果主角破壞了地圖的某個元素或類似的東西,這個圖塊就不會再繪製了,所以將所有圖塊合併到一個圖塊中會花費多少錢?還是我錯了?......不幸的是,地圖幾乎不斷變化,所以VBO或顯示列表對我幫助不大。感謝你的回答。 –

+0

@ oscar.rpr:我的意思是[this](http://www.swingswingsubmarine.com/wp-content/uploads/2010/11/Woodland_Tileset.png)。所有的圖像都是單紋理的,所以你不必調用'glBindTexture'。請使用'glTexCoord2i'來選擇圖像的正確部分。 –

+0

如果只有紋理在改變,那麼VBO不需要隨它們一起改變,除非你用紋理更新UV。一般來說,UV更新是根據我的經驗製作動畫的最快方式。另外,如果你沒有在每次抽搐中更改每個地圖的VBO,他們仍然可能會更快。你應該調查它。 –