OpenGL,渲染纹理上的异常伪影,渲染坐标? [关闭]

Posted

技术标签:

【中文标题】OpenGL,渲染纹理上的异常伪影,渲染坐标? [关闭]【英文标题】:OpenGL, unusual artifacts on rendered texture, render co-ordinates? [closed] 【发布时间】:2019-05-24 20:52:35 【问题描述】:

我正在尝试渲染一个简单的四边形以完美覆盖屏幕(一对一复制)。我用来渲染的纹理是从使用帧缓冲区和glGetTexImage 的先前渲染中捕获的。这部分我很好。但是,当我再次加载并显示纹理时,我在渲染中(左上角)得到了一些奇怪的伪影,到目前为止我一直无法摆脱它们。

为了比较,这是它目前的样子:

它应该是这样的:

这可能是由于纹理坐标、屏幕坐标造成的,但到目前为止我所尝试的一切都失败了。我应该改变/做些什么?

渲染代码如下。

void setWidthHeightRender(GLsizei width, GLsizei height) 
    if(height == 0)
        height = 1;

    glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar
    glOrtho(0.0, width, height, 0.0, -1.0, 1.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

unsigned createGLTexture(unsigned width, unsigned height, const uint8_t* data) 
    // the texture we're going to render
    GLuint renderedTexture;
    glGenTextures(1, &renderedTexture);

    // bind the newly created texture
    glBindTexture(GL_TEXTURE_2D, renderedTexture);

    // give the image to opengl
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glBindTexture(GL_TEXTURE_2D, 0);
    return renderedTexture;

void drawImage(unsigned glTxt, float tx, float ty, float bx, float by, float z) 
    //glEnable(GL_BLEND);
    //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, glTxt);

    glBegin(GL_TRIANGLE_FAN);
        glTexCoord2f(0, 1);
        glVertex3f(tx, ty, z);

        glTexCoord2f(0, 0);
        glVertex3f(tx, by, z);

        glTexCoord2f(1, 0);
        glVertex3f(bx, by, z);

        glTexCoord2f(1, 1);
        glVertex3f(bx, ty, z);
    glEnd();

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);


    //...
    wglMakeCurrent(it->second->hDC, it->second->hRC);

    //create the texture + load the texture
    unsigned glTxt = createGLTexture((right - left), (bottom - top), &bfr[0]);

    //render the texture to the correct screen positions
    setWidthHeightRender((right - left), (bottom - top));

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    drawImage(glTxt, 0.0, 0.0, (right - left), (bottom - top), 0.0f);

    //swap the buffers
    SwapBuffers(it->second->hDC);

    //unload the texture
    glDeleteTextures(1, &glTxt);
    //...

【问题讨论】:

一个可能的原因可能是纹理图像的行必须对齐到 4。可能是您为完整图像分配/读取/存储的数据太少。 (请注意,OpenGL 纹理使用从上到下的图像。因此,伪影出现在顶部是有道理的。)但是,这些伪影也可能是由任何其他越界访问引起的。 【参考方案1】:

我找到了答案,原来是我从窗户获得的窗户宽度和高度有问题。

我使用宽度和高度来设置窗口大小,我也使用glTexImage2D 来获取纹理。

SetWindowPos(glWindow->hWnd, 0,
             0, 0, glWindow->width, glWindow->height,
             SWP_NOMOVE | SWP_NOZORDER);

然而,这设置了窗口大小,我需要设置的是客户区大小,因为这是通过调用glTexImage2D 收到的。要设置客户区大小,您应该改用:

RECT Rect;
Rect.left =     (long)glWindow->x_pos;                  // Set Left Value To x_pos
Rect.right =    (long)glWindow->x_pos+glWindow->width;      // Set Right Value To x_pos+width
Rect.top =      (long)glWindow->y_pos;                  // Set Top Value To y_pos
Rect.bottom =   (long)glWindow->y_pos+glWindow->height;     // Set Bottom Value To y_pos+height

AdjustWindowRectEx(&Rect, glWindow->dwStyle, FALSE, glWindow->dwExStyle);
SetWindowPos(glWindow->hWnd, 0,
             0, 0, Rect.right-Rect.left, Rect.bottom-Rect.top,
             SWP_NOMOVE | SWP_NOZORDER);

    //...
    //bind the texture for modification
    glBindTexture(GL_TEXTURE_2D, glWindow->renderedTexture);

    //Now correct width and height used here (and else where) matching client area.
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, glWindow->width, glWindow->height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    //...

【讨论】:

以上是关于OpenGL,渲染纹理上的异常伪影,渲染坐标? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

opengl 多个对象,纹理和非纹理,伪影

OpenGL:纹理坐标实时变化的地形的最佳渲染方法?

在 OpenGL 中将深度渲染到纹理时出现奇怪的结果

无法使用 OpenGL 渲染 FBX 导入的纹理模型

OpenGL ES 顶点数组对象和奇怪的伪影

我的OpenGL学习进阶之旅关于OpenGL ES 绘制纹理,因为加载纹理坐标设置错误,导致纹理无法渲染的问题