PDA

View Full Version : glDrawElements/glArrayElement with VBO's



VCarnage
11-03-2006, 09:44 AM
Hi,

I am having some confusion with glDrawElements and glArrayElement while using VBO's.

Is it correct to assume that these two code snippets should display the same thing?


glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBufferID);
glDrawElements(GL_TRIANGLES, numIndices, glEnumType, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBufferID);
glBegin(GL_TRIANGLES);
for(int i=0;i<numIndices;i++)
glArrayElement(i);
glEnd();With glDrawElements, everything is rendered correctly. For some reason, when I use glArrayElement, I see models rendered with missing triangles.
Aren't the two code snippets supposed to look the same when rendered?

Thanks

VCarnage
11-03-2006, 10:32 AM
Ok. I just realized that array index buffer objects are only useful for glDrawElements and glDrawRangeElements, not glArrayElement.

Korval
11-03-2006, 10:46 AM
FYI: never use glArrayElement with VBOs. It's bad.

VCarnage
11-03-2006, 11:51 AM
My problem is that I want to send each vertex in my indexed VBO twice and use a vertex shader to adjust the second (but same) vertex so that the position is now different. In order to "know" that it is the second submission of that same vertex, i need to pass a flag thru a vertex attrib. I can't think of any other way to do this but to separate out the vertices with glArrayElement and call glVertexAttrib per vertex alternating 0 for first submission and 1 for second submission.

Does anyone have any better ideas?

Korval
11-03-2006, 01:35 PM
My problem is that I want to send each vertex in my indexed VBO twice and use a vertex shader to adjust the second (but same) vertex so that the position is now different. In order to "know" that it is the second submission of that same vertex, i need to pass a flag thru a vertex attrib.No one ever said you had to use a vertex attribute. You could just use a shader uniform. In fact, this is exactly the kind of thing they're used for. At least, until OpenGL gets instancing support.

Alternatively, though the performance with this method is unknown, you can call glDrawElements once, call glVertexAttrib, then call glDrawElements again. If an array (or buffer object) is not bound to an attribute, then that attribute will remain constant throughout the call.

There have been some IHV suggestions that this should be OK performance-wise.

VCarnage
11-03-2006, 01:54 PM
That would draw the whole vertex array/vbo twice, once with vertexattrib 0 and then again with vertexattrib 1. That's not what I was thinking of. I need to explain it better. Let me try...

The VBO is originally a Triangle list. I want to turn each line/side of the triangle list into a GL_QUAD.
For example, if Vertex0,Vertex1,Vertex2 originally formed a triangle, I want to

First submit Vertex0 with attrib 0.
Then submit Vertex0 with attrib 1.
Then submit Vertex1 with attrib 1.
Then submit Vertex1 with attrib 0.
(end of first quad)
Then submit Vertex1 with attrib 0.
Then submit Vertex1 with attrib 1.
Then submit Vertex2 with attrib 1.
Then submit Vertex2 with attrib 0.
(end of second quad)
Then submit Vertex2 with attrib 0.
Then submit Vertex2 with attrib 1.
Then submit Vertex0 with attrib 1.
Then submit Vertex0 with attrib 0.
(end of third quad)

In the shader, based on which attrib 0 or 1, I would transform the vertex differently.

I'm not sure of the best way to do this.

Korval
11-03-2006, 03:27 PM
Just take up the extra memory and turn them into a list of GL_QUADs. You're not buying anything by doing what you're doing, and you're burning performance by:

1: Not using glDrawElements
2: Setting attributes in the middle of a draw call
3: Complicating your shader processing.

tamlin
11-03-2006, 04:18 PM
"First submit Vertex0 with attrib 0.
Then submit Vertex0 with attrib 1.
Then submit Vertex1 with attrib 1.
Then submit Vertex1 with attrib 0.
(end of first quad)"

That's no quad. That's a line, with interleaved overdraw.

Perhaps I missed something...

Dark Photon
11-03-2006, 05:00 PM
Korval:
At least, until OpenGL gets instancing support.It may be here now. NVX_instanced_arrays is reported by NVidia's 1.0-9640 drivers (shipped with NVPerfSDK 2.1). Haven't used it yet though.

VCarnage
11-05-2006, 01:35 PM
I guess I will just have to store the same vertex data multiple times to do this. I was just hoping that there would be a better way to do this, memory and performance wise.

Thanks a lot for your suggestions.
-VC

Dark Photon
11-06-2006, 05:14 AM
VCarnage:
I guess I will just have to store the same vertex data multiple times to do this.That's what NVX_instanced_arrays (and the associated GPU vertex stream frequency dividers) are designed to avoid.


I was just hoping that there would be a better way to do this, memory and performance wise.

VCarnage
11-06-2006, 09:31 AM
Dark Photon, NVX_instanced_arrays appear to be for changing attribs per object, not per vertex.
What I'm looking for is a bit different from instancing I think.

Korval is probably right that the best way to do this is just to use the extra memory.

Dark Photon
11-06-2006, 02:42 PM
VCarnage:
Dark Photon, NVX_instanced_arrays appear to be for changing attribs per object, not per vertex.
What I'm looking for is a bit different from instancing I think.Actually, I think it's just what you want. Check out pg. 35 here (http://download.nvidia.com/developer/presentations/2006/gdc/2006-GDC_OpenGL_NV_exts.pdf) .

In your example above:

First submit Vertex0 with attrib 0.
Then submit Vertex0 with attrib 1.
Then submit Vertex1 with attrib 1.
Then submit Vertex1 with attrib 0.

with positions only, you'd set up two vertex attribute arrays. Attr 0 with your vertex positions (not repeated), and Attr 1 exactly four elements long containing "0", "1", "1", "0".

Then you'd set the vertex stream frequency divider for Attr 0 to step every other vertex, and the divider for Attr 1 to step every vertex. You get what you have above, without repeating input values.

The whole point of this extension is to render bunches of things like particle systems in one batch without repeating input values that are the same across an instance but different "between" instances (e.g. MODELVIEW transform, color, etc.). Your example fits the template.

That's my understanding at least. Hopefully if I'm way off base, and NVidia person will add their two cents.

zeoverlord
11-07-2006, 07:29 AM
hmm.. i don't know, not with the current configuration since it does not allow for fractional divisor.

I do have an suggestion though on how to solve this if NVIDIA is interested.
It's simple, the divisor part of VertexAttribDivisorNVX is normally 0=off, 1=one step for every reiteration, 2=two steps for every reiteration (and if i might add totally useless).
My suggestion is simple and it will solve some other problems with it as well.
0=one step for every reiteration.
1=off or normal operation (advance once for every vertex).
2=advance once for every other vertex.
3=advance once for every third vertex.
and so on.

What do you guys think?

VCarnage
11-07-2006, 09:54 AM
Dark Photon:
Then you'd set the vertex stream frequency divider for Attr 0 to step every other vertex, and the divider for Attr 1 to step every vertex. You get what you have above, without repeating input values.From my understanding, it seems that divisor is set per object/primitive like GL_TRIANGLE, not per vertex. So I guess that's what zeoverlord is saying, that the current extension does not allow for fractional divisors which would let you advance attribs per vertex.

zeoverlord:
I think your idea is good. Vertex control would be easier to deal with than fractional divisors in my opinion.

However, I don't think this extension will help with what my original problem was. I still think Korval was right that I should just make the new geometry. I have gotten it working using glArrayElement and mapping the vbo. But I know this is probably the worse implementation performance-wise.

Dark Photon
11-09-2006, 05:55 AM
Scratch all that talk on NVX_instanced_arrays. EXT_draw_instanced / EXT_bindable_uniform deprecates it (no wonder the NVidia folks were so quiet ;-)

NVidia G80 OpenGL Extension Specs (http://developer.download.nvidia.com/opengl/specs/g80specs.pdf)

Korval
11-09-2006, 10:36 AM
EXT_bindable_uniformActually bindable uniform doesn't really help with this particular issue. It's useful, but only for more rapidly updating uniforms. Not for changing them mid-primative.

Dark Photon
11-10-2006, 03:30 AM
Korval:
Actually bindable uniform doesn't really help with this particular issue. It's useful, but only for more rapidly updating uniforms. Not for changing them mid-primative. I was thinking about storing per-instance data in bindable uniform arrays, where the index would be gl_InstanceID, but I see now that they've excluded dynamically-sized uniform arrays.

So I suppose you need to store per-instance data in a texture and use vertex texture fetch to get at it.