Search code examples
c++opengltexturesrender-to-textureopengl-compat

OpenGL, unusual artifacts on rendered texture, render co-ordinates?


I am trying to render a simple quad to perfectly cover the screen (one to one replication). The texture I am using to render was captured from a previous render using a framebuffer and glGetTexImage. This part I'm fine with. However when I load and display the texture again I get some odd artifacts in the render (top left corner) and so far I have been unable to get rid of them.

For comparison this is what it currently looks like:

enter image description here

And this is what it should look like:

enter image description here

This maybe due to texture co-ordinates, screen co-ordinates but everything I have so far tried has failed. What should I change/do differently?

Rendering code follows.

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);
    //...

Solution

  • I found the answer, it turned out to be a problem with my window width and height that I was getting from windows.

    I was setting the window size using the width and height that I was also using to get the texture using glTexImage2D.

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

    However this sets the window size, what I needed to set was the client area size as this is what is received with a call to glTexImage2D. To set the client area size you should instead use:

    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);
        //...