2009-10-26 74 views
0

更新:

我已經發布了下面的渲染器代碼,因爲這裏的代碼似乎沒有問題。OpenGL - 紋理加載不正確

我遇到了一些我的代碼的問題,當我嘗試上傳多個紋理到openGL時,一次只有一個,它的渲染效果有點令人驚歎,渲染器只能使用單個紋理。我已經做了一些調試來跟蹤這個函數的錯誤,但是我在確定函數的哪一部分有問題時遇到了問題。是否有特別明顯的擰緊,我只是沒有看到,或者我的代碼中有更微妙的缺陷?

我這裏還有我用來存儲紋理信息,通常只是讓我的所有指針

typedef struct { 
    float Width; 
    float Height; 
} texInfo; 

typedef struct { 
    dshlib::utfstr ResourceName; 
    texInfo * TextureInfo; 
    GLuint TextureNum; 
    SDL_Surface * Image; 
} texCacheItem; 

的跟蹤和這裏的結構是當前WIP圖形裝載機。基本上,它使用預先寫入的庫(順便說一下,它正在使用此程序進行測試)從.zip壓縮文件中加載一個名爲.png的文件。然後加載libpng,然後加載爲紋理,並緩存拋出以加快裝載速度並避免多次加載單個紋理。我忽略了#include語句,因爲它們只是一句蹩腳的文字。

texCacheItem * loadGraphics(dshlib::utfstr FileName) { 

    for(int i = 0; i < NumTexCached; i++) { //First see if this texture has already been loaded 
    if(TextureCache[i]->ResourceName == FileName) 
     return TextureCache[i]; 
    } 

    dshlib::utfstr FullFileName = "Data/Graphics/"; //If not, create the full file path in the archive 
    FullFileName += FileName; 
    dshlib::FilePtr file = resourceCtr.OpenFile(FullFileName); //And open the file 

    if (!file->IsOk()) { //If the file failed to load... 
    EngineState = ENGINESTATE_ERR; 
    return NULL; 
    } 

    SDL_Surface * T = loadPNG(file); 
    texCacheItem * Texture = new texCacheItem; 
    Texture->TextureInfo = new texInfo; 

    glGenTextures(1, &Texture->TextureNum); //Allocate one more texture and save the name to the texCacheItem 
    glBindTexture(GL_TEXTURE_2D, Texture->TextureNum); //Then create it 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, T->w, T->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, T->pixels); 

    Texture->TextureInfo->Width = (float)T->w; //Write the useful data 
    Texture->TextureInfo->Height = (float)T->h; 
    Texture->ResourceName = FileName; //And the caching info needed 
    Texture->Image = T; //And save the image for if it's needed later and for deleting 

    if (!TexCacheSize) { //If this is the first load this is 0, so allocate the first 8 Cache slots. 
    TexCacheSize = 8; 
    TextureCache = new texCacheItem*[8]; 
    } 

    if(NumTexCached == TexCacheSize) { //If we're out of cache space 
    if (TexCacheSize == 32768) { //If too many cache items, error out 
     EngineState = ENGINESTATE_ERR; 
     return NULL; 
    } 
    TexCacheSize <<= 1; //Double cache size 
    texCacheItem ** NewSet = new texCacheItem*[TexCacheSize]; 
    memcpy(NewSet, TextureCache, NumTexCached * sizeof(texCacheItem*)); //And copy over the old cache 
    delete TextureCache; //Delete the old cache 
    TextureCache = NewSet; //And assign the pointer to the new one 
    } 
    TextureCache[NumTexCached++] = Texture; //Store the texCacheItem to the Cache 

    file->Close(); //Close the file 
    file = NULL; //And NULL the smart pointer. [NTS: Confirm with Disch this is what won't cause a memory leak] 

    return Texture; //And return the loaded texture in texCacheItem form. 
} 

SDL_Surface *loadPNG(dshlib::FilePtr File) 
{ 
    Uint8 *PNGFile = new Uint8[(long)File->GetSize()]; 
    File->GetAr<Uint8>(PNGFile, (long)File->GetSize()); 
    return IMG_LoadPNG_RW(SDL_RWFromMem(PNGFile, (long)File->GetSize())); 
} 

下面是渲染器代碼文件。這一刻相當混亂,爲此道歉。 level-> activeMap基本上告訴渲染器tilemap的哪個「層」(0是前面,3是後面)來繪製上面的精靈。

#include "../MegaJul.h" 
void render(void) { 

    //Render the current tilemap to the screen 

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
glLoadIdentity(); 
glTranslatef(0.0f, 0.0f, -4.0f); 

if (level) { 

glBegin(GL_QUADS); 
float dT = 32.0f/level->dTex; 
float sX, fX, fXa, sY, tX, tY, sYa, sYb, sXa, tXa, tYa; 
unsigned long m = level->mapDimensions[0] * level->mapDimensions[1]; 
float ai; long long t; Sint16 * p; 
glBindTexture(GL_TEXTURE_2D, level->tilemap->TextureNum); 

for (int i = 3; i >= 0; i--) { 

    if (level->layers[i]->mapPosition[0] > 0) 
    level->layers[i]->mapPosition[0] = 0; 
    if (level->layers[i]->mapPosition[0] < 0 - (signed long)((level->mapDimensions[0] - 21) * 32)) 
    level->layers[i]->mapPosition[0] = 0 - (signed long)((level->mapDimensions[0] - 21) * 32); 

    if (level->layers[i]->mapPosition[1] < 0) 
    level->layers[i]->mapPosition[1] = 0; 
    if (level->layers[i]->mapPosition[1] > (signed long)((level->mapDimensions[1] - 16) * 32)) 
    level->layers[i]->mapPosition[1] = (signed long)((level->mapDimensions[1] - 16) * 32); 

    if (i == level->activeMap) { 
    for (int j = 0; j < NumSprites; j++) { 
     glBindTexture(GL_TEXTURE_2D, Sprites[j]->Graphics->TextureNum); 
     Sprites[j]->render(level->layers[i]->mapPosition[0], level->layers[i]->mapPosition[1]); 
    } 
    for (int j = 0; j < NumBullets; j++) { 
     glBindTexture(GL_TEXTURE_2D, Bullets[j]->Texture->TextureNum); 
     Bullets[j]->render(level->layers[i]->mapPosition[0], level->layers[i]->mapPosition[1]); 
    } 
    } 

    glBindTexture(GL_TEXTURE_2D, level->tilemap->TextureNum); 

    t = 0 - ((level->layers[i]->mapPosition[0] - (level->layers[i]->mapPosition[0] % 32)) /32) + (((level->layers[i]->mapPosition[1] - (level->layers[i]->mapPosition[1] % 32)) /32) * level->mapDimensions[0]); 
    ai = (float)(3 - i); //Invert Z-Index 
    sX = (float)((level->layers[i]->mapPosition[0] % 32)); 
    sY = (float)((level->layers[i]->mapPosition[1] % 32)); 
    if (sX > 0) 
     sX -= 32; 
    if (sY < 0) 
     sY += 32; 
    fX = sX /= 32.0f; 
    sY /= 32.0f; 
    fXa = sXa = sX + 1.0f; 
    sYa = sY + 14.0f; 
    sYb = sY + 15.0f; 

    for (int y = 0; y < 16; y++) { 
    for (int x = 0; x < 21; x++) { 
     p = level->tiles[level->layers[i]->map[t]]->position; 
     tX = p[0]/level->dTex; 
     tY = p[1]/level->dTex; 
     tXa = tX + dT; 
     tYa = tY + dT; 
     glTexCoord2f(tX, tYa);  glVertex3f(fX, sYa, ai); // Bottom Left Of The Texture and Quad 
     glTexCoord2f(tXa,tYa);  glVertex3f(fXa, sYa, ai); // Bottom Right Of The Texture and Quad 
     glTexCoord2f(tXa,tY);  glVertex3f(fXa, sYb, ai); // Top Right Of The Texture and Quad 
      glTexCoord2f(tX, tY);  glVertex3f(fX, sYb, ai);  // Top Left Of The Texture and Quad 
      fX += 1.0f; 
      fXa += 1.0f; 
      t++; 
      if (t >= m) break; 
     } 
     sYb -= 1.0f; sYa -= 1.0f; 
     fXa = sXa; fX = sX; 
     t += level->mapDimensions[0] - 21; //21 is the number of tiles drawn on a line (20 visible + 1 extra for scrolling) 
     } 

    } 
    glEnd(); 
    } 

SDL_GL_SwapBuffers(); 
} 

下面是設置tilemap的數據精靈的代碼段和水平:

等級:

void loadLevel(dshlib::utfstr FileName) { 
-snip- 
    texCacheItem * Tex = loadGraphics(FileName); 

    if (!Tex) { //Load the tile graphics for the level 
    unloadLevel(); 
    EngineState = ENGINESTATE_ERR; 
    return; 
    } else { 
    level->dTex = Tex->TextureInfo->Width; 
    level->tilemap = Tex; 
    } 
-snip- 
} 

雪碧:

void SpriteBase::created() { 
    this->Graphics = loadGraphics(DefaultGFX()); 
-snip- 
} 

更新2:

Sid Farkus n oted一個大錯誤,我與渲染製作,所以這裏是一個更新的renderer.cpp:

#include "../MegaJul.h" 
void render(void) { 

    //Render the current tilemap to the screen 

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 
    glTranslatef(0.0f, 0.0f, -4.0f); 

    if (level) { 

    float dT = 32.0f/level->dTex; 
    float sX, fX, fXa, sY, tX, tY, sYa, sYb, sXa, tXa, tYa; 
    unsigned long m = level->mapDimensions[0] * level->mapDimensions[1]; 
    float ai; long long t; Sint16 * p; 

    for (int i = 3; i >= 0; i--) { 

     if (level->layers[i]->mapPosition[0] > 0) 
     level->layers[i]->mapPosition[0] = 0; 
     if (level->layers[i]->mapPosition[0] < 0 - (signed long)((level->mapDimensions[0] - 21) * 32)) 
     level->layers[i]->mapPosition[0] = 0 - (signed long)((level->mapDimensions[0] - 21) * 32); 

     if (level->layers[i]->mapPosition[1] < 0)  
     level->layers[i]->mapPosition[1] = 0; 
     if (level->layers[i]->mapPosition[1] > (signed long)((level->mapDimensions[1] - 16) * 32)) 
     level->layers[i]->mapPosition[1] = (signed long)((level->mapDimensions[1] - 16) * 32); 

     if (i == level->activeMap) { 
     for (int j = 0; j < NumSprites; j++) { 
      glBindTexture(GL_TEXTURE_2D, Sprites[j]->Graphics->TextureNum); 
      glBegin(GL_QUADS); 
      Sprites[j]->render(level->layers[i]->mapPosition[0], level->layers[i]->mapPosition[1]); 
      glEnd(); 
     } 
     for (int j = 0; j < NumBullets; j++) { 
      glBindTexture(GL_TEXTURE_2D, Bullets[j]->Texture->TextureNum); 
      glBegin(GL_QUADS); 
      Bullets[j]->render(level->layers[i]->mapPosition[0], level->layers[i]->mapPosition[1]); 
      glEnd(); 
     } 
     } 

     glBindTexture(GL_TEXTURE_2D, level->tilemap->TextureNum); 
     glBegin(GL_QUADS); 

    -snipped out renderer since it was bloat 

    glEnd(); 
    } 

    SDL_GL_SwapBuffers(); 
} 
+1

你的代碼看起來不錯,你確認你的PNG加載程序工作正常嗎?創建一個4x4紋理並檢查值以確保你已經從加載器中獲得正確的東西,並且字節順序與您傳遞給glTexImage2D的字節順序相匹配。除非我專注於您的渲染代碼。 –

+0

順便說一句,怪異的命名約定,以大寫字母開始變量名稱。當我第一次看到你的代碼時,我困惑了10秒。 (不要說這是錯誤的,只是奇怪) – sbk

回答

2

在您的渲染,你適當地調用glBindTexture?這聽起來像你的渲染器只是使用你上傳的最後一個紋理,因爲這是你最後一次調用glBindTexture。 glBindTexture是告訴OpenGL紋理用於你的多邊形。

+0

不,我確保我總是在渲染器中調用glBindTexture()。如果我發佈相關部分以供參考,它會有幫助嗎? – Sukasa

+0

是的,當然,因爲加載代碼中沒有明顯的錯誤。 (當然假設你實際上加載了不同的紋理:)) –

+0

在你調用bind之前打印出TextureNum,確保你至少設置了一個不同的opengl紋理。此外,請嘗試使用GLintercept來查看是否可以使用它來識別任何內容。 (我一直用這個來查找我的opengl問題。) –

0

我假設你不能做任何形式的調試或日誌記錄?如果可以的話,我預計這將是微不足道的診斷。

對我來說看起來很危險的主要事情是你沒有檢查loadPNG的返回值。作爲我做的第一件事,我會在那裏放些東西。

我會考慮評論一下已經緩存的紋理的初始檢查。如果事情在那個時候開始工作,你就知道這是資源名稱或文件名(或它們的比較)的問題。另外,我很驚訝你正在使用類和智能指針,但用裸指針和數組來滾動你自己的std :: vector。;)

+0

我已經完成了調試 - 而且我沒有運氣,這就是我在這裏問的原因。 就intermix而言,好吧,我相信我會盡快讓它變得有意義。 – Sukasa

3

隨着你的渲染代碼,我可以看到你在glBegin/End塊中調用BindTexture。從OpenGL的文檔:如果 之間執行 glBindTexture在glBegin的執行和glEnd的相應的執行產生

GL_INVALID_OPERATION。

將您的BindTexture調用移動到glBegin()/ glEnd()塊之外,您應該是金手指。你可能必須有多個塊來適應你的渲染風格。

編輯:

隨着更新的代碼,確保一些事情;您的精靈位置在當前的投影/模型視圖矩陣的屏幕上可見,而您的精靈紋理ID是有效的紋理。現在沒有任何技術上的錯誤會跳到我身上,但是你的價值觀可能會被忽略。

+0

嗯,現在我得到了同樣的問題,而是使用* other *紋理...在新版本中複製,知道我完全把它弄暈了... – Sukasa

+0

確保在render()中調用你不要做任何奇怪的事情。請記住,您可以在glBegin和glEnd之間調用的函數的有限子集。 –

+0

精靈渲染所做的唯一事情是計算一些偏移量,然後調用glTexCoord2f和glVertex3f。 – Sukasa