c++openglglslglfw

Yet another OpenGL texture not rendering post


I have just started learning OpenGL and I have had no luck rendering the textures that I want. Whenever I execute the code below I get a purple screen with no texture rendered. I tried doing more error checking by glGetError(). But that did not get me anywhere. Also, I made sure error checking is done in Shader and Voa classes. As no error were reported from those classes, they are working fine. The textures seem to be loading as well, since I get no error from those either. I would appreciate it if someone could tell me what I am doing wrong. Here is the code:

C++ code:

int main()
{
    GLFWwindow* lv_window = Init(static_cast<int>(GlobalVar::Mouse::lv_screenWidth), static_cast<int>(GlobalVar::Mouse::lv_screenHeight));

    if (lv_window == nullptr) {
        return -1;
    }

    std::vector<float> lv_vertices
    {
    //Position        //Color              //Texture coordinates
    0.5f,  0.5f, 0.0f,    1.0f, 0.0f, 0.0f,    1.0f, 1.0f,                   
    0.5f, -0.5f, 0.0f,    0.0f, 1.0f, 0.0f,    1.0f, 0.0f,  
       -0.5f, -0.5f, 0.0f,    0.0f, 0.0f, 1.0f,    0.0f, 0.0f,
       -0.5f,  0.5f, 0.0f,    1.0f, 1.0f, 0.0f,    0.0f, 1.0f,
    };

    std::vector<unsigned int> lv_indices
        {
        0, 1, 3,
        1, 2, 3
    };

    glClearColor(0.5f, 0.4f, 0.8f, 1.0f);

    int lv_width, lv_height, lv_nColorChannels;


    //First texture
    GLuint lv_texture;
    glGenTextures(1, &lv_texture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, lv_texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    stbi_uc* lv_textureData = stbi_load("C:/Users/source/repos/firstProjectGL/Images/container.jpg", &lv_width, &lv_height, &lv_nColorChannels, 0);

    if (lv_textureData != nullptr) {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, lv_width, lv_height, 0, GL_RGB, GL_UNSIGNED_BYTE, lv_textureData);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else {
        std::cout << "Texture failed to be generated!\n";
    }
    stbi_image_free(lv_textureData);


    //Second Texture
    GLuint lv_texture2;
    glGenTextures(1, &lv_texture2);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, lv_texture2);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    stbi_set_flip_vertically_on_load(true);
    
    lv_textureData = stbi_load("C:/Users/source/repos/firstProjectGL/Images/Happyface.png", &lv_width, &lv_height, &lv_nColorChannels, 0);
    if (lv_textureData != nullptr) {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lv_width, lv_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, lv_textureData);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else {
        std::cout << "Texture2 failed to be generated!\n";
    }
    stbi_image_free(lv_textureData);

    
        //Compile & Link Shader
        std::string lv_vertexShader = "vTextureTest.txt";
    std::string lv_fragmentShader = "fTextureTest.txt";
    Shader lv_shaderProgram(lv_vertexShader, lv_fragmentShader);
    lv_shaderProgram.Use();


        //Initialize VOA & VBO
    Voa lv_voa(lv_vertices);
    GLuint lv_EBO;
    glGenBuffers(1, &lv_EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lv_EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, lv_indices.size() * sizeof(unsigned int), lv_indices.data(), GL_STATIC_DRAW);
    
    lv_voa.BindVertexArrayObject();
    lv_voa.BindVertexBufferObject(GL_ARRAY_BUFFER);
    lv_voa.BufferDataSTATIC_DRAW(GL_ARRAY_BUFFER);
    
    lv_voa.SetUniform1i(lv_shaderProgram.GetShaderID(), "lv_ourTexture", 0);
    lv_voa.SetUniform1i(lv_shaderProgram.GetShaderID(), "lv_ourTexture2", 1);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), reinterpret_cast<void*>(0));
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), reinterpret_cast<void*>(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), reinterpret_cast<void*>(6 * sizeof(float)));
    glEnableVertexAttribArray(2);


        glEnable(GL_DEPTH_TEST);
    
    //Render loop
    while (!glfwWindowShouldClose(lv_window)) {

        glfwPollEvents();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        glfwSwapBuffers(lv_window);
    }


    glfwTerminate();
    return 0;

}

Vertex shader:

#version 330 core

layout (location = 0) in vec3 lv_pos;
layout (location = 1) in vec3 lv_color;
layout (location = 2) in vec2 lv_texCoordInput;

out vec3 lv_ourColor;
out vec2 lv_texCoord;

void main()
{
    gl_Position = vec4(lv_pos, 1.0);
    lv_ourColor = lv_color;
    lv_texCoord = lv_texCoordInput;
}

Fragment shader:

#version 330 core

out vec4 lv_fragColor;
in vec3 lv_ourColor;
in vec2 lv_texCoord;

uniform sampler2D lv_ourTexture;
uniform sampler2D lv_ourTexture2;

void main()
{
    lv_fragColor = mix(texture(lv_ourTexture, lv_texCoord), texture(lv_ourTexture2, lv_texCoord), 0.2);
}

Solution

  • The Index Buffer (ELEMENT_ARRAY_BUFFER) binding is stored within the Vertex Array Object. When glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...) is called the element buffer object ID is stored in the currently bound Vertex Array Object. Therefore the VAO must be bound before the element buffer with glBindVertexArray(VAO).

    Voa lv_voa(lv_vertices);
    lv_voa.BindVertexArrayObject();             // <--- bind the VAO here
    
    GLuint lv_EBO;
    glGenBuffers(1, &lv_EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lv_EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, lv_indices.size() * sizeof(unsigned int), lv_indices.data(), GL_STATIC_DRAW);