首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL:如何使用深度排序的顶点数组设计高效的绘制系统?

OpenGL:如何使用深度排序的顶点数组设计高效的绘制系统?
EN

Stack Overflow用户
提问于 2010-12-13 00:19:02
回答 2查看 6.2K关注 0票数 4

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

因此,我是否应该停止使用glPushMatrix(),“手动”计算世界上旋转/移动的顶点位置,然后将它们的顶点数据推入顶点数组,然后一次性呈现?

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

所以:

  1. I也必须用纹理面ID存储每个对象。
  2. i将根据所有可见对象的Z位置对它们进行排序(游戏仅自顶向下查看,所有对象都是平面的)。
  3. I将遍历这个排序数组:
  4. 创建新缓冲区,并在纹理面ID与以前的ID发生变化时只将顶点/texcoord/color/normal复制到此
  5. 中。我将绑定到正确的纹理ID: collected.
  6. Free
  7. 将顶点数据上传到临时顶点array.
  8. Repeat步骤4-7所使用的缓冲区,直到我首先检查了我排序的所有数据。
  9. 释放了已排序的数组数据,并重复步骤1-9.

我做得对吗?

此外,我应该如何为我将要排序的对象设计数据结构?例如,使用std::vector存储每个对象的顶点数据好吗?还是有更好的选择?我认为存储所有这些数据的std::vector看起来是这样的:

代码语言:javascript
复制
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更改时创建新的缓冲区?

EN

回答 2

Stack Overflow用户

发布于 2010-12-14 09:57:44

请放弃glBegin/glEnd 现在,它已被废弃,并已从OpenGL-4中删除。您肯定应该使用顶点数组,如果使用顶点缓冲区对象则更好。

使用即时模式(glBegin/glEnd),OpenGL驱动程序必须从函数调用构建一个顶点数组。由于还不清楚会出现多少个版本,它最终会多次重新分配内存(GPU直接执行glBegin/glEnd之间调用的时间很长)。

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

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

排序顺序应如下所示:

  1. 分为不透明的和半透明的对象。对不透明的
  2. 进行排序,根据GL对象(纹理、阴影、材料等)对opqaues进行排序。由于切换GL对象是最昂贵的。
  3. 对每个不同的GL对象组进行近到远排序,并按该顺序绘制
  4. 排序的半透明,并按

的顺序绘制。

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

performant).

  • 索引数组: 16位/顶点(16位大小索引是大多数
  • )

  • 即时模式调用:每个顶点

4*32位

票数 10
EN

Stack Overflow用户

发布于 2010-12-13 04:25:11

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

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

至于使用std::vector,大多数实现都在内部使用一个原始C数组,因此,您可以做&myVec来访问该数组。但是,不要试图持久化该指针,因为std::vector可以更改它的数组,这样持久化指针就不再有效。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4424936

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档