我写了一个快速的应用程序,以了解RenderScript的限制,并发现当达到大约65,000个三角形时,系统根本不会绘制任何其他三角形。例如,如果我创建一个具有70,000个三角形的圆柱体,则圆柱体上缺少对应于超过~65,000计数的三角形的楔形。三角形是纹理化的,为了便于编写应用程序,我只使用了TriangleMeshBuilder
类,因此没有真正的优化,例如使用trifans或tristrips。硬件是三星Galaxy Nexus。 LogCat报告堆大小约为15MB,可用3%。我没有收到有关图形系统或RenderScript的错误或警告。
任何人都可以解释掉落三角形的原因吗?我是否处于RenderScript优雅处理的硬件限制?
更新适用于三星Galaxy Nexus(4.0.3),三星Galaxy Tab 7.0+(3.2)和摩托罗拉Xoom(3.2)。所有在大约65,000个三角形的同一点。每个设备都有不同的GPU。
更新2 为了回应Steve Blackwell的见解,我还有一些额外的想法。
第710-712行确实将int
索引向下转换为short
,因此当史蒂夫指出时,65536变为0。此外,第757行的“强制转换”并不是告诉RenderScript最终将发送给它的二进制数据的格式。 RenderScript要求将所有数据打包到名为Allocation
的RenderScript特定数据类型中,以便从Java移动到RenderScript运行时,并且需要了解数据结构。根据Steve的观点,这是一个错误,第757行告知RenderScript将索引数据视为short
(无符号16位),但它发送一个32位有符号值(由于缺少一个,它将被接受)检查和处理无符号,然后只使用低16位,这就是为什么我们得到的东西低于这个阈值时,三角形连接回第一个索引,当我们结束时。)
对TriangleMeshBuilder
进行子类化以查看是否可以使其接受这些值全部作为整数来增加此限制不起作用,这使我相信在我们无法访问的深层代码中的某处,有对无符号短裤的额外参考。看起来唯一的解决方法是添加额外的顶点缓冲区,正如史蒂夫建议的那样,这可以通过现有的Mesh.AllocationBuilder
类轻松完成。我还会在开发人员环聊中与谷歌联系,以确定这实际上是错误还是故意。
答案 0 :(得分:3)
我对RenderScript几乎一无所知,所以我不知道这是一些固有的限制,硬件问题,还是与TriangleMeshBuilder有关,但我敢打赌你在数字65535之后用完了三角形。
这是一个神奇的数字,因为它是无符号16位整数的最大值。 (Wikipedia)
我怀疑代码中的某处有一个unsigned short
,它包含三角形的数量。它不在Java代码中,因为Java没有无符号值。并且限制可能不是硬件,因为CPU寄存器/路径是> = 32位。所以我会检查TriangleMeshBuilder。
修改强>
这是line 553的绝佳发现。每个索引的值必须符合short
。这看起来像是在line 710-712发生的。
我假设您正在呼叫addTriangle()
。该函数需要三个int
,然后对short
进行显式转换。我认为那是一个错误,因为沮丧地发生了,并且它不是你对函数签名的期望。
在line 768上,虚假数据传递给Allocation.copy1DRangeFromUnchecked()
。我没有完全遵循它,但我想在某些时候,那些签名的值会被转换为无符号:-32768到-1会变回32768到65535.因此将指数转换为负数看起来很糟糕,但它只是重新解释相同的数据而且并不是真正的问题。
当您发送65536之类的值时,真正的问题就开始了。当65536转换为short
时,它变为0.这是一个真正的数据丢失。现在你指的是不同的索引,而对无符号的强制转换并不能解决它。
真正的踢球者是copy1DRangeFromUnchecked()
是一个重载函数,而overloads takes an int[]
之一,所以这一切都不需要成为一个问题。
对于变通方法,我猜你可以继承TriangleMeshBuilder
并覆盖成员变量mIndexData[]
和方法addTriangle()
。或者也许你可以使用多个顶点缓冲区。或者在某处提交错误报告?无论如何,有趣的问题。
答案 1 :(得分:1)
这可能是因为OpenGL ES仅允许short
个元素索引,而不是int
。来源:http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-2.1:-Buffers-and-Textures.html(搜索“OpenGL ES”)