Search code examples
c++opengltextures

OpenGL - Texture not displaying properly (clamping?)


I've just started learning about textures in OpenGL and have come across this problem :

Suspected : Problem with function glEnableVertexAttribArray() or glVertexAttribPointer()

For the VertexBuffer and IndexBuffer Constructors they take in the size, data and indices,data respectively

// Cant post images, dont have enough reputation (sry)

Texture.cpp

Texture::Texture(const std::string & filepath)
    : m_RendererID(0), m_Filepath(filepath), m_ImageBuffer(nullptr), 
    m_Width(0), m_Height(0), m_BPP(0)
{
stbi_set_flip_vertically_on_load(true);
m_ImageBuffer = stbi_load(filepath.c_str(), &m_Width, &m_Height, &m_BPP, 4);

if (m_ImageBuffer == NULL)
    std::cout << "Unable to open file : " << m_Filepath << "!";

glGenTextures(1, &m_RendererID);
glBindTexture(GL_TEXTURE_2D, m_RendererID);

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

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_ImageBuffer);
glBindTexture(GL_TEXTURE_2D, 0);

if (m_ImageBuffer)
    stbi_image_free(m_ImageBuffer);
}

main.cpp

float positions[] =
{
    // positions //texCoords
     0.5f,  0.5f, 0.0f, 0.0f,
    -0.5f,  0.5f, 1.0f, 0.0f,
    -0.5f, -0.5f, 0.0f, 1.0f,
     0.5f, -0.5f, 1.0f, 1.0f
};

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

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

VertexBuffer vb(4 * 4 * sizeof(float), positions);

IndexBuffer ib(6, indices);

Shader shader("res/shaders/basic.shader");
shader.Bind();
shader.SetUniform4f("u_Color", 0.0f, 0.0f, 1.0f, 1.0f);

Texture texture("res/textures/pepe.jpg");
texture.Bind();
shader.SetUniform1i("u_Texture", 0);

Renderer renderer;

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);

while (!glfwWindowShouldClose(window))
{
    renderer.Clear();

    renderer.Draw(ib, shader);

    glfwSwapBuffers(window);

    glfwPollEvents();
}

Solution

  • The last parameter of glVertexAttribPointer is the offset of the first component of the first generic vertex attribute in the array. This parameter is not set correctly for the texture coordinates:

    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), (void*)(2*sizeof(float)));

    see OpenGL 4.6 API Compatibility Profile Specification; 10.3.9 Vertex Arrays in Buffer Objects; page 409

    ... When an array is sourced from a buffer object for a vertex attribute, [...] the offset set for the vertex buffer [...] is used as the offset in basic machine units of the first element in that buffer’s data store.


    Further the texture coordinates are confused. Change it to:

    float positions[] =
    {
        // positions //texCoords
        0.5f,  0.5f, 1.0f, 0.0f,
       -0.5f,  0.5f, 0.0f, 0.0f,
       -0.5f, -0.5f, 0.0f, 1.0f,
        0.5f, -0.5f, 1.0f, 1.0f
    };