在OpenGL中Map纹理

9avjhtql  于 2022-11-04  发布在  其他
关注(0)|答案(2)|浏览(254)

我第一次尝试将一个纹理Map到一个简单的四边形,但是它并不能完全渲染。我使用freeglut来实现,并使用stb_image. h头文件来加载纹理。代码:


# include <GL/glut.h>

# include <stb_image.h>

# include <iostream>

int ww = 500, wh = 500;

void display()
{
    glClearColor(1.0, 1.0, 0.7, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_QUADS);
    glEnable(GL_TEXTURE_2D);
    glTexCoord2f(0.0, 0.0); glVertex3f(10,10,0);
    glTexCoord2f(0.0, 1.0); glVertex3f(10,wh-10,0);
    glTexCoord2f(1.0, 1.0); glVertex3f(ww-10,wh,0);
    glTexCoord2f(1.0, 0.0); glVertex3f(ww-10,10,0);
    glDisable(GL_TEXTURE_2D);
    glEnd();
    glFlush();
}

void myinit()
{   
    glViewport(0, 0, ww, wh);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, (GLdouble)ww, 0.0, (GLdouble)wh);
    glMatrixMode(GL_MODELVIEW);

    unsigned int texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    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_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    int width, height, nrChannels;
    unsigned char* data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
    if (data)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data);
}
int main(int argc, char**argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
    glutInitWindowSize(ww, wh);
    glutCreateWindow("texture-try");
    glutDisplayFunc(display);
    myinit();
    glutMainLoop();
    return 0;
}

它成功地加载了纹理,但四元图看起来只是白色的。我错过了什么?

编辑:

我按照建议在glEnable(GL_TEXTURE_2D);glDisable(GL_TEXTURE_2D);命令中移动了glBegin(GL_QUADS);glEnd();,但它仍然无法渲染纹理。
我还检查了glGetError命令,但它返回GL_NO_ERROR

wj8zmpe1

wj8zmpe11#

几件事:

  • 前面提到的“不要在glBegin()/glEnd()对中使用被禁止的功能”问题;在发布时,问题代码中还没有修复这个问题。
  • 正在使用GL_LINEAR_MIPMAP_LINEAR,但未提供任何mipmap。请降到GL_LINEAR或提供一些mipmap。
  • 3传递给stbi_load()desired_channels参数(而不是当前的0),以确保获得3通道图像数据,而不是假设nrChannels是所有输入图像的3
  • 使用GL_RGB和默认的GL_UNPACK_ALIGNMENT4)可能会导致显示不稳定,如果你的图像宽度不是4的整数倍,那么在调用glTexImage2D()之前,通过glPixelStorei(GL_UNPACK_ALIGNMENT, 1)将其下拉到1
  • 请切换到GLUT_DOUBLEglutSwapBuffers(),而不要使用GLUT_SINGLEglFlush()

所有人一起:


# include <GL/glut.h>

# define STB_IMAGE_IMPLEMENTATION

# include <stb_image.h>

# include <iostream>

int ww = 500, wh = 500;

void display()
{
    glClearColor(1.0, 1.0, 0.7, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0); glVertex3f(10,10,0);
    glTexCoord2f(0.0, 1.0); glVertex3f(10,wh-10,0);
    glTexCoord2f(1.0, 1.0); glVertex3f(ww-10,wh,0);
    glTexCoord2f(1.0, 0.0); glVertex3f(ww-10,10,0);
    glEnd();
    glDisable(GL_TEXTURE_2D);
    glutSwapBuffers();
}

void myinit()
{   
    glViewport(0, 0, ww, wh);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, (GLdouble)ww, 0.0, (GLdouble)wh);
    glMatrixMode(GL_MODELVIEW);

    unsigned int texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    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_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    int width, height, nrChannels;
    // https://commons.wikimedia.org/wiki/File:Container.JPG
    unsigned char* data = stbi_load("container.jpg", &width, &height, &nrChannels, 3);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    if (data)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data);
}
int main(int argc, char**argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(ww, wh);
    glutCreateWindow("texture-try");
    glutDisplayFunc(display);
    myinit();
    glutMainLoop();
    return 0;
}

aelbi1ox

aelbi1ox2#

从glBegin的OpenGL文档:
在glBegin和glEnd之间只能使用GL命令的子集。这些命令包括glVertex、glColor、glSecondaryColor、glIndex、glNormal、glFogCoord、glTexCoord、glMultiTexCoord、glVertexAttrib、glEvalCoord、glEvalPoint、glArrayElement、glMaterial和glEdgeFlag。此外,可以使用glCallList或glCallLists来执行仅包含上述命令的显示列表。如果在glBegin和glEnd之间执行任何其他GL命令,则会设置错误标志并忽略该命令。
换句话说,您不能在glBegin/glEnd块中启用/禁用纹理。

void display()
{
    glClearColor(1.0, 1.0, 0.7, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    // move to before glBegin
    glEnable(GL_TEXTURE_2D);

    glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0); glVertex3f(10,10,0);
    glTexCoord2f(0.0, 1.0); glVertex3f(10,wh-10,0);
    glTexCoord2f(1.0, 1.0); glVertex3f(ww-10,wh,0);
    glTexCoord2f(1.0, 0.0); glVertex3f(ww-10,10,0);
    glEnd();

    // move to after glEnd
    glDisable(GL_TEXTURE_2D);

    glFlush();
}

相关问题