Currently working on applying a texture to a cube and I am at a road block. I am using UV coordinates to apply the texture. Currently using 24 uv coordinates with indices. I am using glDrawElement and draw all 36 vertices. The cube in itself renders but the texture looks blurry and not accurate.
const GLfloat vertices[] = {
-0.5f, 0.5f, 0.0f, // Top Left
-0.5f, -0.5f, 0.0f, // Bottom Left
0.5f, -0.5f, 0.0f, // Bottom Right
0.5f, 0.5f, 0.0f, // Top Right
-0.5f, 0.5f, -1.0f, // Top Left (back)
-0.5f, -0.5f, -1.0f, // Bottom Left (back)
0.5f, -0.5f, -1.0f, // Bottom Right (back)
0.5f, 0.5f, -1.0f // Top Right (back)
};
const GLfloat color[] = {
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f
};
const GLfloat texCoord[] = {
1.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
const GLfloat uvCoord[] =
{
0.0f, 1.0f, // Top Left
0.0f, 0.0f, // Bottom Left
1.0f, 0.0f, // Bottom Right
1.0f, 1.0f, // Top Right
0.0f, 1.0f, // Top Left
0.0f, 0.0f, // Bottom Left
1.0f, 0.0f, // Bottom Right
1.0f, 1.0f, // Top Right
0.0f, 1.0f, // Top Left
0.0f, 0.0f, // Bottom Left
1.0f, 0.0f, // Bottom Right
1.0f, 1.0f, // Top Right
0.0f, 1.0f, // Top Left
0.0f, 0.0f, // Bottom Left
1.0f, 0.0f, // Bottom Right
1.0f, 1.0f, // Top Right
0.0f, 1.0f, // Top Left
0.0f, 0.0f, // Bottom Left
1.0f, 0.0f, // Bottom Right
1.0f, 1.0f, // Top Right
0.0f, 1.0f, // Top Left
0.0f, 0.0f, // Bottom Left
1.0f, 0.0f, // Bottom Right
1.0f, 1.0f // Top Right
};
const GLuint indices[] =
{
// Front
0, 1, 3,
1, 2, 3,
// Back
4, 5, 6,
4, 6, 7,
// Left
4, 5, 1,
1, 0, 4,
// Right
3, 6, 2,
7, 6, 3,
// Top
7, 4, 3,
4, 0, 3,
// Bottom
1, 2, 5,
2, 5, 6
};
const GLuint VERTEX_POS = 0;
const GLuint COLOR = 1;
const GLuint TEX_POS = 2;
const GLuint UV_POS = 3;
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
const int SIZE = 4;
GLuint VBO[SIZE];
glGenBuffers(SIZE, VBO);
// Handles position
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(VERTEX_POS, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(VERTEX_POS);
// Handles Color
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(color), color, GL_STATIC_DRAW);
glVertexAttribPointer(COLOR, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(COLOR);
// Handles Texture Coordinates
glBindBuffer(GL_ARRAY_BUFFER, VBO[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW);
glVertexAttribPointer(TEX_POS, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(TEX_POS);
// Handles uv Coordinates
glBindBuffer(GL_ARRAY_BUFFER, VBO[3]);
glBufferData(GL_ARRAY_BUFFER, sizeof(uvCoord), uvCoord, GL_STATIC_DRAW);
glVertexAttribPointer(UV_POS, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(UV_POS);
GLuint EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
GLuint Texture;
glGenBuffers(1, &Texture);
glBindTexture(GL_TEXTURE_2D, 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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
int texWidth;
int texHeight;
unsigned char * image = SOIL_load_image("brick_texture1.jpg", &texWidth, &texHeight, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth, texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
In the loop:
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
vertex shader:
#version 400 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;
layout (location = 2) in vec2 texCoord;
layout (location = 3) in vec2 uvCoord;
out vec4 out_color;
out vec2 out_texCoord;
out vec2 out_uvCoord;
uniform mat4 MVP;
uniform mat4 rotation_matrix;
void main()
{
out_color = color;
out_uvCoord = uvCoord;
out_texCoord = vec2(texCoord.x, texCoord.y);
gl_Position = MVP * rotation_matrix * vec4(position, 1.0f);
}
Fragment Shader:
#version 400 core
in vec4 out_color;
out vec4 Output_Color;
in vec2 out_texCoord;
out vec2 Output_texCoord;
in vec2 out_uvCoord;
uniform sampler2D Texture;
void main()
{
Output_Color = texture(Texture, out_uvCoord);
}
The finale product:
I do not know what the problem might be.
The 5th "stride" argument in all of your 4 glVertexAttribPointer
calls is specified as 3 * sizeof(GLfloat)
, while in your case it should be 0, as you are using separate buffers per vertex attribute (see https://www.opengl.org/sdk/docs/man/html/glVertexAttribPointer.xhtml).
That argument is non-zero for cases when you interleave those attributes in a single buffer, which is an interesting optimisation, see https://www.opengl.org/wiki/Vertex_Specification_Best_Practices, but I'd just change those arguments to 0 for now.
You're also using glDrawElements, which forces a different topology than you probably want to have, as the cube's faces share vertex positions, but not necessarily vertex uv mappings.
What the glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
call is doing, is taking only uvCoord
with indices from the 0-7 range (as that's what your indices
array contains) which don't correspond to the correct texture coordinates at most faces.
You'll find a good explanation of mesh topologies at http://alfonse.bitbucket.org/oldtut/Illumination/Tut09%20Mesh%20Topology.html, the whole tutorial is a great read.
To cut the long story short :)
Define vertices as:
const GLfloat vertices[] = {
-0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5,
-0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5,
0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5,
0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5,
0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5,
-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5,
-0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5,
-0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5,
-0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
-0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5,
-0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5
};
(This does what your indices sort of did, but in an explicit way)
Define uvCoord as:
const GLfloat uvCoord[] = {
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f
};
so each face has the same uv mapping.
Replace the
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
call with
glDrawArrays(GL_TRIANGLES, 0, 36);
- Comment out the indices binding (
GLuint EBO;...
and 3 following lines)
Hopefully it works, if it does then try to experiment with the uvCoord
definition to obtain the texture mapping you need.