Hi! I need to port some deprecated code to Core and I have troubles with texturing. I simply can’t find a good tutorial for texturing with GLSL (tried the NeHe, Oranges, Superbible…).
I have a 2D puzzle-like image that consists of a few dozen quadratic tiles that should be textured. Think of it as a chessboard, or a quad 2D mesh. Following some examples I found, I’ve managed to get the things working for a single triangle, but I cannot port the solution to the ‘real thing’. Can anyone point me in the right direction, either in form of a tutorial or at least with a hint at what am I missing?
Thanks!
The code looks like this -
Vertex is a simple structure, the coordinates and indexes of the mesh are 100% ok.
typedef struct
{
GLfloat loc[2]; //2 coordinates are enough for 2D
GLfloat tex[2];//same here
} Vertex;
The whole thing works correctly without shaders in this way:
In the pre-loop function setupRC() :
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numberOfVertices, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * numberOfVertices, myVertices);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(8));
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numberOfIndexes * sizeof(GLushort), myIndexes, GL_STATIC_DRAW);
and then in the paintGL:
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, myTextureId );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(8));
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));
glDrawElements(GL_TRIANGLES, numberOfIndexes, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable( GL_TEXTURE_2D );
However, if I use the vertex array object and shaders instead like this: (setupRC function):
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(2, bufferObjects); //2 buffers, vertex + texture interleaved and indexes
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[0]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numberOfVertices, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * numberOfVertices, myVertices);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(8));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObjects[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*numberOfIndexes, myIndexes, GL_STATIC_DRAW);
glBindVertexArray(0);
myShader = loadShaderWithAttribs( 2, 0, "vVertex", 1, "vTexCoords"); //2 attributes, in index 0 comes 'vVertex' and in index 1 'vTexCoords'
with the shaders and the loadShaderWithAttribs function defined as:
GLuint loadShaderWithAttribs(int nAttribs, ...)
{
GLuint vs;
GLuint fs;
GLuint shader = 0;
//Vertex shader:
static std::string source_vs =
"#version 330
"
"in vec4 vVertex;
"
"in vec2 vTexCoords;
"
"smooth out vec2 vVaryingTexCoords;
"
"void main(void)
"
" {
"
" vVaryingTexCoords = vTexCoords;
"
" gl_Position = vVertex;
"
" }\0";
//Fragment shader:
static std::string source_fs =
"#version 330
"
"uniform sampler2D colorMap;
"
"out vec4 vFragColor;
"
"smooth in vec2 vVaryingTexCoords;
"
"void main(void)
"
" {
"
" vFragColor = texture(colorMap, vVaryingTexCoords.st);
"
" }\0";
const char * vsSource = source_vs.c_str();
const char * fsSource = source_fs.c_str();
vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vsSource, NULL);
glCompileShader(vs);
fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fsSource, NULL);
glCompileShader(fs);
shader = glCreateProgram();
glAttachShader(shader, vs);
glAttachShader(shader, fs);
//Binding the attributes...
va_list attributeList;
va_start(attributeList, nAttribs);
char *nextArg;
int iArgCount = va_arg(attributeList, int);
for(int i = 0; i < iArgCount; i++)
{
int index = va_arg(attributeList, int);
nextArg = va_arg(attributeList, char*);
glBindAttribLocation(shader, index, nextArg);
}
va_end(attributeList);
glLinkProgram(shader);
glDeleteShader(vs);
glDeleteShader(fs);
return shader;
}
… now I suppose this is the part where I fail - painGL():
glUseProgram(myShader);
glBindTexture(GL_TEXTURE_2D, myTextureId);
GLint iTextureUniform = glGetUniformLocation(myShader, "colorMap");
glUniform1i(iTextureUniform, 0);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, numberOfIndexes, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));