0
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ If you use 24 vertices for a cibe, then you need to privide 24 textureCoords too. \$\endgroup\$
    – Bálint
    Apr 13 '16 at 16:34
  • \$\begingroup\$ Using 24 uv coordinates. I tried copying the above texture coordinates to equal 24 texture coordinates. Final image still looks weird. Should the texture coordinates be in any particular configuration? \$\endgroup\$
    – user40247
    Apr 13 '16 at 17:18
0
\$\begingroup\$

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.

\$\endgroup\$
4
  • \$\begingroup\$ Thank you for the response. Your recommended renders one face of the cube correctly, the rest look even more blurry. \$\endgroup\$
    – user40247
    Apr 13 '16 at 17:52
  • \$\begingroup\$ I see, answer updated with the indices resolution. \$\endgroup\$
    – michcio
    Apr 13 '16 at 18:52
  • \$\begingroup\$ The solution works. The only problem I'm having is that one of the faces is not rendering at all. There also seems to be a problem were when I rotate the cube, some faces are transparent, and I can be through the cube. Its there are a way to remove the transparency aspect. Thanks for the help overall. \$\endgroup\$
    – user40247
    Apr 13 '16 at 20:20
  • \$\begingroup\$ actually nevermind, I remember I could use glEnable(GL_DEPTH_TEST), and glDepthFunc(GL_LEQUAL). Thank you again for the help. \$\endgroup\$
    – user40247
    Apr 13 '16 at 23:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .