PDA

View Full Version : Trying in vain to get a VBO implementation working



OpenGL Developer
02-26-2012, 02:19 AM
I've wrestled with VBOs for quite some time, never satisfactorily implementing a class in C++ that handles the basic "VNT" VBO (one which most readily replaces immediate mode).

I have read almost every tutorial worth a glance on the net and I have got to the following situation through careful implementation and reading many different function specifications, tutorials and Wiki entries on the topic.

I fully understand that VBOs have components defined in a C struct that are then passed to the GPU via glBufferData and related functions. I understand indices and 'auto-interleaving' as well as the optimal type choices.

I'm confused about the usefulness of a VAO, and even how to create one. However, the thing I'm trying to accomplish shouldn't require one, based on "VBO Examples" from the Wiki.


Situation:
I have a list of triangles indexed in a linked list of linked lists of vertexes.

I copied these from a unit cube PLY:

unitcube.ply:

ply
format ascii 1.0
comment Cube
element vertex 24
property float x
property float y
property float z
property float nx
property float ny
property float nz
element face 6
property list uchar uint vertex_indices
end_header
1.000000 1.000000 -1.000000 0.000000 0.000000 -1.000000
1.000000 -1.000000 -1.000000 0.000000 0.000000 -1.000000
-1.000000 -1.000000 -1.000000 0.000000 0.000000 -1.000000
-1.000000 1.000000 -1.000000 0.000000 0.000000 -1.000000
1.000000 0.999999 1.000000 0.000000 -0.000000 1.000000
-1.000000 1.000000 1.000000 0.000000 -0.000000 1.000000
-1.000000 -1.000000 1.000000 0.000000 -0.000000 1.000000
0.999999 -1.000001 1.000000 0.000000 -0.000000 1.000000
1.000000 1.000000 -1.000000 1.000000 -0.000000 0.000000
1.000000 0.999999 1.000000 1.000000 -0.000000 0.000000
0.999999 -1.000001 1.000000 1.000000 -0.000000 0.000000
1.000000 -1.000000 -1.000000 1.000000 -0.000000 0.000000
1.000000 -1.000000 -1.000000 -0.000000 -1.000000 -0.000000
0.999999 -1.000001 1.000000 -0.000000 -1.000000 -0.000000
-1.000000 -1.000000 1.000000 -0.000000 -1.000000 -0.000000
-1.000000 -1.000000 -1.000000 -0.000000 -1.000000 -0.000000
-1.000000 -1.000000 -1.000000 -1.000000 0.000000 -0.000000
-1.000000 -1.000000 1.000000 -1.000000 0.000000 -0.000000
-1.000000 1.000000 1.000000 -1.000000 0.000000 -0.000000
-1.000000 1.000000 -1.000000 -1.000000 0.000000 -0.000000
1.000000 0.999999 1.000000 0.000000 1.000000 0.000000
1.000000 1.000000 -1.000000 0.000000 1.000000 0.000000
-1.000000 1.000000 -1.000000 0.000000 1.000000 0.000000
-1.000000 1.000000 1.000000 0.000000 1.000000 0.000000
4 0 1 2 3
4 4 5 6 7
4 8 9 10 11
4 12 13 14 15
4 16 17 18 19
4 20 21 22 23
[/B]

The quads are split into the corresponding triangles, and the draw method is GL_TRIANGLES.

Normals are calculated on each triangle before they are passed to the GPU, or use the ones from the file, with no difference.

I have tried both the open ended and "deprecated?" method:

glEnableVertexAttribArray(0); // Vertices on stream 0
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VBO_VNTC), BUFFER_OFFSET(0));
glEnableVertexAttribArray(1); // Normals on stream 1
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VBO_VNTC), BUFFER_OFFSET(4+4+4));
glEnableVertexAttribArray(2); // Texture coordinates on stream 2
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VBO_VNTC), BUFFER_OFFSET(4*3+4*3));
glEnableVertexAttribArray(3); // RGBA color values on stream 3


or


glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(VBO_VNT), BUFFER_OFFSET(0));
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(VBO_VNT), BUFFER_OFFSET(4+4+4));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(VBO_VNT), BUFFER_OFFSET(4*3+4*3));



I use this line to render:

glDrawElements(draw_method,count,preferred_type_en um,BUFFER_OFFSET(0));


It renders the VBO red (a good sign) except it's just not the same cube (features are missing). Face culling on or off makes no difference in the output. What gives?

Over top of this, I also ran through each triangle in immediate mode, transparently adding "green" versions over the "red" VBO render pass.

The output for a cube is garbled on the VBO, yet looks fine on the immediate mode.

Both used GL_TRIANGLES and the same source data.

Alfonse Reinheart
02-26-2012, 07:34 AM
Your data appears to lack either texture coordinates or normals. Showing us a file is meaningless if that's not exactly what you load up into your buffer. Show us the buffer itself.

Also, learn to use [ code ] tags.

OpenGL Developer
02-26-2012, 01:15 PM
TCs are calculated for this test with "poots mapping" -- not that it matters because I'm not providing any texture.

Render segment:


void Render() {
// glDisable(GL_CULL_FACE);
lap.Apply();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef((GLfloat) position.x,(GLfloat) position.y,(GLfloat) position.z);
glRotatef((GLfloat) rotation.x, 1.0, 0.0, 0.0);
glRotatef((GLfloat) rotation.y, 0.0, 0.0, 1.0);
glColor3d(1.0,0.0,0.0);
// lights.On();
vbo.Render();
Blending(transparency);
glColor4d(0.0,1.0,0.0,0.25);
test->model.Render();
// lights.Off();
glPopMatrix();
// glEnable(GL_CULL_FACE);
}


Normals are calculated for this test with the following:


// Given a triangle, calculate the normal. (Windedness matters here.)
Vertex *Vertex::TriNormal( Vertex *a, Vertex *b, Vertex *c ) {
Vertex *normal=new Vertex;
Vertex U; U.Subtract(b,a);
Vertex V; V.Subtract(c,a);
normal->x=(U.y * V.z) - (U.z * V.y);
normal->y=(U.z * V.x) - (U.x * V.z);
normal->z=(U.x * V.y) - (U.y * V.x);
normal->normalize();
return normal;
}


Screenshots of debugger output is attached.
Output from the debugger showing all of the data in the VBO at the time of uploading is in attached as PDF.

OpenGL Developer
03-02-2012, 01:11 AM
Still trying to get this one solved.

OpenGL Developer
03-05-2012, 01:53 PM
This problem was solved when I noted that count did not include the right value. Also, glDrawElements() was used in the render and I switched to glDrawRangeElements()