4

人们经常告诉我至少使用顶点数组。但我认为这不是一个好主意,因为我使用glPushMatrix()withglTranslatef/glRotatef在 3d 世界中定位对象。

那么,我是否应该停止使用glPushMatrix()并“手动”计算世界中旋转/移动的顶点位置,然后将它们的顶点数据推送到顶点数组中,然后一次全部渲染?

但是,当我为屏幕上的所有对象使用不同的纹理表面时,所有这些都会变得更加混乱,这些对象也是深度排序的。

所以:

  1. 我还必须使用纹理表面 ID 存储每个对象。
  2. 我会按 Z 位置对所有可见对象进行排序(游戏只能自上而下查看,所有对象都是平面的)。
  3. 我会通过这个排序数组:
  4. 创建新缓冲区并仅将顶点/纹理坐标/颜色/法线复制到此缓冲区中:
  5. 每次纹理表面 ID 从以前的 ID 发生变化时,我都会绑定到正确的纹理 ID:
  6. 上传我收集的顶点数据。
  7. 释放用于临时顶点数组的缓冲区。
  8. 重复步骤 4-7,直到我完成了我首先排序的所有数据。
  9. 释放我的排序数组数据,然后重复步骤 1-9。

我做对了吗?

另外,我应该如何为要排序的对象设计数据结构?例如,std::vector用于存储每个对象的顶点数据是否很好?还是有更好的选择?我在想std::vector存储所有这些数据的方式如下:

struct GameObject {
    int TexID;
    float z; // we will sort by this
    vector<VTCNStruct> VertexData; // store each point of the object here (including color/normal/texcoord points).
};

vector<GameObject> GameObjectBuffer; // push all sortable objects here

另外,在第 4 步:在这种情况下是否可以使用已经存在std::vector的?我有一个想法,我必须使用原始数组,例如new float[100]将顶点数组发送到我的 GPU,或者我可以以std::vector某种方式(有效地)使用我已经存在的排序在这里,而不在每次纹理 ID 更改时创建新缓冲区?

4

2 回答 2

10

请立即放弃 glBegin/glEnd ,它已被弃用并已从 OpenGL-4 中删除。您绝对应该使用顶点数组,如果您使用顶点缓冲区对象会更好。

使用立即模式 (glBegin/glEnd),OpenGL 驱动程序必须从函数调用中构建一个顶点数组。由于不清楚会到达多少顶点,它最终会多次重新分配内存(GPU 直接执行 glBegin/glEnd 之间调用的时间已经过去了)。

使用顶点数组的性能永远不会低于立即模式。可以将多个对象的几何图形放入单个顶点数组中,您可以通过顶点索引列表将它们分开。顶点索引列表也可以存储在缓冲区对象中。

然后在绘制对象之间调整模型视图矩阵。

排序顺序应如下所示:

  1. 分为不透明物体和半透明物体。排序不透明
  2. 按 GL 对象(纹理、着色器、材质等)对 opqaues 进行排序,因为切换 GL 对象是最昂贵的。
  3. 对于每个不同的 GL 对象组,从近到远排序并按该顺序绘制
  4. 将半透明物体从远到近排序并按该顺序绘制

您不应该尝试摆弄缓冲区向上/下载。只需上传一次顶点数据,然后调整索引数组及其提交顺序即可。无需担心可用的 OpenGL 内存,没有强制限制。如果您的数据不适合 GPU RAM,则驱动程序负责将其交换到系统内存 - 这也是您应该首先按 OpenGL 对象排序的原因,因为每次切换 OpenGL 对象(glBindTexture、glBindBuffer 等)时,驱动程序可能需要交换,因此您希望将这些交换操作保持在最低限度。以索引数组的形式发送到 GPU 的数据量至少会比立即模式调用发送的数据量少得多:

  • 索引数组:每个顶点 16 位(16 位大小的索引性能最高)。

  • 立即模式调用:每个顶点 4*32 位

于 2010-12-14T09:57:44.173 回答
2

您应该为每个对象保留一个顶点数组。不要使用 glTranslatef/glRotatef 等。而是自己将变换折叠成一个矩阵。使用该矩阵对对象进行深度排序。然后通过推动对象变换矩阵,绘制顶点数组,然后弹出变换矩阵,从前到后绘制对象。

这种方法意味着您不必不断地创建和释放数组来存储顶点数据。

至于使用 std::vector,大多数实现在内部使用原始 C 数组,因此,您可以执行 &myVec[0] 来获取该数组。但是,不要尝试持久化该指针,因为 std::vector 可能会更改其数组的重新分配,然后您的持久化指针将不再有效。

于 2010-12-13T04:25:11.983 回答