我有一个EAGLView
,我正在动画中调整其大小,动画由调用绘图函数的NSTimer
驱动。当我调整EAGLView
的大小时,我需要调整视图的投影,以保持内容的纵横比。draw函数如下所示:
gameView.frame = newFrame;
[gameView setFramebuffer];
[self updateProjection];
/* Drawing to the EAGLView, gameView, here, then... */
[gameView presentFramebuffer];
不过,这样运行时,EAGLView的内容会显示为动画的"阶梯"。当我记录它并逐帧查看时,很明显投影已经调整,然后在很短的时间后(不到一个动画帧)调整视图的大小。
我怀疑原因是gameView
帧的更改被推迟了,同时更新的帧缓冲区正在进入屏幕。我曾尝试使用CATransactions
使帧更新立即生效,但正如我所期望的UIView更改一样,这没有起到任何作用。我想我可以修改视口并保留EAGLView
完整帧,但我担心这可能会在其他地方留下同步问题(例如,更新任何覆盖的CALayer)。
这似乎是对问题的合理评估吗?我如何防止它——也就是说,我如何最好地确保帧缓冲区表示与EAGLView(和其他CA元素)的实际帧中的更改一致?
谢谢!
我在编写自定义EAGLView
时遇到了类似的问题。问题是,当更改方向时,视图会被调整大小,内容也会被拉伸,只有在动画之后,才会显示具有正确比例的场景。
我认为你的问题也是一样,我不认为你可以强迫CoreAnimation在渲染动画帧之前等待视图更新,因为它的工作方式(CA不知道视图或操作层的绘制机制)。
但您可以轻松绕过这个问题:打开包含视图的xib文件,切换到右侧的属性检查器。选择EAGLView
(与GLKView
相同),在View部分下有Mode属性。如果以编程方式创建视图,请设置contentMode
属性。
该值描述了在动画过程中如何管理视图内容。在显示缓冲区之前,旧场景将根据该模式调整大小;也许你可以找到一种适合你需要实现的动画的模式。
-
如果您担心比例问题,中心内容模式可能会起作用,但尚未渲染的场景部分将在动画过程中显示为空。
-
不幸的是,重绘模式不一定会刷新
EAGLView
:视图实际上是重绘的,但可能会使用颜色缓冲区的旧内容。这是一个在正确的时间填充缓冲区的问题。 -
在开始之前,你可以尝试调整大小并预先渲染一个足够大的帧,以覆盖整个动画;或者,您可以尝试将帧渲染为
UIImage
,动态替换视图,设置其动画,将EAGLView
放回原处,但这可能会严重影响性能。 -
我解决问题的方法就是让
EAGLView
足够大。 -
关于其他
CALayer
的混合,就我所尝试的而言,我没有遇到同步问题;EAGLView
在可能的时候进行更新,其他层也进行更新。如果使用alpha通道,只需将正确的属性设置为CAEAGLLayer
,并记住每次OpenGL更新场景时混合层可能会在性能方面代价高昂。