0
votes

I have this weird problem with texturing of OBJ files in OpenGL. I have successfully parse and render the models correctly and i'm trying now to apply texture to it. Here's how I do it.

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

// bind the vertices coord
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, cc * sizeof(GLfloat), vertices,   GL_STATIC_DRAW);


// bind the textures coord
GLuint tcbuffer;
glGenBuffers(1, &tcbuffer);
glBindBuffer(GL_ARRAY_BUFFER, tcbuffer);
glBufferData(GL_ARRAY_BUFFER, tcc * sizeof(GLfloat), textures GL_STATIC_DRAW);

// for the texture itself
GLuint tid;
glGenTextures(1, &tid);
glBindTexture(GL_TEXTURE_2D, tid);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nptr);

glEnableVertexAttribArray(m_vert);
glBindBuffer(GL_ARRAY_BUFFER, vbufferid);
glVertexAttribPointer(m_vert, 3, GL_FLOAT, GL_FALSE, 0, 0);

glEnableVertexAttribArray(m_texcoord);
glBindBuffer(GL_ARRAY_BUFFER, tcbufferid);
glVertexAttribPointer(m_texcoord, 2, GL_FLOAT, GL_FALSE, 0, 0);

glDrawArrays(GL_TRIANGLES, 0, vc);

And for the texture coordinates in my parser, I swap the y-coordinate(subtract y from 1) to get the proper orientation of the texture. This code works for different models but with this specific model, the texture is incomplete. You can here for the output I get with this model and here for the working ones. Hope you can help! :)

P.S: the code is shorten for viewing purposes :)

1
Not sure if this is your immediate problem, but the glGenerateMipmap() call needs to be after glTexImage2D(). Otherwise it has not texture data to generate the mipmaps from.Reto Koradi
@RetoKoradi Thanks for pointing it out. I have tried moving it after glTexImage2D yet it does not solve the problem. What I have noticed is that the texture itself only provides half of the model, look here link for what I am talking about :D But should I do something to somehow duplicate the texture? From what I know obj handles this as it provides the texture coordinates per face.zyneragetro
Does the file have texture coordinates outside the [0.0, 1.0] range? Try using GL_REPEAT for the texture wrap modes.Reto Koradi
@RetoKoradi - I tried using the GL_REPEAT and now it works! Thanks :) I just wanna ask if GL_REPEAT will always work in other models? Because my plan is to make an OBJ parser for any models without modifying my code every other model I tried.zyneragetro
@RetoKoradi - I just tested other models and it works great! Thanks dude.zyneragetro

1 Answers

2
votes

Depending on how the modelling program generates textures and texture coordinates, it is possible that it will generate texture coordinates outside the standard [0.0, 1.0] range. Since you set the wrap modes as:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

all texture coordinates outside this range will get the color of the closest edge texel. It loos like your texture has black around the edge, so all those pixels will be sampled as black.

If this is the problem, you need to set the parameters as:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

It's also theoretically possible, even though less likely, that the modelling program would generate texture coordinates to work with mirrored repeat. If texture images show up in the currently black parts after switching to GL_REPEAT, but they look like the wrong parts of the texture, you could also try:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

There's a related problem that the OP had already figured out, but I'll mention it here just in case somebody else with a similar problem comes across this answer: In the OBJ files with textures I have seen, the second texture coordinates (y, or t if you prefer that nomenclature) were in the opposite direction of the way OpenGL uses them (aka y-inverted). I'm not sure if this is standard in OBJ, or depends on what software generated the file. The typical symptom is that the texture is displayed on the geometry, but completely wrong parts of the texture are mapped. This can be fixed by mirroring the second coordinate, either while reading the file (replace y by 1.0 - y), or by applying the corresponding mapping of the texture coordinates in the shader.