【问题标题】:OpenGL - How can I make this program work for textures larger than 1x1?OpenGL - 如何使该程序适用于大于 1x1 的纹理?
【发布时间】:2018-04-17 11:40:18
【问题描述】:

我正在编写一个概念验证程序来更熟悉纹理,但它的行为很奇怪,因为它适用于 1x1 纹理,但不适用于所有其他纹理。我多次扫描程序并查看了每个函数的参数,但不明白为什么它适用于 1x1 纹理(或较大纹理中的第一个像素),但在其他情况下显示为白色方块。

这是使用 glTexImage2D 的宽度和高度参数 (1, 1) 和 (2,2) 分别运行的同一程序的图片。

这是显示白色方块的代码(而预期会绘制 2x2 红色、绿色、蓝色、黄色行的主要纹理)。

注意:in(Comment, Arg) 宏等同于 Arg,它只在这个特定程序中使用,因为记住 glTexImage2D 的参数很棘手。

#include <GL/glut.h>

// | reminder decorator macro.
#define in(Comment, Arg) Arg

GLubyte bm[16] = {
    0xff, 0x00, 0x00, 0xff,
    0x00, 0xff, 0x00, 0xff,
    0x00, 0x00, 0xff, 0xff,
    0xff, 0xff, 0x00, 0xff
};

GLuint tex;

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);           

    glBindTexture(GL_TEXTURE_2D, tex);

    glLoadIdentity();

    // | make the square smaller to contrast our target from the background.
    glScalef(.5f, .5f, 1.f);

    glBegin(GL_TRIANGLE_FAN);
        glTexCoord2f(0.f, 0.f);
        glVertex2f(-1.f, 1.f);
        glTexCoord2f(0.f, 1.f);
        glVertex2f(1.f, 1.f);
        glTexCoord2f(1.f, 1.f);
        glVertex2f(1.f, -1.f);
        glTexCoord2f(1.f, 0.f);
        glVertex2f(-1.f, -1.f);
    glEnd();

    glFlush();
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);
    glutCreateWindow("");

    glEnable(GL_TEXTURE_2D);        
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D (
        in(target, GL_TEXTURE_2D), 
        in(level, 0), 
        in(internalFormat, GL_RGBA), 
        in(width, 2), 
        in(height, 2), 
        in(border, 0), 
        in(format, GL_RGBA), 
        in(type, GL_UNSIGNED_BYTE), 
        in(data, bm)
    );
    glTexParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glutDisplayFunc(display);
    glutMainLoop();

    return 0;
}

如果我将in(width, 2) 更改为in(width, 1) 并将in(height, 2) 更改为in(height, 1),它会显示一个红色方块,并更改bm 数组的前三个值,它会按预期将此颜色映射到立方体。

#include <GL/glut.h>

// | reminder decorator macro.
#define in(Comment, Arg) Arg

GLubyte bm[16] = {
    0xff, 0x00, 0x00, 0xff,
    0x00, 0xff, 0x00, 0xff,
    0x00, 0x00, 0xff, 0xff,
    0xff, 0xff, 0x00, 0xff
};

GLuint tex;

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);           

    glBindTexture(GL_TEXTURE_2D, tex);

    glLoadIdentity();

    // | make the square smaller to contrast our target from the background.
    glScalef(.5f, .5f, 1.f);

    glBegin(GL_TRIANGLE_FAN);
        glTexCoord2f(0.f, 0.f);
        glVertex2f(-1.f, 1.f);
        glTexCoord2f(0.f, 1.f);
        glVertex2f(1.f, 1.f);
        glTexCoord2f(1.f, 1.f);
        glVertex2f(1.f, -1.f);
        glTexCoord2f(1.f, 0.f);
        glVertex2f(-1.f, -1.f);
    glEnd();

    glFlush();
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);
    glutCreateWindow("");

    glEnable(GL_TEXTURE_2D);        
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D (
        in(target, GL_TEXTURE_2D), 
        in(level, 0), 
        in(internalFormat, GL_RGBA), 
        in(width, 1), 
        in(height, 1), 
        in(border, 0), 
        in(format, GL_RGBA), 
        in(type, GL_UNSIGNED_BYTE), 
        in(data, bm)
    );
    glTexParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glutDisplayFunc(display);
    glutMainLoop();

    return 0;
}

有人可以解释发生了什么以及如何解决这个问题吗?

解决方案:将 tex 传递给 glTexParameteri 而不是 GL_TEXTURE_2D(旁注:以及 glVertex2f 中的 1.1 到 1.f 的错字)

#include <GL/glut.h>

// | reminder decorator macro.
#define in(Comment, Arg) Arg

GLubyte bm[16] = {
    0xff, 0x00, 0x00, 0xff,
    0x00, 0xff, 0x00, 0xff,
    0x00, 0x00, 0xff, 0xff,
    0xff, 0xff, 0x00, 0xff
};

GLuint tex;

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);           

    glBindTexture(GL_TEXTURE_2D, tex);

    glLoadIdentity();

    // | make the square smaller to contrast our target from the background.
    glScalef(.5f, .5f, 1.f);

    glBegin(GL_TRIANGLE_FAN);
        glTexCoord2f(0.f, 0.f);
        glVertex2f(-1.f, 1.f);
        glTexCoord2f(1.f, 0.f);
        glVertex2f(1.f, 1.f);
        glTexCoord2f(1.f, 1.f);
        glVertex2f(1.f, -1.f);
        glTexCoord2f(0.f, 1.f);
        glVertex2f(-1.f, -1.f);
    glEnd();

    glFlush();
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);
    glutCreateWindow("");

    glEnable(GL_TEXTURE_2D);        
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D (
        in(target, GL_TEXTURE_2D), 
        in(level, 0), 
        in(internalFormat, GL_RGBA), 
        in(width, 2), 
        in(height, 2), 
        in(border, 0), 
        in(format, GL_RGBA), 
        in(type, GL_UNSIGNED_BYTE), 
        in(data, bm)
    );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glutDisplayFunc(display);
    glutMainLoop();

    return 0;
}

【问题讨论】:

    标签: c opengl textures texture-mapping texture2d


    【解决方案1】:

    当您指定 2x2 纹理时,您的纹理不是 mipmap-complete,但您使用了 mip-mapping 缩小过滤器。根据规范,您得到的结果是正确的结果。

    您的错误在于您尝试设置非 mipmapping GL_NEAREST 过滤器:

    glTexParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    

    glTexParameter 需要纹理绑定点,即GL_TEXTURE_2D,而不是纹理名称。结果这个调用会产生GL_INVALID_ENUM错误,没有其他作用。

    【讨论】:

    • 设置 GL_TEXTURE_MIN_FILTER 的正确属性是什么?此外,在这种情况下,我应该担心的是 GL_TEXTURE_MAG_FILTER,因为它被放大而不是最小化吗?
    • 这不是要设置的值,是第一个参数target是错误的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多