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\$
  • \$\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\$
  • \$\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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.