PDA

View Full Version : VAO's and UV indices



dlukeb
06-27-2010, 09:32 PM
I'm having trouble rendering a texture onto my 3d model using a VAO, seems like problem with the UV's. I can see the texture but its all stretched and wacky.

I have the UV coords, UV indices and the Vertices, Vert indices which I have parsed in from an .obj file.

I start by creating the buffers for only the verts, UV coords and the Vert indices.


//Push the entire vert array onto the card
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, positionSize , &pNewModel->mLocalMesh.vertices[0], GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0);

GLsizeiptr const uvSize =
pNewModel->mLocalMesh.textureCoords.size() *sizeof(glm::vec2);
//Push the entire vert array onto the card
glGenBuffers( 1, &UVbo );
glBindBuffer( GL_ARRAY_BUFFER, UVbo );
glBufferData( GL_ARRAY_BUFFER, uvSize , &pNewModel->mLocalMesh.textureCoords[0], GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0);

GLsizeiptr const elementSize = pNewModel->mLocalMesh.vertIndices.size() * sizeof( GLushort );
///TODO: create UV index buffer
///TODO: create vertexNormal index Buffer
glGenBuffers( 1, &ElementBufferName );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ElementBufferName );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, elementSize, &pNewModel->mLocalMesh.vertIndices[0], GL_STATIC_DRAW );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );


glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
//Setup the element buffer
///Vert Buffer
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(shaderPOSITION, 3, GL_FLOAT, GL_FALSE, 0, 0);

//shader property
glEnableVertexAttribArray(shaderPOSITION);

///glActiveTexture(GL_TEXTURE0); Don't think I need this
glBindTexture(GL_TEXTURE_2D, pNewModel->mMaterial.texture1ID);

///UV buffer
glBindBuffer( GL_ARRAY_BUFFER, UVbo );
glVertexAttribPointer(pNewModel->mMaterial.shaderTEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(pNewModel->mMaterial.shaderTEXCOORD);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBufferName);
glBindVertexArray(0);


Then when I render:


glBindVertexArray( currModel.mMeshBuffers.vaoIDs.at(x) );

glDrawElements( GL_TRIANGLES, currModel.mLocalMesh.vertIndices.size() , GL_UNSIGNED_SHORT, 0 );

glBindVertexArray(0);




Feels like I'm missing the part where I need to tell openGL about the UV indices. But how do I do it using a VAO? There seems to be only binding for the vert indices in the VAO.

I'm only using non-deprecated functions.

Alfonse Reinheart
06-27-2010, 10:17 PM
There are no vertex indices or UV indices. There is only the one element array (http://www.arcsynthesis.org/gltut/Positioning/Tutorial%2005.html#d0e3779) that selects for all vertex attributes.

dlukeb
06-28-2010, 12:44 AM
Thanks for the reply Alfonse!

Hmmm, right, so there is only ONE element array bound to the VAO.

Though it says in that tutorial is you give it elements say:
0,1,2

Then I'm guessing it looks what attribute buffers has been bound to the VAO say (pos, vert normal, textcoords) and will go like:

(Pos0, VN0, UV0), (Pos1, VN1, UV1, (Pos2, VN2, UV2)?

Though when I'm reading in from my .obj file:

vertIndex/uvIndex/VertNormalIndex
f 144/155/437 42/42/438 143/154/439

and I stick these into my element array everything would go wrong?:
(Pos144, VN144, UV144), (Pos155, VN155, UV155), (Pos437, VN437, UV437)

I would want this:
(Pos144, VN155, UV437), (Pos42, VN42, UV438), (Pos143, VN154, UV439)

I'm not sure if I'm understanding this correctly. The tutorial seems great. But can't see how they build the element Array and use glBufferData to allocate the element memory, so I don't get the hole picture in my head.

Alfonse Reinheart
06-28-2010, 08:38 AM
I would want this:

OpenGL has no direct support for it. You can finesse it if you want with buffer textures or something else, but you're not going to get it with simple attributes.

The normal way to deal with this is to properly format your data, duplicating vertex attributes where necessary, so that it uses the same index for all attributes.

dlukeb
06-28-2010, 09:30 AM
Thanks again Alfonse
ok, so if I have a face with attributes like these

f 52/52/123 49/53/124 51/51/125

I could copy the vertex and the UV, append the new vert and UV to the end of the list, making sure I give them the exact same index number....

this seems like an incredible pain? hmm

What I don't understand is with parts in my OBJ file it has:

47/47/121 49/49/120 50/50/122
s 32
f 52/52/123 49/53/124 51/51/125

so vertex 49 has 2 different UV's. Don't know why that is, should maybe use a simpler model for now..

But I'm still fairly confused with why openGL won't let me explicitly tell it which UVs to use with which verts, seems crazy. So now I'll have to take note that if the vert , UV and vertexNormal are different indices I have to copy each of them and append it to the end of their buffers so I can align them, so they have the same index.....?

Rosario Leonardi
06-28-2010, 11:09 AM
Take a Cube.
Cube have 8 vertex and 6 quad face ==> 12 triangles.

But every face have shared point and every point have three different normal. (Don't consider UV now but the problem is the same).

Now, let's say you want to render this with your method.
You have an array of position, and an array of normal. Then you setup an array of index for position and an array of index for the normal.

With openGL method (in this case) you have to split every triangle and you have 12 triangles, every triangle have three vertexes and every vertex have a position and a normal.
12*3*((3+3)*4)= 864 byte. And the indexes 12*3*4=144 byte

Almost a 1kB for a cube (without UV). WOW openGL sucks!!

With your method we don't split, we have 8 position, and 6 normal

(8+6) * 3 * 4 = 168 and our 144 byte for the index X2 (we need index for normal too) ==> 168+144*2=456
This is cool, we save more than half of the memory.

So, why openGL use the dump memory eater method?

The answer is quite simple:
- If you keep the information very separated in memory to draw a triangle you have to jump from a memory location to another. It's a cache killer.

Also consider that cube is an extreme case where every face must split. A smooth mesh share most of the vertexes attributes.

The split algorithm is quite easy and you can find it on-line.

dlukeb
06-29-2010, 09:50 AM
Ah right because of the cache "hit" and "miss", that makes sense.

I can't find this split algorithm you talk about on the net. Though, all I would have to do is if the vert index differs from the other indicies then I would have to make a copy of the vert attributes into their own VBOs to align and match the attributes index numbers.

so if I get
//vertPos, UV,vertNormal
(1,1,1)
thats fine .
but if i get (1,2,3)
I possibly have to copy the vertPos.UV into index 3 of their buffer object or maybe possibly copy the attributes into, say, index 4 of their own buffers.

Is this correct?