Search code examples
c++openglvisual-studio-2017sfml

Texturing a Quad in OpenGL


So far I've learned how to create a cube with textures in OpenGL. Now I want to change this code for texturing a Quad. I've changed the vertices + indices from a cube to a quad.

And the Quad looks like this:

The texture is completely distorted and the upper triangle is missing...

This is the code I'm using:

1.

GLfloat vertices[] = {
    1.0f,  1.0f, 0.0f,   1.0f, 1.0f, 
    1.0f, -1.0f, 0.0f,   1.0f, 0.0f,  
    -1.0f, -1.0f, 0.0f,   0.0f, 0.0f,  
    -1.0f,  1.0f, 0.0f,   0.0f, 1.0f
};

unsigned int indices[]{
    0,1,2,
    1,2,3,
};

2.

for (size_t o = 0; o < 6; o++) {
    glPixelStorei(GL_UNPACK_ROW_LENGTH, breite_komplett);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, ausschnitt_x_counter);
    glPixelStorei(GL_UNPACK_SKIP_ROWS, ausschnitt_y_counter);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(
        GL_TEXTURE_CUBE_MAP_POSITIVE_X + o, 0, GL_RGBA, ausschnitt_breite, ausschnitt_höhe, 0, GL_RGBA, GL_UNSIGNED_BYTE, sprite_image.getPixelsPtr());
}
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glEnable(GL_TEXTURE_2D);

Do you have an ideas what I need to change?


Edit:

unsigned int indices[]{
    0,1,2,
    0,2,3
};

This is my object builder:

glGenVertexArrays(1, &obj_vao);
glBindVertexArray(obj_vao);

glGenBuffers(1, &obj_ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, obj_ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies[0])* indicies_count, indicies, GL_STATIC_DRAW);

glGenBuffers(1, &obj_vbo);
glBindBuffer(GL_ARRAY_BUFFER, obj_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * count_vertices, vertices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 5, 0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 5, (void*)(sizeof(vertices[0]) * 3));
glEnableVertexAttribArray(1);

glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

Edit:

If the vertices would be like this:

GLfloat vertices[] = {
    1.0f,  1.0f, -1.0f,   1.0f, 1.0f,
    1.0f, -1.0f, -1.0f,   1.0f, 0.0f,
    -1.0f, -1.0f, -1.0f,   0.0f, 0.0f,
    -1.0f,  1.0f, -1.0f,   0.0f, 1.0f
};

Everything would be fine and the Quad looks like this: enter image description here

But I need the Quad in the origin like this:

GLfloat vertices[] = {
    1.0f,  1.0f, 0.0f,   1.0f, 1.0f,
    1.0f, -1.0f, 0.0f,   1.0f, 0.0f,
    -1.0f, -1.0f, 0.0f,   0.0f, 0.0f,
    -1.0f,  1.0f, 0.0f,   0.0f, 1.0f
};

With this vertices the texture is distorted...


Solution

  • The indices of the 2 triangle primitives do not form a quad. The indices have to be:

    unsigned int indices[]{ 0, 1, 2, 1, 2, 3 };

    unsigned int indices[]{ 0, 1, 2,   0, 2, 3 };
    
    3          0
     +-----+  +
     |   /  / |
     | /  /   |
     +  +-----+
    2          1
    

    When you crate the texture, the you mix GL_TEXTURE_CUBE_MAP and GL_TEXTURE_2D. That makes no sense. Either create a cubemap texture and set the parameters for the GL_TEXTURE_CUBE_MAP or create a 2 dimensional texture.


    Anyway if you want to create a cubemap texture, then you have to use GL_TEXTURE_CUBE_MAP, when you set the parameters, too.

    The texture coordinate for a texture cube is a 3 dimensional vector. Change the vertex coordinates for the side of the cube. e.g:
    (You don't need the texture coordinates at all)

    GLfloat vertices[] = {
    //   x      y      z     
         1.0f,  1.0f,  1.0f,   1.0f, 1.0f, 
         1.0f, -1.0f,  1.0f,   1.0f, 0.0f,  
        -1.0f, -1.0f,  1.0f,   0.0f, 0.0f,  
        -1.0f,  1.0f,  1.0f,   0.0f, 1.0f
    };
    

    The center of the cube is (0, 0, 0), so you can use the vertex coordinates for the texture, too:

    Vertex shader

    in vec3 position;
    
    out vec3 cubeCoord;
    
    void main()
    {
        cubeCoord = position;
    
        // [...]
    }
    

    Fragment shader:

    in vec3 cubeCoord;
    uniform samplerCube cubeTex;
    
    void main()
    {
        vec4 color = texture(cubeTex, cubeCoord);
    
        // [...]
    }
    

    Alternatively you can use separate 3 dimensional texture coordinates for the cubemap texture:

    GLfloat vertices[] = {
    //   x      y      z       u      v      w
         1.0f,  1.0f,  0.0f,   1.0f,  1.0f,  1.0f,
         1.0f, -1.0f,  0.0f,   1.0f, -1.0f,  1.0f,
        -1.0f, -1.0f,  0.0f,  -1.0f, -1.0f,  1.0f,
        -1.0f,  1.0f,  0.0f,  -1.0f,  1.0f,  1.0f,
    };