Monday, July 31, 2017

opengl - Trouble applying a texture to a cube


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: enter image description here enter image description here


I do not know what the problem might be.



Answer



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 :)





  1. 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)




  1. 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.





  1. Replace the


    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);


call with


glDrawArrays(GL_TRIANGLES, 0, 36);


  1. 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.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...