ios - 如何在 iOS/OpenGL ES 2.0 中批处理 Sprite

标签 ios opengl-es-2.0 sprite

我在 OpenGL ES 2.0 之上开发了自己的 Sprite 库。现在,我没有做任何绘制调用的批处理;相反,每个 Sprite 都有自己的四个纹理顶点的 VBO/VAO,绘制为三角形带(VAO/VBO 本身由纹理图集管理,因此相同的 Sprite 重用相同的 VAO/VBO,这是“引用计数”和因此在没有 Sprite 实例引用它时删除)。

在绘制每个 Sprite 之前,我会绑定(bind)它的纹理,将它的制服/属性上传到着色器(模型 View 矩阵,不透明度 - 投影矩阵始终保持不变),绑定(bind)它的顶点数组对象(4 个纹理顶点 + 四个索引) ,并调用 glDrawElements()。我确实剔除了屏幕外的 Sprite (基于位置和边界),但它仍然是每个 Sprite 一个绘制调用,即使所有 Sprite 共享相同的纹理。每个 Sprite 的顶点位置和纹理坐标永远不会改变。

我必须说,尽管效率低下,但我从未遇到过性能问题,即使在屏幕上绘制许多 Sprite 时也是如此。我确实将 Sprite 分成不透明/非不透明,先绘制不透明的,然后绘制非不透明的,从后往前。我看到只有在 overdraw (对填充率征税)时性能才会受到影响。

然而,Xcode 中的 OpenGL 工具会提示我绘制了太多小网格,我应该将我的几何体合并为更少的对象。在 Unity 世界中,每个人都在谈论限制绘制调用的数量,就好像它们是瘟疫一样。

那么,我应该如何将许多 Sprite (每个 Sprite 具有不同的变换和不透明度值(但纹理相同))批处理到一个绘制调用中?想到的一件事是修改每一帧的顶点数据,并将其流式传输:将每个 Sprite 的模型 View 矩阵应用于其所有顶点,将所有 Sprite 的变换顶点组装到一个网格中,并将其提交给 GPU。这种方法不能解决 Sprite 之间不透明度变化的问题。

我想到的另一个想法是将所有 Sprite 的所有纹理顶点组装到一个网格 (VBO) 中,将其视为“静态”(我现在使用的顶点格式相同),以及一个单独的数组每帧每个 Sprite 都会改变的东西(变换矩阵和不透明度),并且每帧只流式传输那个数据,并将它拉/应用到顶点着色器端。也就是说,有一个单独的数组,其中表示的“属性”是相应顶点的模型 View 矩阵/alpha。仍然需要根据数据格式/步幅等找出确切的实现方式。无论如何,每当创建/销毁新 Sprite 时都会出现额外的复杂情况,必须修改整个网格...

或者也许有一个理想的、“教科书式”的解决方案来解决这个问题,但我还没有想出来? cocos2d是做什么的?

最佳答案

当我最初开始阅读您的帖子时,我虽然每个四边形使用不同的纹理(因为您说“在绘制每个 Sprite 之前,我将绑定(bind)它的纹理”)但是后来您说每个 Sprite 都具有“相同的纹理” .

一个可能的轻松胜利是在绘制期间控制您绑定(bind)纹理的方式,因为每次调用都是 OpenGL 驱动程序的负担。如果(而且我不太确定你的帖子中的这一点)你使用不同的纹理,我建议使用一个简单的纹理图集,其中所有的 Sprite 都在一张图片中(最好是 2 的幂纹理和 mipmapping),然后你使用纹理坐标在片段中获取您需要的纹理(这就是它们最终存在的原因)

如果 Sprite 的位置在每一帧随时间变化(当然会发生变化),一个可能的优势是在每一帧打包 Sprite 的新顶点坐标并直接从内存中绘制(可能通过 VAO.VBO可能会花费更多,因为您需要在每一帧中构建它?在真实场景中进行测试)。这将是一个很好的调用包操作,我很确定它会破坏性能。

考虑到 VAO 选项可能是可行的,因为我们正在谈论非常少量的数据,内存带宽不应该代表真正的瓶颈(我猜每个四边形使用 12 个 float 用于顶点坐标,8 个用于纹理,12 个用于法线, 128 字节?),这对 VAO 来说应该不是什么大问题。

关于不透明度,您不能在使用 alpha 的片段着色器中使用制服吗?我错了吗?它应该有效。

希望对您有所帮助。

再见, 毛里齐奥

关于ios - 如何在 iOS/OpenGL ES 2.0 中批处理 Sprite ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22828516/

相关文章:

ios - iOS 8 中带有 native 预测的自定义键盘

ios - 如何使用json和swift 4.1在Google map 上添加多个标记?

c++ - 将 glTexImage2D 保存到文件系统以供检查

opengl-es-2.0 - opengl纹理映射偏离5-8像素

css - compass - 从 Sprite 位置获取个人编号

ios - 如何从 UICollectionView 单元格引用选项卡栏 Controller

ios - 如何更改 "Camera and Photo Library Permission"描述?

opengl-es - OpenGL ES 2.x : Bind both `GL_TEXTURE_2D` and `GL_TEXTURE_CUBE_MAP` in the same texture image unit?

ios - 如何在 SKAction 中途反转 Sprite 所遵循的路径方向?

c++ - 为什么该代码不绘制 Sprite C++ SFML