I am learning OpenGL recently. In one of my exercise, I try to load a texture image and map it onto 6 surfaces of a cube. I also applied simple transformation matrix to the vertex shader.
But it turns out that none of the 6 surfaces got right output. Please see the image.
I suspect that something wrong with the indices and texture coordinate vector, but I checked multiple times, cannot find where the error comes from. Can anyone help me find out the issue? Thanks.
The code:
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
int width, height;
unsigned char * image = SOIL_load_image("./challenger.jpg", &width, &height, 0, SOIL_LOAD_RGB);
if(image == NULL) { std::cout << "Failed to load image" << std::endl; return -1; }
// Transfer texture data to texture object.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
//Prepare data
GLfloat vertices[] = {
// front plane
0.5f, 0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
// back plane
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
};
// This is my cube.
/* 7 4
* 3 0
* _________
* /________/|
* | | |
* | | |
* | | |
* |________|/
* 6 5
* 2 1
*/
GLuint indices [] = {
// top
4, 0, 3,
3, 7, 4,
// bottom
5, 1, 2,
2, 6, 5,
// front
0, 1, 2,
2, 3, 0,
// back
4, 5, 6,
6, 7, 4,
// left
3, 2, 6,
6, 7, 3,
// right
4, 5, 1,
1, 0, 4
};
GLfloat texCoords [] = {
// top
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
// bottom
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
// front
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
// back
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
// left
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
// right
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f
};
// Define VBO, EBO and VAO.
GLuint vbo, ebo, vao;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
GLuint vbo_tex_coords;
glGenBuffers(1, &vbo_tex_coords);
glBindVertexArray(vao);
{
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
GLint posAttribPtrLoc = program.getAttribLocation("position");
glVertexAttribPointer(posAttribPtrLoc, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(posAttribPtrLoc);
glBindBuffer(GL_ARRAY_BUFFER, vbo_tex_coords);
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW);
GLint texAttribPtrLoc = program.getAttribLocation("texCoord");
glVertexAttribPointer(texAttribPtrLoc, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(texAttribPtrLoc);
}
glBindVertexArray(0);
program.use();
// Create a game loop.
double lastTime = glfwGetTime();
int frame = 0;
while(!glfwWindowShouldClose(window))
{
glfwPollEvents();
// Rendering
glEnable(GL_DEPTH_TEST);
glClearColor(0.80f, 0.80f, 0.80f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// This uniform should be defined here. Not outside the loop.
// Define my transform matrix.
glm::mat4 model, view, projection;
model = glm::rotate(model, (GLfloat)glfwGetTime() * 1.0f, glm::vec3(1.0f, 1.0f, 1.0f));
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -2.0f));
projection = glm::perspective(45.0f, 800.0f/600, 0.1f, 100.0f);
glm::mat4 transform = projection * view * model;
GLuint transformLoc = program.getUniformLocation("transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, (GLvoid*)0);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
// Finish rendering
glfwSwapBuffers(window);
showFPS(window, lastTime, frame);
}
Vertex shader
const GLchar * vsSource = SHADER_SOURCE(
layout(location = 0) in vec3 position;
layout(location = 2) in vec2 texCoord;
out vec2 myTexCoord;
uniform mat4 transform;
void main()
{
gl_Position = transform * vec4(position.xyz, 1.0f);
myTexCoord = texCoord;
}
);
Fragment shader
const GLchar * fsSource = SHADER_SOURCE(
in vec2 myTexCoord;
out vec4 color;
uniform sampler2D sampler;
void main()
{
color = texture(sampler, vec2(myTexCoord.x, 1.0f - myTexCoord.y));
}
);