Ios 如何将CIContext drawImage:inRect:fromRect:与CADisplayLink一起使用
: 。。在iOS 6上,此方法是异步的 因此,如果我在一个应用程序中使用它,它会遇到一个问题,因为它将以60fps的速度不断启动异步绘图,而实际绘图可能无法跟上Ios 如何将CIContext drawImage:inRect:fromRect:与CADisplayLink一起使用,ios,objective-c,cocoa-touch,core-image,Ios,Objective C,Cocoa Touch,Core Image,: 。。在iOS 6上,此方法是异步的 因此,如果我在一个应用程序中使用它,它会遇到一个问题,因为它将以60fps的速度不断启动异步绘图,而实际绘图可能无法跟上 - (void) displayLinkDidFire:(CADisplayLink *)displatLink; { CFTimeInterval duration = [displatLink duration]; CGFloat fps = round (1.0 / duration); NSLog(@"%
- (void) displayLinkDidFire:(CADisplayLink *)displatLink;
{
CFTimeInterval duration = [displatLink duration];
CGFloat fps = round (1.0 / duration);
NSLog(@"%f fps", fps); // Always logs 60 fps since drawImage is async
// This method is fast since a CIImage is just a 'recipe' for an image
CIImage * result = [Helper generateCIImage];
// This drawing is unable to keep up with the calls to the displayLinkDidFire method
[self.ciContext drawImage:result
inRect:self.destFrame
fromRect:self.targetFrame];
}
我如何回避这个问题
编辑-更多信息 我正在使用CoreImage和
EAGLContext
(根据WWDCs获得更好的绘图性能)
解决方案是使用“OpenGL ES渲染循环”,而不是尝试使用
CADisplayLink
构建一个循环。幸运的是,这很容易,因为a自动执行此操作:
GLKViewController类提供所有标准视图控制器功能,但还实现了OpenGL ES渲染循环
唯一不好的一面是,这将您与使用GLKViewController
紧密联系在一起,而不是仅仅将GLKView
添加到现有的UIView。要解决这个问题,您需要了解如何实现自己的OpenGL ES渲染循环
// The GLKViewController automatically calls this method
- (void) updateScreen
{
CIImage * result = [Helper generateCoreImage];
// Clears the screen to a grey color
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
[self.ciContext drawImage:result
inRect:self.destFrame
fromRect:self.targetFrame];
// `display` needs to be called here according to the docs.
GLKView *view = (GLKView *)self.view;
[view display];
}
通常,显示链接将执行它所需的操作,然后调用
setNeedsDisplay
通知视图刷新。这不会导致任何异步计时问题。@Rob我认为显示链接不会调用-setNeedsDisplay
。它独立于标准的-drawRect:
视图更新周期工作。@Rob-感谢您的评论。我在我的设备上获得了大约0.5 fps的可视速度,而displayLink的速度是60 fps,所以我认为异步是问题所在。你是说drawImage是异步的,或者我应该使用非CADisplayLink
的东西来触发绘图,这不重要吗?@Robert你要么需要加快绘图速度,要么降低刷新率以适应绘图速度,要么需要跳过帧。如果绘制图像需要2秒钟,则CADisplayLink对您没有多大用处。您还可以使用while()循环。根据您的更新,我建议在开始渲染之前,使用图像数据加载适当的OpenGL纹理。从文件加载到内存中,然后复制到帧缓冲区可能太慢了。@BoredAstronaut同意,它不会自动调用setNeedsDisplay
,但在制作自己的动画时,通常使用CADisplayLink
处理程序调用setNeedsDisplay
。显示链接调用的频率将自动匹配动画的FPS。
// The GLKViewController automatically calls this method
- (void) updateScreen
{
CIImage * result = [Helper generateCoreImage];
// Clears the screen to a grey color
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
[self.ciContext drawImage:result
inRect:self.destFrame
fromRect:self.targetFrame];
// `display` needs to be called here according to the docs.
GLKView *view = (GLKView *)self.view;
[view display];
}