2
votes

I am trying to map a texture to objects using GLSL version 330

Here is some code that my help you understanding my problem

Fragment Shader:

#version 330
layout(location = 0) in vec3 vertex;
layout(location = 1) in vec3 vertex_normal;
layout(location = 2) in vec2 texCoord;

out vec2 tCoord;

uniform mat4 modelview;
uniform mat4 projection;

void main() {

  gl_Position = projection * modelview * vec4(vertex, 1.0);
  tCoord = texCoord;

}

Vertex Shader

#version 330

in vec2 tCoord;

uniform sampler2D texture;

out vec4 color;

void main() {
  if(tCoord == vec2(0,0))
    color = vec4(1.0,0.0,0.0,1.0);
  else
    color = vec4(0.0,1.0,0.0,1.0);
}

Loading the Mesh and texture to OpenGL
texture coordinates will be boudn using vertexAttribPointer to position 2 (0 is position and 1 is normal)

Creating the MeshObj

void MeshObj::setData(const MeshData &meshData) {
  mIndexCount = meshData.indices.size();

  // TODO: extend this method to upload texture coordinates as another VBO //
  // - texture coordinates are at location 2 within the shader code


  // create local storage arrays for vertices, normals and indices //
  unsigned int vertexDataSize = meshData.vertex_position.size();
  unsigned int vertexNormalSize = meshData.vertex_normal.size();
  unsigned int vertexTexcoordSize = meshData.vertex_texcoord.size();

  GLfloat *vertex_position = new GLfloat[vertexDataSize]();
  std::copy(meshData.vertex_position.begin(), meshData.vertex_position.end(), vertex_position);
  GLfloat *vertex_normal = NULL;
  if (vertexNormalSize > 0) {
    vertex_normal = new GLfloat[vertexNormalSize]();
    std::copy(meshData.vertex_normal.begin(), meshData.vertex_normal.end(), vertex_normal);
  }
  GLfloat *vertex_texcoord = NULL;
  if (vertexTexcoordSize > 0) {
    vertex_texcoord = new GLfloat[vertexTexcoordSize]();
    std::copy(meshData.vertex_texcoord.begin(), meshData.vertex_texcoord.end(), vertex_texcoord);
  }
  GLuint *indices = new GLuint[mIndexCount]();
  std::copy(meshData.indices.begin(), meshData.indices.end(), indices);

  // create VAO //
  if (mVAO == 0) {
    glGenVertexArrays(1, &mVAO);
  }
  glBindVertexArray(mVAO);

  // create and bind VBOs and upload data (one VBO per available vertex attribute -> position, normal) //
  if (mVBO_position == 0) {
    glGenBuffers(1, &mVBO_position);
  }
  glBindBuffer(GL_ARRAY_BUFFER, mVBO_position);
  glBufferData(GL_ARRAY_BUFFER, vertexDataSize * sizeof(GLfloat), &vertex_position[0], GL_STATIC_DRAW);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
  glEnableVertexAttribArray(0);

  if (vertexNormalSize > 0) {
    if (mVBO_normal == 0) {
      glGenBuffers(1, &mVBO_normal);
    }
    glBindBuffer(GL_ARRAY_BUFFER, mVBO_normal);
    glBufferData(GL_ARRAY_BUFFER, vertexNormalSize * sizeof(GLfloat), &vertex_normal[0], GL_STATIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    glEnableVertexAttribArray(1);
  }

  if (vertexTexcoordSize > 0) {
    if (mVBO_texcoord == 0) {
      glGenBuffers(1, &mVBO_texcoord);
    }
    std::cout << "Texture stuff set" << std::endl;
    glBindBuffer(GL_ARRAY_BUFFER, mVBO_texcoord);
    glBufferData(GL_ARRAY_BUFFER, vertexTexcoordSize * sizeof(GLfloat), &vertex_texcoord[0], GL_STATIC_DRAW);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
    glEnableVertexAttribArray(2);
  }

  // init and bind a IBO //
  if (mIBO == 0) {
    glGenBuffers(1, &mIBO);
  }
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIBO);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndexCount * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);

  // unbind buffers //
  glBindVertexArray(0);

  // make sure to clean up temporarily allocated data, if neccessary //
  delete[] vertex_position;
  if (vertexNormalSize > 0) {
    delete[] vertex_normal;
  }
  if (vertexTexcoordSize > 0) {
    delete[] vertex_texcoord;
  }
  delete[] indices;
}

Render the Scene

  glm_ModelViewMatrix.push(glm_ModelViewMatrix.top());
  glActiveTexture(GL_TEXTURE0);

  glm_ModelViewMatrix.top() = glm::translate(glm_ModelViewMatrix.top(),0.0f,-13.0f,-10.0f);
  glUniformMatrix4fv(uniformLocations["modelview"], 1, false, glm::value_ptr(glm_ModelViewMatrix.top()));

  glBindTexture(GL_TEXTURE_2D, objLoader->getMeshObj("trashbin")->getTexttureID());
  glUniform1i(glGetUniformLocation(shaderProgram,"texture"), objLoader->getMeshObj("trashbin")->getTexttureID());
  objLoader->getMeshObj("trashbin")->render();



  glm_ModelViewMatrix.top() = glm::translate(glm_ModelViewMatrix.top(),-9.0f,-13.0f,-10.0f);
  glm_ModelViewMatrix.top() = glm::scale(glm_ModelViewMatrix.top(), 1.5f,1.5f,1.5f);
  glUniformMatrix4fv(uniformLocations["modelview"], 1, false, glm::value_ptr(glm_ModelViewMatrix.top()));

  glBindTexture(GL_TEXTURE_2D, objLoader->getMeshObj("ball")->getTexttureID());
  glUniform1i(glGetUniformLocation(shaderProgram,"texture"), objLoader->getMeshObj("ball")->getTexttureID());
  objLoader->getMeshObj("ball")->render();

  // restore scene graph to previous state //
  glm_ModelViewMatrix.pop();

Render the mesh

void MeshObj::render(void) {
  // render your VAO //
  if (mVAO != 0) {
    glBindVertexArray(mVAO);
    glDrawElements(GL_TRIANGLES, mIndexCount, GL_UNSIGNED_INT, (void*)0);
    glBindVertexArray(0);
  }
}

After all this code, now a short description of my problem: In my shaders I am currently checking if the texCoord is passed correctly to the shader, but it always stays (0,0). Where is the problem when uploading the texture coordinates? The same technique is working fine for the vertexPosition and the vertex normal...

2

2 Answers

3
votes
glUniform1i(glGetUniformLocation(shaderProgram,"texture"), objLoader->getMeshObj("trashbin")->getTexttureID());

Try passing in the texture unit index (texUnit) instead of the texture object ID (texObj, from a glGenTextures() call).

Generally:

unsigned int texUnit = 0;
glActiveTexture​( GL_TEXTURE0​ + texUnit );
glBindTexture​( GL_TEXTURE_2D, texObj );
glUniform1i( ..., texUnit );

In your case:

glActiveTexture( GL_TEXTURE0 );
...
glBindTexture( GL_TEXTURE_2D, objLoader->getMeshObj("trashbin")->getTexttureID() );
glUniform1i( glGetUniformLocation( shaderProgram, "texture" ), 0 );
1
votes

You don't give the image to OpenGL at any point with glTexImage2D

Add this below your bind texture in order to give OpenGL your texture

//example parameters, substitute with your own.    
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
//just parameters for texture(optional)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

Reference to glTexImage2D:

http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml