2

Let's assume I have the following simplified structure in AoSoA format to represent a vertex or point:

struct VertexData
{
    float px[4]; // position x
    float py[4]; // position y
};

That is, each instance of VertexData is storing 4 vertices. Almost all OpenGL examples I've seen use the traditional AoS layout, but that is not an option for me. I can't change the actual structures, and I would also like to avoid converting the data into AoS format before rendering.

So, is it possible to instruct OpenGL to read the vertex data when the data is organized this way, and if so, which GL functions should I look into? The problem as I see it, is to make OpenGL aware of the fact that VertexData.px[i] is paired with VertexData.py[i], and those two values should form a vertex/point.

Clarification 1: In the end, there will be an array of VertexData, for example: std::vector<VertexData>. The size of the std::vector would then be total number of vertices / 4.

Clarification 2: AoSoA = Array of Structure of Arrays.

Update: See How do I draw vertices that are stored in a SSBO? for on how to draw vertices that are stored in a SSBO in AoSoA format.

thomas_f
  • 1,854
  • 19
  • 27

1 Answers1

2

OpenGL's vertex array formats are designed for... arrays of data. Each individual array/buffer binding can have a stride of substantial size. But that stride, the distance from one vertex's data (for that attribute) to the next, is the same for every vertex in the array; that's what makes it an array. Your stride is not constant. Sometimes, it is 4 bytes and sometimes it's 16.

So hardware-based vertex pulling isn't going to be helpful here.

There is one option that will work no matter what you do: programmatic vertex pulling. That is, ignore vertex attribute arrays altogether. Bind your "vertex buffers" as SSBOs to your shader, and use gl_VertexID to fetch whichever data you want. That would look something like this in GLSL:

struct Vertex4
{
    float px[4]; // position x
    float py[4]; // position y
};

layout(std430) readonly buffer VertexData
{
    Vertex4 vertices[];
};

void main()
{
  int dataIx = gl_VertexID / 4;
  int vertexIx = gl_VertexID % 4;
  vec2 my_position = vec2(vertices[dataIx].px[vertexIx], vertices[dataIx].py[vertexIx]);
}

This will be faster than any geometry shader based solution, since GS's basically kill performance.

If you don't have access to SSBOs, because your hardware can't handle them, you can use buffer textures instead.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • I'm going to try what you suggested, but it will take some time as I discovered I have some reading to do before attempting this. I'm still new to OpenGL. – thomas_f Jan 06 '20 at 22:06
  • I think `int main()` should be `void main()`? BTW, I got everything working now, thank you. – thomas_f Jan 07 '20 at 23:16