Search code examples
c++openglrenderingtextures

OpenGL - Textured quad cropped and weirdly stretched


I'm currently creating some pixeldata on my computer and sending it into a texture in OpenGL. The exported buffer to which I'm writing is perfeclty fine, however the same buffer rendered as a texture on a quad is weirdly distorted. I've corrected the UVs, checked the texture settings but everything seems to be ok.

OpenGL preview is on the right hand side. On the left hand side is a preview of a raw buffer data stored as RGB components (I've used rawpixels.net for preview). It's the same data that I'm sending to the texture. Preview

int width = 400;
int height = 300;

int main() {
    glfwInit();
    glewInit();

    GLFWwindow* win = glfwCreateWindow(width, height, "", NULL, NULL);
    glfwMakeContextCurrent(win);
    glfwSetWindowAttrib(win, GLFW_RESIZABLE, 0);

    unsigned int tex;
    rgb* canvas = new rgb[width * height];

    graphics g(width, height, canvas);
    g.drawLine(vec2(0, 0), vec2(100, 300), 10, rgb(100, 100, 255));

    float x1 = 255.0 / width;
    float x2 = 255.0 / height;

    for (int i = 0; i < width; ++i) {
        for (int j = 0; j < height; ++j) {
            g.pixel(i, j, rgb(i * x1, j * x1, 255));
        }
    }

    g.drawLine(vec2(0, 0), vec2(100, 300), 10, rgb(255, 50, 20));

    g.saveBuffer("./res/frame.raw");

    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_RECTANGLE, tex);
    glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, canvas);
    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP);

    glEnable(GL_TEXTURE_RECTANGLE);

    while (!glfwWindowShouldClose(win)) {
        glfwPollEvents();

        glBegin(GL_QUADS);

        glTexCoord2i(0, 0);
        glVertex2i(-1, 1);

        glTexCoord2i(0, width);
        glVertex2i(-1, -1);

        glTexCoord2i(height, width);
        glVertex2i(1, -1);

        glTexCoord2i(height,0 );
        glVertex2i(1, 1);

        glEnd();

        glfwSwapBuffers(win);
    }

    glDeleteTextures(1, &tex);

    return 0;
}

rgb is just a struct containing R, G and B components stored as unsigned bytes. graphics is an object of a class that I've created. It contains some methods that writes data to the canvas.


Solution

  • You have an issue with your glTexCoord2i - x and y are swapped

            glTexCoord2i(height, width); // must be glTexCoord2i(width, height)
            //           ^=======^
    

    Here is fixed one:

    int width = 400;
    int height = 300;
    
    int main() {
        glfwInit();
        glewInit();
    
        GLFWwindow* win = glfwCreateWindow(width, height, "", NULL, NULL);
        glfwMakeContextCurrent(win);
        glfwSetWindowAttrib(win, GLFW_RESIZABLE, 0);
    
        unsigned int tex;
        rgb* canvas = new rgb[width * height];
    
        graphics g(width, height, canvas);
        g.drawLine(vec2(0, 0), vec2(100, 300), 10, rgb(100, 100, 255));
    
        float x1 = 255.0 / width;
        float x2 = 255.0 / height;
    
        for (int i = 0; i < width; ++i) {
            for (int j = 0; j < height; ++j) {
                g.pixel(i, j, rgb(i * x1, j * x1, 255));
            }
        }
    
        g.drawLine(vec2(0, 0), vec2(100, 300), 10, rgb(255, 50, 20));
    
        g.saveBuffer("./res/frame.raw");
    
        glGenTextures(1, &tex);
        glBindTexture(GL_TEXTURE_RECTANGLE, tex);
        glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, canvas);
        glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP);
    
        glEnable(GL_TEXTURE_RECTANGLE);
    
        while (!glfwWindowShouldClose(win)) {
            glfwPollEvents();
    
            glBegin(GL_QUADS);
    
            glTexCoord2i(0, 0);
            glVertex2i(-1, 1);
    
            glTexCoord2i(0, height);
            glVertex2i(-1, -1);
    
            glTexCoord2i(width, height);
            glVertex2i(1, -1);
    
            glTexCoord2i(width,0 );
            glVertex2i(1, 1);
    
            glEnd();
    
            glfwSwapBuffers(win);
        }
    
        glDeleteTextures(1, &tex);
    
        return 0;
    }