2009-10-26 73 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