OpenGL 与 C++ - 纹理

Posted

技术标签:

【中文标题】OpenGL 与 C++ - 纹理【英文标题】:OpenGl with C++ - Textures 【发布时间】:2015-06-14 22:37:00 【问题描述】:

我正在尝试将 OpenGL 中的一些纹理映射到立方体的表面。但是,当我运行我的程序时,我的纹理没有出现。所以我有这段代码:

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,texture[1]);

        glPushMatrix();

        glBegin(GL_QUADS);                                  // Begin drawing the color cube with 6 quads
                                                            // Top face (y = 1.0f)
                                                            // Define vertices in counter-clockwise (CCW) order with normal pointing out
        //glColor3f(0.0f, 1.0f, 0.0f);     // Green
        glVertex3f( 1.0f+i*2, -2.0f+y*2, -1.0f+j*2);
        glVertex3f(-1.0f+i*2, -2.0f+y*2, -1.0f+j*2);
        glVertex3f(-1.0f+i*2, -2.0f+y*2,  1.0f+j*2);
        glVertex3f( 1.0f+i*2, -2.0f+y*2,  1.0f+j*2);

                                                            // Bottom face (y = -1.0f)
        //glColor3f(1.0f, 0.5f, 0.0f);     // Orange
        glVertex3f( 1.0f+i*2, -4.0f+y*2,  1.0f+j*2);
        glVertex3f(-1.0f+i*2, -4.0f+y*2,  1.0f+j*2);
        glVertex3f(-1.0f+i*2, -4.0f+y*2, -1.0f+j*2);
        glVertex3f( 1.0f+i*2, -4.0f+y*2, -1.0f+j*2);

                                                            // Front face  (z = 1.0f)
        //glColor3f(1.0f, 0.0f, 0.0f);     // Red
        glTexCoord2f(0.0f,0.0f);  glVertex3f( 1.0f+i*2,  -2.0f+y*2, 1.0f+j*2);
        glTexCoord2f(10.0f,0.0f); glVertex3f(-1.0f+i*2,  -2.0f+y*2, 1.0f+j*2);
        glTexCoord2f(10.0f,10.0f); glVertex3f(-1.0f+i*2, -4.0f+y*2, 1.0f+j*2);
        glTexCoord2f(0.0f,10.0f); glVertex3f( 1.0f+i*2, -4.0f+y*2, 1.0f+j*2);

                                                            // Back face (z = -1.0f)
        //glColor3f(1.0f, 1.0f, 0.0f);     // Yellow
        glVertex3f( 1.0f+i*2, -4.0f+y*2, -1.0f+j*2);
        glVertex3f(-1.0f+i*2, -4.0f+y*2, -1.0f+j*2);
        glVertex3f(-1.0f+i*2,  -2.0f+y*2, -1.0f+j*2);
        glVertex3f( 1.0f+i*2,  -2.0f+y*2, -1.0f+j*2);

                                                            // Left face (x = -1.0f)
        //glColor3f(0.0f, 0.0f, 1.0f);     // Blue
        glVertex3f(-1.0f+i*2,  -2.0f+y*2,  1.0f+j*2);
        glVertex3f(-1.0f+i*2,  -2.0f+y*2, -1.0f+j*2);
        glVertex3f(-1.0f+i*2, -4.0f+y*2, -1.0f+j*2);
        glVertex3f(-1.0f+i*2, -4.0f+y*2,  1.0f+j*2);

                                                            // Right face (x = 1.0f)
        //glColor3f(1.0f, 0.0f, 1.0f);     // Magenta
        glVertex3f(1.0f+i*2,  -2.0f+y*2, -1.0f+j*2);
        glVertex3f(1.0f+i*2,  -2.0f+y*2,  1.0f+j*2);
        glVertex3f(1.0f+i*2, -4.0f+y*2,  1.0f+j*2);
        glVertex3f(1.0f+i*2, -4.0f+y*2, -1.0f+j*2);
        glEnd();                                            // End of drawing color-cube

        glPopMatrix();

        glDisable(GL_TEXTURE_2D);

我的初始化函数是这样的:

void initGL() 
     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);                       // Set background color to black and opaque
     glShadeModel(GL_SMOOTH);                                    // Enable smooth shading
     cria_texturas();
glEnable(GL_TEXTURE_2D);
     //glClearDepth(1.0f);                                         // Set background depth to farthest
     glEnable(GL_DEPTH_TEST);                                    // Enable depth testing for z-culling
     //glDepthFunc(GL_LEQUAL);                                     // Set the type of depth-test
     //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);          // Nice perspective corrections

为了加载纹理,我编写了这段代码,它使用了一个加载图像的预制类:

glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
imag.LoadBmpFile("chao.bmp");
glTexImage2D(GL_TEXTURE_2D, 0, 3,
             imag.GetNumCols(),
             imag.GetNumRows(), 0, GL_RGB, GL_UNSIGNED_BYTE,
             imag.ImageData());

所以我不明白为什么纹理没有出现在立方体的表面。你能帮帮我吗?

【问题讨论】:

您正在为texture[0] 生成一个纹理,然后您正在使用texture[1]。您应该在glBindTexture 中使用texture[0]。另外,您应该在cria_texturas() 之前调用glEnable( GL_TEXTURE_2D) 【参考方案1】:

当使用即时模式(glBegin,glEnd)时,glVertex 的调用正在完成一个顶点的构建。本质上,glVertex 所做的是合并已放置在其他属性“寄存器”中的属性并将其发送到缓冲区中。

在您的代码中,您有以下内容:

    glTexCoord2f(0.0f,0.0f);  glVertex3f( 1.0f+i*2,  -2.0f+y*2, 1.0f+j*2);
    glTexCoord2f(10.0f,0.0f); glVertex3f(-1.0f+i*2,  -2.0f+y*2, 1.0f+j*2);
    glTexCoord2f(10.0f,10.0f); glVertex3f(-1.0f+i*2, -4.0f+y*2, 1.0f+j*2);
    glTexCoord2f(0.0f,10.0f); glVertex3f( 1.0f+i*2, -4.0f+y*2, 1.0f+j*2);

                                                        // Back face (z = -1.0f)

    glVertex3f( 1.0f+i*2, -4.0f+y*2, -1.0f+j*2);

只有这些 glTexCoord 调用中的最后一个实际上有效果,其他的只会设置寄存器,但该值会立即被以下调用覆盖。

立即模式的使用方法是

foreach vertex in model:
    glColor
    glNormal
    glTexCoord
    ...
    glVertex // must be the last call for specifying a vertex!

您不能对 glColor、glNormal 和其他调用进行分组。 但是你无论如何都不应该使用立即模式!自 1996 年 OpenGL-1.1 引入 顶点数组 以来,它已被弃用。你真的坚持使用已经过时近 20 年的技术吗?

【讨论】:

每个 glTexCoord2f 后面跟着一个 glVertex3f 调用,在同一行中。 @aslg:是的,但仅在某些行中。在其他情况下,您根本不会触及纹理坐标。 OP 正在尝试仅在正面渲染纹理。您不必为所有顶点定义 tex 坐标,但其他面会显示为黑色,因为它们没有 tex 坐标。 @aslg:问题是,glVertex 只会使用最后设置的 glTexCoord。 glTexCoord 和朋友没有锁定,即调用 glVertex 不会将其他属性“重置”为未设置状态。如果您不想对相关面部进行纹理处理,则必须启动一个禁用纹理的新图元。 啊,我明白了。好吧,我同意无论如何最好为所有顶点设置纹理坐标,即使你只想要一张脸。但我不知道最后设置的坐标仍然会被使用。 (我测试了这段代码,没有定义tex坐标的面孔是黑色的,所以这可能是因为我的图像大部分是黑色的,最后一个tex坐标是黑色的texel?)我没有投反对票,但我现在要投赞成票。

以上是关于OpenGL 与 C++ - 纹理的主要内容,如果未能解决你的问题,请参考以下文章

使用 DevIL 在 C++ OpenGL 中加载纹理

如何在 C++ 中将位图绘制为 OpenGL 纹理?

C++ OpenGL/SDL 2.0 无法加载纹理

纹理未正确显示 - 可能坐标是错误的 OpenGL、C++

将 GLubyte* 转换为 GLuint* 用于 alpha 纹理 Opengl 3.0 / c++ / Win32

使用 OpenGL 和 QT 进行纹理映射 - C++