当前位置: 首页 > 知识库问答 >
问题:

OpenGL-如何让这个程序适用于大于1x1的纹理?

从烈
2023-03-14

我正在编写一个概念验证程序来更熟悉纹理,但它的行为很奇怪,因为它对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;
}

如果我将(width,2)中的< code >更改为(width,1)中的< code >,将(height,2)中的< code >更改为(height,1)中的< code >,它会显示一个红色方块,并且更改< code>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;
}

共有1个答案

柯昆
2023-03-14

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

您的错误在于试图设置非mipmappingGL_NEAREST过滤器:

glTexParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexParameter期望纹理绑定点,它将是GL_texture_2D,而不是纹理名称。因此,此调用将生成GL_INVALID_ENUM错误,并且没有其他影响。

 类似资料:
  • 因此,我正在构建这个游戏和一个地图编辑器/sdk类型的协议。在我运行w7的台式电脑和我的朋友运行w10的笔记本电脑上,一切都工作得非常好。我可以添加对象并四处移动它们(每个对象都有一个自动更新属性窗口),一切都很好。 我目前正在旅行,所以我决定将项目复制到我的macbook上。UI上的一切都仍然有效,除了停止渲染的东西。我知道对象存在于应用程序中,因为我可以单击它们所在的位置,属性更新就像在我的桌

  • 我需要在着色器中使用两个纹理,一个在顶点着色器中,另一个在片段着色器中。在这两种情况下,它们都在着色器中引用,例如

  • 你能帮忙找出哪一部分错了吗,多谢。:)

  • 当我在Android手机上调试应用程序时,我绝对没有遇到任何错误,但在AVD上,我一开始就得到了一个NullPointerException()。我的Android设备在22 API的Lollipop(5.1.1)上运行,我的AVD在28 API的Pie(9.0)上运行。我在gradle中将最小SDK设置为21,编译SDK设置为28。 这是错误: E/AndroidRuntime:致命异常:主进程

  • 我创建了一个OpenGL(GL_TEXTURE_2D)纹理,使用clCreateFromGLTexture()制作了一个OpenCLimage2d_t缓冲区,我运行我的OpenCL内核来绘制纹理,使用clEnqueueAcquireGLObject和clEnqueueReleaseGLObject之前和之后,然后我通过这样做在OpenGL中显示结果(我试图简单地将我的帧缓冲区纹理绘制到没有缩放的窗

  • 我试图在OpenGL中制作一个场景,从太空模拟地球。我现在有两个球体,一个用于地球,另一个稍大一些用于云层。地球和云球体对象都有自己的着色器程序来保持简单。地球着色器程序采用4种纹理(白天、夜晚、specmap和normalmap),而云着色器程序采用2种纹理(cloudmap和normalmap)。我有一个对象类,它有一个渲染函数,在该函数中我使用以下逻辑: 它从第0个纹理单元开始,从GL_TE