英文:
OpenGL and loading/reading data in AoSoA (hybrid SoA) format
问题
让我们假设我有以下简化的AoSoA格式结构来表示一个顶点或点:
struct VertexData
{
float px[4]; // 位置 x
float py[4]; // 位置 y
};
也就是说,每个VertexData
实例存储4个顶点。我看到的几乎所有OpenGL示例都使用传统的AoS布局,但这对我来说不是一个选项。我不能改变实际的结构,而且我也想避免在渲染之前将数据转换为AoS格式。
那么,是否可能指示OpenGL在数据组织成这种方式时读取顶点数据,如果可以,我应该查找哪些GL函数?我看到的问题是让OpenGL意识到VertexData.px[i]
与VertexData.py[i]
是成对的,这两个值应该组成一个顶点/点。
澄清 1:最终将会有一个VertexData
数组,例如:std::vector<VertexData>
。std::vector
的大小将是总顶点数 / 4
。
澄清 2:AoSoA = 结构体数组的数组。
更新:请参阅https://stackoverflow.com/questions/59637006/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.
英文:
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 https://stackoverflow.com/questions/59637006/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.
答案1
得分: 2
OpenGL的顶点数组格式是为了...数据数组而设计的。每个单独的数组/缓冲绑定可以有相当大的步幅。但是,步幅,从一个顶点的数据(对于该属性)到下一个的距离,在数组中的每个顶点都是相同的;这就是使它成为数组的原因。您的步幅不是常数。有时它是4个字节,有时它是16个字节。
因此,基于硬件的顶点提取在这里不会有帮助。
有一种选项无论您做什么都会起作用:编程式顶点提取。也就是说,完全忽略顶点属性数组。将您的"顶点缓冲"绑定为SSBOs到您的着色器,并使用gl_VertexID
来获取您想要的任何数据。在GLSL中,它会看起来像这样:
struct Vertex4
{
float px[4]; // 位置 x
float py[4]; // 位置 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]);
}
这比任何基于几何着色器的解决方案都要快,因为几何着色器基本上会降低性能。
如果您无法访问SSBOs,因为您的硬件无法处理它们,您可以使用缓冲纹理来代替。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论