澄清一下,我知道纹理图集在使用多个不同图像时会提高性能。但我感兴趣的是,当你不这样做时,事情是如何完成的。
我尝试在自定义 OpenGL 中手动制作一些逐帧动画,其中每一帧我绑定(bind)一个新纹理并将其绘制在同一个点 Sprite 上。它可以工作,但与 UIImageView 抽象相同的能力相比它非常慢。我预先加载了所有纹理,但重新绑定(bind)是在每一帧完成的。相比之下,UIImageView 接受单个图像,而不是纹理图集,所以我想它的做法类似。
这些是单独加载的 76 张图像,而不是作为纹理图集,每张大约 200 像素见方。在 OpenGL 中,我怀疑瓶颈是需要在每一帧重新绑定(bind)纹理。但是 UIImageView 是如何做到这一点的,因为我预计会有类似的瓶颈? UIImageView 是否以某种方式在幕后创建了一个图集,因此不需要重新绑定(bind)纹理?由于 UIKit 最终在其下运行了 OpenGL,我很好奇它是如何工作的。
如果有更有效的方法来为多个纹理设置动画,而不是在 OpenGL 中每一帧交换不同的绑定(bind)纹理,我想知道,因为它可能暗示苹果正在做什么在他们的框架内。
如果我确实在一秒钟内为 60 帧中的每一帧都获得了一个新帧,那么我的 76 帧动画将花费大约 1.25 秒。事实上,我通过 UIImageView 得到了它,但 OpenGL 大约需要 3 - 4 秒。
最佳答案
我会说你的瓶颈在别的地方。 openGL 更有能力按照您的方式制作动画。由于所有纹理都已加载,并且您只需在每一帧绑定(bind)另一个纹理,因此没有加载时间或其他任何东西。考虑进行比较,我有一个应用程序可以在运行时生成或删除纹理,并且可以在某些时候在 GPU 上加载大量纹理,我必须每帧绑定(bind)所有这些纹理(不是每帧 1 个),使用所有从深度缓冲区、模板、多个 FBO、大量用户输入、大约 5 个线程瓶颈到 1 个线程来处理所有 GL 代码,我在 FPS 方面完全没有问题。
由于您使用的是 iOS,我建议您运行一些分析器来查看哪些代码导致了开销。如果出于某种原因,您的时间分析器会告诉您带有 glBindTexture 的行花费的时间太长,我仍然会说问题出在其他地方。
所以回答你的问题,UIImageView 如此顺利地工作是正常和伟大的,并且使用 openGL 实现相同的性能应该没有问题。不过,此时需要考虑一些事项。你怎么能说 ImageView 不跳过图像,你可能每秒 60 次设置一个指向不同图像的指针,但 ImageView 可能每秒要求自己重绘 30 次,而当它这样做时,它只使用分配的当前图像给它。另一方面,对于您的 GL 代码,您强制应用程序以 60FPS 的速度重绘,而不管它是否能够这样做。
综上所述,苹果开发人员为您创建了一个叫做显示链接的东西。我相信这正是您想要做的。显示链接会告诉您帧之间经过了多少时间,通过该键您应该问问自己要绑定(bind)什么纹理,而不是试图在可能太短的时间范围内强制它们全部。
还有一件事,我已经看到,如果您尝试在大多数 iOS 设备(可能是所有设备)上以 100 FPS 的速度呈现渲染缓冲区,您将只能获得 60 FPS,因为呈现渲染缓冲区的方法将暂停您的线程,如果它在不到 1/60 秒的时间内被调用。也就是说,在 iOS 设备上根本不可能以 60 FPS 显示任何内容,所有运行 30+ FPS 的内容都被认为是好的。
关于ios - UIImageView 是怎么做到动画这么流畅的? (或 : how to get OpenGL to efficiently animate frame by frame textures),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16181411/