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);
}
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);