OpenGL - texture are mapped incorrectly using glDrawElements
Asked Answered
S

2

-1

I am creating an OBJ parser which reads the file and draw it using glDrawElements. The thing here is the model is correctly drawn but when I try to give it a texture, it is incorrectly mapped. I have read here that "OpenGL can only use one index buffer, whereas OBJ use one index buffer by attribute". I have also researched about the textures being incorrectly mapped when using glDrawElements and found out that I need to rearrange the textures because only vertices are shared but not the textures. Having said all of this, how should I suppose to rearrange the textures? Should I duplicate some textures? Please refer to this link for the sample output I get.

Scala answered 27/7, 2015 at 9:37 Comment(0)
B
1

The OBJ format specifies UNIQUE texture coordinates, vertices and faces.

Opengl has nothing to do with OBJ, of course, so all it wants is the right information at the right place.

Imagine two faces like this in your OBJ (Notice vertex 1 texcoords in both faces)

f:    v1 |t1|     v2 t2      v3 t3 
f:    v1 |t2|     v4 t4      v5 t5 

Your INDEX buffer like this:

1 2 3     1 4 5

Your opengl VERTEX buffer first looks like this:

v1 v2 v3 v4 v5

If you add texture coordinates, where do you add them? Like this?

v1 t1     v2 t2     v3 t3     v4 t4      v5 t5

This is likely what you have now, its wrong because opengl makes the faces like this:

f:    v1 |t1|      v2 t2      v3 t3 
f:    v1 |t1|      v4 t4      v5 t5 

Because v1 and t1 are linked together by your indexbuffer, notice the difference between the vertices in the OBJ and in OpenGL.

There are a couple of ways to solve this. I'd recommend getting rid of the indexbuffer, because it only complicates everything. Without the index buffer, you simply supply all faces as if they are unique, and use a different draw call (glDrawArrays). Your vertex buffer will look like this:

v1 |t1|      v2 t2       v3 t3       v1 |t2|       v4 t4        v5 t5

You duplicate v1, but really its not so much extra data most of the time, since you don't have to specify an index buffer anymore.

This kind of stuff is really annoying to think about, I tried my best to make it approachable, and I hope I didn't make any mistakes.

Baccivorous answered 27/7, 2015 at 12:53 Comment(1)
Thanks for the response and sorry for the late reply. This is really helpful to me and it makes it clear now. The index buffer was used because I intend to use the GL_TRIANGLE_STRIP and I can't make it work in glDrawArrays.Scala
W
0

I am not too familiar with OBJ, but what you say is that OBJ can reference different attributes by index per vertex. You have one big array of xyz, another big array of uv. And every vertex then has an index into the xyz array and another index into the uv array. But opengl only has one index per vertex! So if the xyz and uv index are different opengl will not work. One easy way to fix this is to loop through all vertices, and if their uv index is not the same as the xyz index, just copy the data of both to the end of their buffers and set the index to that.

Whited answered 27/7, 2015 at 9:51 Comment(1)
I will keep this in mind as I really want to make it work with glDrawElements. I am just curious, should I really copy both to the end of their buffer or it can be just the texture?Scala

© 2022 - 2024 — McMap. All rights reserved.