0
votes

Currently I create my 3D models using following code (simplified):

gl3Element->shaderProgram=glCreateProgram();
glAttachShader(gl3Element->shaderProgram,m_gl3VertexShader);
glAttachShader(gl3Element->shaderProgram,m_gl3DynColourFragmentShader);
glLinkProgram(gl3Element->shaderProgram);
glDeleteShader(m_gl3VertexShader);
glDeleteShader(m_gl3DynColourFragmentShader);

glGenVertexArrays(1, &gl3Element->VAO);
glGenBuffers(1, &gl3Element->VBO);

glBindVertexArray(entity->m_gl3Element.VAO);
glBindBuffer(GL_ARRAY_BUFFER,entity->m_gl3Element.VBO);

glBufferData(GL_ARRAY_BUFFER,size,data,GL_STATIC_DRAW);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

// todo: add texture code here?

glBindBuffer(GL_ARRAY_BUFFER, 0); 
glBindVertexArray(0); 
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

My current (not working) texture code looks like this:

glGenTextures(1, &imgEntity->m_glTexture);
glBindTexture(GL_TEXTURE_2D, imgEntity->m_glTexture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,transImage->GetWidth(),transImage->GetHeight(),0,GL_RGB,GL_UNSIGNED_BYTE,transImage->GetData());
glBindTexture(GL_TEXTURE_2D, imgEntity->m_glTexture);

The things that are missing obviously are texture coordinates and assignment of the texture to the created model. So my questions:

How can I apply some valid texture coordinates to the object using only OpenGL 3.0 and GLSL 1.3?

How do I assign these texture data to the model so that they are drawn on my next call to

glBindVertexArray(element->VAO);
glDrawArrays(element->arrayType,arrayStart,element->arraySize);

for this model ?

Thanks!

1
You need a 2nd attribute. Create a 2nd attribute for the texture coordinates in the vertex shader, beside the vertex coordinates. Pass the texture coordinates from the vertex shader to the fragment shader, and use it for the texture look up. Create and define a texture coordinate array as you do it for the vertex coordinates (/glVertexAttribPointer/glEnableVertexAttribArray). See the following tutorial Textures objects and parameters. But usually this question is to broad. - Rabbid76

1 Answers

3
votes

How can I apply some valid texture coordinates to the object using only OpenGL 3.0 and GLSL 1.3?

Texture coordinates are normally generated by a third party program such as 3DS Max or Blender. 3D artists use these programs to texture their models, when the model is exported the texture coordinates are also exported in the model file. When the model is loaded for rendering, the texture coordinates for each vertex are extracted and then we can pass these coordinates to the shader via a shader attribute.

How do I assign these texture data to the model?

Getting textured geometry in OpenGL can be a bit of a process so I will try to break down the process within a few steps.

  1. Get the models texture coordinates; could be programmatically generated or loaded from a model.

  2. Load in the texture so that it can be used by OpenGL

  3. Set up the attribute array so that the shader can find the texture coordinates.

  4. Modify the vertex shader and fragment shader to support textured geometry

It looks like you already have a mechanism for number 2 (loading in the texture).

So you seem to be just missing the last two steps.

To get the texture coordinates associated with the vertex data you can specify attributes that are associated with the vertex data.

As per the OpenGL documentation:

Vertex attributes are used to communicate from "outside" to the vertex shader. Unlike uniform variables, values are provided per vertex (and not globally for all vertices). There are built-in vertex attributes like the normal or the position, or you can specify your own vertex attribute like a tangent or another custom value. Attributes can't be defined in the fragment shader.

Some sample code might look like this:

//An easy way keep track of what locations are assigned for each attribute
enum Attribute_Location 
{
  AL_Vertices = 0,
  AL_DiffuseTexCoords = 1,
  AL_AlphaTexCoords = 2,
  AL_Normals = 3,
};


GLuint uvBuffer;
glGenBuffers(1, &uvBuffer);

//Bind the buffer 
glBindBuffer(
GL_ARRAY_BUFFER, 
uvBuffer);

//Bind the data to the buffer
glBufferData(GL_ARRAY_BUFFER, 
bufferSize, //size of the buffer you are uploading
&diffuseTexCoords[0], //array of texture coords
GL_STATIC_DRAW);

glEnableVertexAttribArray(AL_DiffuseTexCoords);

//Tells OpenGL how to assign data from the texture buffer to the shader
glVertexAttribPointer(AL_DiffuseTexCoords, 
2, 
GL_FLOAT, 
GL_FALSE, 
0, 
0);

And here is an example of how the vertex shader and fragment shader would look, courtesy of http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/

Textured.vs

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;

// Output data ; will be interpolated for each fragment.
out vec2 UV;

// Values that stay constant for the whole mesh.
uniform mat4 MVP;

void main()
{

    // Output position of the vertex, in clip space : MVP * position
    gl_Position =  MVP * vec4(vertexPosition_modelspace,1);

    // UV of the vertex. No special space for this one.
    UV = vertexUV;
}

Textured.fs

#version 330 core

// Interpolated values from the vertex shaders
in vec2 UV;

// Ouput data
out vec3 color;

// Values that stay constant for the whole mesh.
uniform sampler2D myTextureSampler;

void main()
{

    // Output color = color of the texture at the specified UV
    color = texture( myTextureSampler, UV ).rgb;
}

Note that the attribute location of the vertices and texture coordinates specified in the enum Attribute_Location match the layout location in the vertex shader:

enum Attribute_Location 
    {
      AL_Vertices = 0,
      AL_DiffuseTexCoords = 1,
      ...
    }

layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;