顶点缓冲区中的多种数据类型 (openGL)

Multiple datatypes within a vertex buffer (openGL)

我正在研究 openGL 并正在尝试编写一个基本程序。我要么误解了什么,要么根本找不到我要找的答案。

我正在尝试将(多种数据类型的)数据添加到顶点缓冲区。我不知道这是否是不好的做法。但我认为将 int 用于我的一些数据而不是 float 用于所有数据会节省很多 space。

是否可以将多种数据类型添加到单个顶点缓冲区中?如果是这样,如何?有这方面的最佳实践吗?

我知道如何使用 glVertexAttribPoint 定义每个属性,但我如何使用 glBufferSubData 添加数据?现在,我的问题是 glBufferSubData 需要一个数组,我相信数组只能有 1 种数据类型。

回避你的实际问题:

But I figured it would save a lot of space using int for some of my data instead of floats for everything.

不,你没有保存任何东西。 sizeof(int) == sizeof(float) 在您将要关注的所有平台上。

无论如何,您可以在一个缓冲区对象中完美地混合多种数据类型,这里的关键是 glVertexAttribPointer 的 stride 参数。这通常称为“结构数组”。以下 (C) 完全没问题:

struct foo {
    GLfloat a[2];
    GLbyte b[3];
};

enum { N = 10 };

foo arr[N];

glBufferData(GL_ARRAY_BUFFER, N*sizeof(foo), arr, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(foo), (void*)offsetof(foo, a));
glVertexAttribPointer(0, 3, GL_BYTE,  GL_FALSE, sizeof(foo), (void*)offsetof(foo, b));

现在有一些关于“结构数组”的重要知识:它们通常比“数组结构”效率低,原因有二:

  • 结构元素必须自对齐;根据结构内部的内容,要求可能会强制使用填充字节,即使用更多 space

  • 如果只需要结构中的一部分元素,由于内存提取在 GPU 上的工作方式,很多正在加载的数据将被丢弃。在 GPU 上,通常会获取连续的内存片段,由于大多数图形操作的局部性较高,因此通常可以很好地缓存。

在 Nvidia 的这个应用说明中,他们将其称为“流”而不是“数组”。

https://developer.nvidia.com/gpugems/gpugems2/part-iv-general-purpose-computation-gpus-primer/chapter-33-implementing-efficient