"Region" attributes in a VBO

How can I replicate “flat” attributes in a VBO without duplicating the attributes on each vertex of a very complicated, multi-surfaced mesh? For example, when I create a display list, I only need one normal for flat surfaces but unique normals for curved surfaces. Similarly if the surfaces have unique colors, I don’t want to duplicate those either and those are “flat” for the curved surfaces as well. Displaying each surface/face of the mesh individually is too slow because there are hundreds or even thousands of various surfaces in a single mesh. Also note that the flat faces are not all orthogonal. Duplicating these (and other) flat attributes (even using texture lookups) will add megabytes to the mesh so I’m looking for a more elegant solution.

To understand the complexity of the planar surfaces I’m talking about, envision a thin metal plate with a grid of 10’s, 100’s, or 1000’s of holes punched through it. If there are 10,000 vertices for one side of the plate, a single short vertex attribute requires 20,000 bytes but a single flat attribute only takes 2 bytes (excluding any extraneous overhead). Now imagine 1000’s of similar but unique meshes in the full scene. Faking the result is not a solution because precision is an absolute requirement.

Also be aware that the memory overhead in the display list (relative to process virtual bytes) of the single attribute is the single attribute - it is not duplicated by the driver into any detectable internal VBO.

T

You don’t. Well, not without using shader logic to fetch values from a buffer. That’s generally done by using a pair of buffer textures (one for the per-vertex index, and one for the actual value). Of course, you give up a lot of the ability for you to shrink the individual attribute data. But considering your circumstances, that’s probably acceptable.

Also be aware that the memory overhead in the display list (relative to process virtual bytes) of the single attribute is the single attribute - it is not duplicated by the driver into any detectable internal VBO.

Don’t forget: what happens in display lists is implementation-defined. You can rely on this behavior only so long as you’re relying on a single implementation. Once you take it somewhere else, all bets are off.

That’s about what I had concluded. I would not classify this as “acceptable” – “unavoidable” might be more appropriate – “disappointed” is more like it. I have been able to feed this type of compact data to shaders via display lists, but I’m limited to early versions of GLSL. I can’t imagine that three lookups will ever be as fast as one (one per-vertex lookup, one per-region lookup, and one actual data). Not to mention having to manage three sets of data instead of one.

As for memory footprints of display lists go, there’s really only three major players and I know how they all behave. Virtual memory placement of VBO’s is actually less predictable by those very same players.

T

If a value doesn’t change for a mesh, then that value is called a uniform in the GLSL language, not an attribute.
Example, if the normal is the same, then you declare a “uniform vec3 normal” in your GLSL.

If there are multi meshes with various such uniforms, then you create various shaders for them.

Of course, doing it with a texel fetch + attribute inside your VS is another solution.

As for memory footprints of display lists go, there’s really only three major players and I know how they all behave

How do they behave?

I have been able to feed this type of compact data to shaders via display lists, but I’m limited to early versions of GLSL.

Why? Unless you need your code to work on MacOSX 10.7’s OpenGL 3.2 implementation, you can pretty much assume that compatibility contexts will be available. Thus far, none of the major vendors have said or implied any intent to drop support for compatibility, and the ARB keeps producing compatibility specifications every time they drop a new core.

The value actually does change for the mesh, only at a different frequency than that of the vertices. For example a single mesh containing a cube has 8 positions and 6 normals – a display list only needs to call glNormal3f six times for the 24 unique vertices while a VBO has to expand this to 24 normals (4x as much data) or have an index into another object.

Considering that just one of my meshes can contain 10,000 faces and 200,000 triangles and I may have thousands of meshes in the scene, I definitely don’t want different shaders for each uniform. Some form of lookup may work, but it’s still going to be slower.

Predictably.

I understand about the compatibility support. My point is that if I specify any version beyond 120, I can’t feed data to the shader from a display list:

error C7533: global variable gl_Normal is deprecated after version 120 (etc...)

GLSL’s definition of deprecated means “unavailable”. While I can write version 120 compatible shaders to do what I need to do, it would be nice to be able to use features from 130 and beyond (e.g., native integer support, etc.) without having to scrap my data format. But if I have to do that, I have to be smart about managing my customer’s resources.

T

GLSL’s definition of deprecated means “unavailable”.

If you’re in a compatibility profile, all you need to do is have your shader state that it’s a compatibility shader:


#version 330 compatibility

Also, you don’t have to use old-style vertex attributes with display lists. You can use glVertexAttrib to send generic attributes to the shader with display lists.

“error C7533: global variable gl_Normal is deprecated after version 120 (etc…)”

That just means that they are suggesting that you use glVertexAttrib or glVertexAttribPointer instead of the classical glNormal and glNormalPointer.

Somehow I missed how the #version statement worked – core vs. compatibility.

This is somewhat encouraging … MultiTexCoords are sufficient for the time being.

Thanks for the pointer!

T