如何使用混合类型的 c++ 结构并只将一些值传递给 OpenGL?

How do I use a mixed type c++ struct and only pass some values to OpenGL?

我读了很多书,认为我了解 C++ 和 OpenGL 顶点数据布局,但我一定是哪里错了...

我有一个用于创建 Line 对象的结构。因此它有两个点(每个 3 个浮点数代表一个向量位置)。它还必须有一个对象 ID,以便我可以在稍后的应用程序中跟踪创建碰撞等的特定对象。该结构如下所示。

struct Point
{
    Vector position = { 0.0f, 0.0f, 0.0f };
};

struct Line
{
    Point B = { 0.0f,0.0f,0.0f };
    Point C = { 0.0f,0.0f,0.0f };
    int ID = 0;
};

然后我创建了一个 simpe c++ STL 线向量并推回两个线对象:

vector<Line> lines; 

Line w0;
    w0.B = { 2.0f,2.0f, 0.0f };
    w0.C = { 8.0f,2.0f, 0.0f }; 
    w0.ID = 0; 
    lines.push_back(w0);

Line w1;
    w1.B = { 10.0f,4.0f, 0.0f };
    w1.C = { 18.0f,4.0f, 0.0f };
    w1.ID = 1;
    lines.push_back(w1);

我进一步指定 glVertexAttribPointer 如下:

glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 0, (void*)(0));
glEnableVertexAttribArray(4);

这只绘制了 1 条线,而不是我为 (!) 创建的两个对象。 如果我从我的结构中删除 ID int 变量,我会正确显示两行。 后来发现可能是我没有正确指定glVertexAttribPointer,所以顺理成章地改成如下:

glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Line), (void*)offsetof(Line, B));

然后它只在完全不同的坐标处画了1条线!偏移等的不同组合没有帮助。我最终能否使用一个与结构的其余部分不同的 int 值,并仅将浮点数传递给 OpenGL?我确实需要对象的 ID 并稍后在应用程序中使用它。一定有办法-我一定是遗漏了什么……请帮忙。

仅仅因为您需要在应用程序中以某种方式表示线条并不意味着您必须以完全相同的方式将该数据准确地提供给 OpenGL 进行绘图。 OpenGL 不需要此 ID 字段。似乎没有理由将此 ID 数据上传到 GPU。除此之外,没有办法让 OpenGL 顶点属性数组使用像 Line 结构数组那样的内存布局。想想多个Line在内存中是什么样子的:

B1 C1 ID1  B2 C2 ID2  B3 C3 ID3  …

注意连续顶点位置之间的间隙是如何不固定的,而是在同一线段的两个点之间为 0,或者在一条线的结束顶点和下一条线的起始顶点之间为 sizeof(int)。没有办法只用步长和基本偏移量来描述这样的顶点属性数组。所有这一切都忽略了一个事实,即编译器可以自由地以他们认为合适的任何方式在结构成员之间添加填充字节。因此,您的内存布局甚至不能保证看起来像那样,并且至少在理论上可能会根据您使用的编译器版本和编译选项而有所变化。

我建议放弃这样的想法,即 Line 结构是给定的,应用程序的每个方面都必须绝对使用该确切的数据表示。无论如何,您必须在某个时候将数据上传到 GPU 进行绘图。当你这样做时,只需复制起点和终点并跳过 id。除此之外,请考虑这样一个事实,即您通常也可以从 Array of Structures approach you have now (where you keep an array of Line structures) to a Structure of Arrays approach, i.e., have one array for all the line start points, one for all the end points, and one for the IDs. Depending on how exactly you process your data, this is often beneficial even on the CPU. Finally, there would be the option to upload the data to a Shader Storage Buffer 切换并手动查找顶点着色器中的顶点属性。我不认为我会推荐在这里走那条路......