A replacement for Vertex Attributes

Hello,

I would like your advice on a topic.

!! Warning !! I’m limiting myself to OpenGL 2.1.

Currently my configuration preloads the VBO with geometry, and the vertex shader moves vertices with Vertex Attributes.

The application exposes that as transforming quads. -So in fact when the application moves and rotates a quad, it has to update vertex attributes with 6 times the same value (a pair of triangles, 3 vertices each of course).

While simple, you can see that for large geometry transforms, the poor CPU has to specify the the same value a lot.

What other way can I update the vertex shader other than fine-grain Vertex Attribute changes.

Ideally I would like something to specify a more course-grain. Say, a way to affect 6 vertex shaders with the same attributes.

I’m ruling out:

[ul]
[li]Instancing (geometry can be all different)[/li][li]Uniforms (I want a potentially large number of independently moving objects)[/li][li]VTF (wonky AMD/ATI support, recommends PBO instead)[/li][li]Anything non-core OpenGL 2.1[/li][/ul]

Can anyone suggest to me other approaches?

Thanks,

Cameron

From what I know instancing is available only since GL 3. So you won’t be able to use instancing, except if you plan your hardware to be compliant with GL 3.x or all have some instancing extensions available.

See these extensions for example:

https://www.opengl.org/registry/specs/ARB/instanced_arrays.txt
https://www.opengl.org/registry/specs/ARB/draw_instanced.txt
https://www.opengl.org/registry/specs/ARB/base_instance.txt

For uniforms, I would suggest uniform buffers, but this is since GL 3.1.

With GL 2.1, and if you want to stay with this version, you can also take into account the good old Push/Pop Matrix and use gl_* matrix variables in your shader.

[QUOTE=Silence;1284843]
With GL 2.1, and if you want to stay with this version, you can also take into account the good old Push/Pop Matrix and use gl_* matrix variables in your shader.[/QUOTE]

I don’t know where to begin to implement that.

-Is it reasonable to use a PBO with coordinate transform/translate data from the application, which can be accessed in the vertex shader through a texture sampler?

This would be an OpenGL 2.1 compliant approach that would have AMD’s blessing. Or is that slower than using regular Vertex Attributes?

I know it will probably hurt the vertex shader perf to have to do dynamic look up into the texture holding the geometry info.

Thanks,

Cameron

Fake instancing, i.e. obtain the transformation data from a texture indexed using gl_VertexID/4 (you should be using four vertices per quad and glDrawElements() rather than duplicating two of the vertices).

Texture lookups are likely to be slower than instanced attributes, but if you’re limited to OpenGL 2.1 that’s unavoidable.

I personally don’t know for the PBO. And from what I know texture lookup on the vertex shader might not work on all hardware/drivers. See this for example.

To my opinion, if you don’t have too many different transforms, then I would go for the uniforms/uniform buffers. If you start to have slowdowns due to this, then try instancing. But all of these are not GL 2.1 features.

The “easy” thing would be to do something like this:


SetMVP();

for (all mesh){
   glPushMatrix();
   glRotate(...);
   glTranslate(...);
   glDrawArrays(...);
   glPopMatrix();
}

This is GL 2.1 compliant and does not use any extensions that might not be supported by the aimed hardware.

Ok, an interesting approach, however not something I would do with it at this point.

I will continue to investigate.

I very much appreciate your help. Thank you.

[QUOTE=GClements;1284850]Fake instancing, i.e. obtain the transformation data from a texture indexed using gl_VertexID/4 (you should be using four vertices per quad and glDrawElements() rather than duplicating two of the vertices).

Texture lookups are likely to be slower than instanced attributes, but if you’re limited to OpenGL 2.1 that’s unavoidable.[/QUOTE]

This is what I suspected. I’m just trying to ease the burden on the CPU to somehow avoid respecifying every vertex attribute each frame (where geometry moves, obviously).

I’m praying that the c++ optimiser is looking at all the static arrays i’m modifying and it’s auto-vectorizing the hell out of it.

I’m sad that a non-instanced vertex attribute divisor never made it into 2.1. :frowning:

glVertexAttrib1f
glVertexAttrib2f
glVertexAttrib3f
glVertexAttrib4f

You can use these as well as glVertexAttribPointer calls, set additional attribs with them, set the attrib values only once, and have them persist over multiple shader invocations and shader changes. You’re still limited to the max number of attribs supported by your implementation (typically 16) and of course the attribs are only available to your VS (which I assume from context is not a problem).

[QUOTE=mhagain;1284864]glVertexAttrib1f
glVertexAttrib2f
glVertexAttrib3f
glVertexAttrib4f

You can use these as well as glVertexAttribPointer calls, set additional attribs with them, set the attrib values only once, and have them persist over multiple shader invocations and shader changes. You’re still limited to the max number of attribs supported by your implementation (typically 16) and of course the attribs are only available to your VS (which I assume from context is not a problem).[/QUOTE]

That’s really interesting. I’ve been reading since yesterday to understand how I can utilise that.

What do you mean “persist over multiple shader invocations and shader changes.” ? Documentation says that glVertexAttrib persists across all shader programs, which is good…

-But I’m not clear how glVertexAttrib can provide leverage over my current configuration. -Can you elaborate a little more please?

Thank you very much for your expertise.

Ok, so I think I understand it a little more. So, glVertexAttrib acts in a sort of Uniform-like way.

For me, my setup has the bulk of the draw in typically one or two glDrawArray commands.

glVertexAttrib is very interesting, but I think to utilize it I would need to break my draw commands wide open with a loop that calls glVertexAttrib (dynamically feeding position/rotation/etc) before a glDrawArray, drawing in 6 vertex chunklets.

This would indeed reduce quad position/rotation assignments, but the Draw portion of the configuration would blow up with draw calls.

My thinking is that the CPU is more likely to neutralise my verbose unrolled static array assignments more effectively than the GL driver will be able to ameliorate the massive number of draw calls I would be issuing.

Unless you meant some other approach using glVertexAttrib?