iPhone 上的 OpenGL ES 2.0:无法超过小索引/顶点数

Posted

技术标签:

【中文标题】iPhone 上的 OpenGL ES 2.0:无法超过小索引/顶点数【英文标题】:OpenGL ES 2.0 on iPhone: Unable to Exceed Small Index/Vertex Count 【发布时间】:2011-08-31 19:59:24 【问题描述】:

我会尽量保持简短:我在 iPhone 上使用 OpenGL ES 2.0,并且正在利用顶点缓冲区对象一次在屏幕上渲染许多形状。

一系列从零向上的索引用于GL_ELEMENT_ARRAY_BUFFER,它们存储在:

GLushort *ixData;

每个形状都有一个顶点数。创建新形状时,总顶点计数“vxCount”用于为 ixData 重新分配内存:

NSLog(@"allocating ixData for %i shapes, %i vertices",shapes.size(),vxCount);
ixData = (GLushort*)realloc(ixData, vxCount*sizeof(GLushort));

当然,ixData 也有一个初始的 malloc。

每个形状有 6 个顶点属性(2 个位置,4 个颜色),这些都是GLfloat。每个形状总共有 24 个顶点。由于代码是 C++,形状存储在 vector<Shape> 中。 vxCount 的值是通过将此形状向量的大小乘以每个形状的顶点数(即shapes.size()*24)来计算的。

每个形状的位置每帧都会改变,所以我在每次渲染调用 glDrawElements 之前重新提交缓冲区数据:

glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, vxDataSize, vxData, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
NSLog(@"render vxcount is %i",vxCount);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ixDataSize, ixData, GL_STATIC_DRAW); //*

该应用程序适用于不超过 508 的任意数量的形状,包括 508。但是,当我尝试添加第 509 个形状时,我得到一个 EXC_BAD_ACCESS 用于索引缓冲区数据;相关行在上面的代码中带有星号。

上面代码中的 NSLog 打印输出如下所示。如您所见,最新分配的顶点计数与提交原始索引时的计数一致。

...

2011-08-31 20:35:59.438 nibfree[26409:707] 为 503 分配 ixData 形状,12072 个顶点

2011-08-31 20:35:59.441 nibfree[26409:707] 为 504 分配 ixData 形状,12096 个顶点

2011-08-31 20:35:59.444 nibfree[26409:707] 为 505 分配 ixData 形状,12120 个顶点

2011-08-31 20:35:59.448 nibfree[26409:707] 为 506 分配 ixData 形状,12144 个顶点

2011-08-31 20:35:59.451 nibfree[26409:707] 为 507 分配 ixData 形状,12168 个顶点

2011-08-31 20:35:59.454 nibfree[26409:707] 为 508 分配 ixData 形状,12192 个顶点

2011-08-31 20:35:59.457 nibfree[26409:707] 为 509 分配 ixData 形状,12216 个顶点

2011-08-31 20:35:59.746 nibfree[26409:707] 渲染 vxcount 为 12216

~12k个顶点对设备来说应该没问题,索引数据的类型是GLushort意味着0-65535个顶点索引应该是可能的。

我真的被难住了,谁能猜出哪里出了问题?我是否超出了某些特定于 iPhone 的顶点/索引缓冲区限制?

更新

为了增加洞察力,我将形状大小从 24 verts 减半到 12 verts。然后我再次尝试,达到了1536 shapes, 18432 vertices 的限制。如果我尝试添加 1537 个形状,每个形状有 12 个顶点,那么它会像以前一样崩溃,并带有 EXC_BAD_ACCESS

最新测试表明 vxData/ixData 存储不存在问题,顶点或顶点索引的数量也没有限制。可能的形状数量增加了大约 3 倍 - 这是否表明它是我遇到的 GL_TRIANGLES 渲染怪癖?或者可能是对 realloc 的滥用?我真的不确定为什么会出现问题:(

更新 2

发现模式的另一组数字:300 个顶点有最多 61 个形状,62 个导致崩溃。在 62 处有 vxcount 18300,​​最后 ixData 索引 18299 符合预期。

【问题讨论】:

完全不相关的评论:如果您的形状只是移动(并且不会变得更多或更少),您不需要每帧都将索引数据重新复制到缓冲区中。 感谢克里斯蒂安的优化提示,我会记住的 :) 有没有可能ixDataSize 的值不正确,超过vxCount*sizeof(GLushort) @Tommy - 我爱你。我不小心有 vxCount*sizeof(GLuint)。如果您将其复制到答案中,那么我会给您打勾:) 我确实做到了,并进行了有趣的扩展说明。 【参考方案1】:

上传时的 EXC_BAD_ACCESS 可能是由于 GL 驱动程序尝试读取您的应用程序不拥有的内存时引起的。因此,您的ixDataSize 的值很可能大于vxCount*sizeof(GLushort)。使用较小的缓冲区大小可能不会发现这样的问题,因为在这些情况下您提出的ixDataSize 不会在给您的应用程序的区域之外运行,并且因为它大于您实际想要的数字,所以所有您继续使用的数据被复制。

【讨论】:

再次感谢 Tommy ;) 有趣的扩展展览非常愉快。

以上是关于iPhone 上的 OpenGL ES 2.0:无法超过小索引/顶点数的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 成本与收益 - OpenGL ES 1.x 与 2.0

iPad 或 iPhone 是不是支持 OpenGL ES 2.0?

iphone opengl es 2.0,如何使用objective-c类来存储原始数据?

如何在 iPhone OpenGL ES 2.0 中在渲染和呈现帧缓冲区之间切换?

iPhone OpenGL ES 2.0 奇怪的图案在 COLLADA 文件中的球体上渲染纹理

iPhone OpenGL ES 2.0 与 Cocos2D 的混合产生了意想不到的结果