OpenGL渲染纹理全白

6

我试图将一个 .png 图像作为纹理渲染,但是渲染出来的只有一个白色正方形。

我给我的纹理一个独特的整数 ID 叫做 texID,将像素数据读入缓冲区 'image'(在 .h 文件中声明)。我加载了像素缓冲区,进行了所有的 OpenGL 操作,并将该像素缓冲区绑定到 OpenGL 的纹理上。然后使用 glDrawElements 进行绘制。

此外,当调用构造函数时,我初始化纹理大小为 32x32,因此我怀疑这与二次幂大小问题无关。

有人能否看出我的 OpenGL GL_TEXTURE_2D 设置中是否存在任何错误,导致我得到一个白色正方形。

 #include "Texture.h"




Texture::Texture(int width, int height, string filename)
{

    const char* fnPtr = filename.c_str(); //our image loader accepts a ptr to a char, not a string
    printf(fnPtr);
    w = width; //give our texture a width and height, the reason that we need to pass in the width and height values manually
    h = height;//UPDATE, these MUST be P.O.T.

    unsigned error = lodepng::decode(image,w,h,fnPtr);//lodepng's decode function will load the pixel data into image vector
    //display any errors with the texture
    if(error)
    {
        cout << "\ndecoder error " << error << ": " << lodepng_error_text(error) <<endl;
    }

    for(int i = 0; i<image.size(); i++)
    {
        printf("%i,", image.at(i));

    }

    printf("\nImage size is %i", image.size());

    //image now contains our pixeldata. All ready for OpenGL to do its thing

    //let's get this texture up in the video memory
    texGLInit();
}

void Texture::texGLInit()
{
    //WHERE YOU LEFT OFF: glGenTextures isn't assigning an ID to textures. it stays at zero the whole time
    //i believe this is why it's been rendering white
    glGenTextures(1, &textures);
    printf("\ntexture = %u", textures);
    glBindTexture(GL_TEXTURE_2D, textures);//evrything we're about to do is about this texture
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    //glDisable(GL_COLOR_MATERIAL);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,w,h,0, GL_RGBA, GL_UNSIGNED_BYTE, &image);
    //we COULD free the image vectors memory right about now.


}

void Texture::draw(point centerPoint, point dimensions)
{
    glEnable(GL_TEXTURE_2D);
    printf("\nDrawing block at (%f, %f)",centerPoint.x, centerPoint.y);
    glBindTexture(GL_TEXTURE_2D, textures);//bind the texture
    //create a quick vertex array for the primitive we're going to bind the texture to
    printf("TexID = %u",textures);
    GLfloat vArray[8] = 
    {
        centerPoint.x-(dimensions.x/2), centerPoint.y-(dimensions.y/2),//bottom left i0
        centerPoint.x-(dimensions.x/2), centerPoint.y+(dimensions.y/2),//top left i1
        centerPoint.x+(dimensions.x/2), centerPoint.y+(dimensions.y/2),//top right i2
        centerPoint.x+(dimensions.x/2), centerPoint.y-(dimensions.y/2)//bottom right i3
    };

    //create a quick texture array (we COULD create this on the heap rather than creating/destoying every cycle)
    GLfloat tArray[8] = 
    {
        0.0f,0.0f, //0
        0.0f,1.0f, //1
        1.0f,1.0f, //2
        1.0f,0.0f //3
    };

    //and finally.. the index array...remember, we draw in triangles....(and we'll go CW)
    GLubyte iArray[6] =
    {
        0,1,2,
        0,2,3
    };

    //Activate arrays
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    //Give openGL a pointer to our vArray and tArray
    glVertexPointer(2, GL_FLOAT, 0, &vArray[0]);
    glTexCoordPointer(2, GL_FLOAT, 0, &tArray[0]);

    //Draw it all
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, &iArray[0]);

    //glDrawArrays(GL_TRIANGLES,0,6);

    //Disable the vertex arrays
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_TEXTURE_2D);
    //done!

    /*glBegin(GL_QUADS);
    glTexCoord2f(0.0f,0.0f);
        glVertex2f(centerPoint.x-(dimensions.x/2), centerPoint.y-(dimensions.y/2));
    glTexCoord2f(0.0f,1.0f);
        glVertex2f(centerPoint.x-(dimensions.x/2), centerPoint.y+(dimensions.y/2));
    glTexCoord2f(1.0f,1.0f);
        glVertex2f(centerPoint.x+(dimensions.x/2), centerPoint.y+(dimensions.y/2));
    glTexCoord2f(1.0f,0.0f);
        glVertex2f(centerPoint.x+(dimensions.x/2), centerPoint.y-(dimensions.y/2));
    glEnd();*/
}



Texture::Texture(void)
{
}
Texture::~Texture(void)
{
}

我还将包括主类的初始化,在此之前,我会进行更多的OGL设置。

void init(void)
{
    printf("\n......Hello Guy. \n....\nInitilising");
    glMatrixMode(GL_PROJECTION);    
    glLoadIdentity();
    gluOrtho2D(0,XSize,0,YSize);
    glEnable(GL_TEXTURE_2D);
    myBlock = new Block(0,0,offset);
    glClearColor(0,0.4,0.7,1);


    glLineWidth(2);         // Width of the drawing line
    glMatrixMode(GL_MODELVIEW); 
    glDisable(GL_DEPTH_TEST);
    printf("\nInitialisation Complete");

}

更新:添加了我第一次设置OpenGL窗口的主要函数。
int main(int argc, char** argv) 
{
  glutInit(&argc, argv);    // GLUT Initialization 
  glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE); // Initializing the Display mode
  glutInitWindowSize(800,600);  // Define the window size
  glutCreateWindow("Gem Miners");   // Create the window, with caption.
        printf("\n========== McLeanTech Systems =========\nBecoming Sentient\n...\n...\n....\nKILL\nHUMAN\nRACE \n");
  init();   // All OpenGL initialization


  //-- Callback functions ---------------------
  glutDisplayFunc(display);
  glutKeyboardFunc(mykey);
  glutSpecialFunc(processSpecialKeys);
  glutSpecialUpFunc(processSpecialUpKeys);
  //glutMouseFunc(mymouse);


  glutMainLoop();   // Loop waiting for event 
}

1
使用glGenTextures()让OpenGL为您创建纹理ID,而不是告诉它要使用哪个ID。 - genpfault
@genpfault,然而我的Texture类有多个实例。如果我为生成纹理指定一个数组来放置ID,那么每个实例不是都会不同吗?或者这个数组被OpenGL认为是静态的? - Guy Joel McLean
@GuyJoelMcLean:通常情况下,您希望每个纹理都有一个不同的ID。您应该考虑将绘图函数移出纹理类。 - datenwolf
1个回答

14

每当纹理呈白色时,请按照以下常用清单进行检查:

  • 在尝试加载纹理时,已创建OpenGL上下文并将其绑定到当前线程?

  • 使用glGenTextures分配了纹理ID吗?

  • formatinternal format参数是否是glTex [Sub] Image…函数允许的有效OpenGL标记?

  • 是否使用了Mipmapping?

    • 是:提供所有Mipmap层 - 最好设置glTexParameteri GL_TEXTURE_BASE_LEVEL和GL_TEXTURE_MAX_LEVEL以及GL_TEXTURE_MIN_LOD和GL_TEXTURE_MAX_LOG。

    • 否:通过将glTexParameteri GL_TEXTURE_MIN_FILTER设置为GL_NEAREST或GL_LINEAR关闭Mipmap过滤。


@GuyJoelMcLean:纹理的外观应该反映出你所看到的胡言乱语。因此,它不应该是全白的。 - datenwolf
你是对的,当我将向量强制转换为整数并使用printf打印时,它们以完美的RGBA格式打印出来。然而,通过实验,我发现可以使用glColor4f()来给白色块着色 :) 通常可以在纹理中这样做吗? - Guy Joel McLean
是的,它们被实例化为静态全局变量!这很有道理,我会尝试一下。 - Guy Joel McLean
8
我终于解决了它。对于任何在未来浏览此页面且遇到类似问题的人,问题就像 @datenwolf 所说的那样。我在另一个类中全局实例化了我的 Texture 实例。我不得不将其移动到代码中的某个位置,在这里它们将在 OpenGL 创建上下文之后创建。此外,在修复这个问题之后,我的纹理模糊了(即像是乱七八糟的像素),并时而导致运行时访问违规。这是因为在 glTexImage2D 中,对于我的像素数据,我只是传递了一个对它所创建的数组的引用。而不是对数组第一部分的引用...。 - Guy Joel McLean
2
我之前传递的是 &image,但是传递 &image[0] 解决了问题。 虽然我还没有完全搞定 alpha 位的问题,但总体来说我非常开心。感谢大家的时间和帮助。 - Guy Joel McLean
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接