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

问题描述 投票:1回答:1

我读过高低,认为我理解C ++和OpenGL顶点数据布局,但我一定是错的...

我有一个结构来创建一个Line对象。因此它有两个点(每个浮点代表一个向量位置)。它还必须有一个对象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;
};

然后我创建一个简单的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));

然后它在完全不同的坐标处只绘制了一条线!偏移等的不同组合没有帮助。我可以最终使用一个int值,与结构的其余部分不同,只将浮点数传递给OpenGL吗?我真的需要对象的ID,稍后在应用程序中使用它。必须有办法 - 我必须遗漏一些东西......请帮忙。

c++ opengl struct vertex
1个回答
3
投票

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

B1 C1 ID1  B2 C2 ID2  B3 C3 ID3  …

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

我建议放弃Line结构是给定的想法,并且应用程序的每个方面都必须完全使用该确切的数据表示。您必须将数据上传到GPU以便在某些时候绘制。当你这样做时,只需复制起点和终点并跳过id即可。除此之外,考虑一下你也可以通常从你现在拥有的Array of Structures approach(你保持一个Line结构的数组)切换到阵列结构方法,即为所有行起始点设置一个数组,一个对于所有端点,以及一个用于ID。根据您处理数据的准确程度,即使在CPU上也是如此。最后,可以选择将数据上传到Shader Storage Buffer并手动查找顶点着色器中的顶点属性。虽然我不认为我会推荐这样做...

© www.soinside.com 2019 - 2024. All rights reserved.