iPhone OpenGL 第一帧黑色
我的应用程序基于 openGL,支持 ES 1.1 和 ES 2.0。
我的视图控制器有一个视图,它是 EAGLView 的实例(根据 Apple 的示例代码),它又为 ES 1.1 或 2.0 使用不同的“渲染器”对象(对于使用过 Xcode 示例的任何人来说几乎都是标准)。
我使用 CADisplayLink 来更新屏幕。我的目标至少是 iOS 4.0+,所以应该没有问题。
启动时,显示启动图像 (Default.png) 后的第一帧呈现为黑色。 中间有一帧令人讨厌的黑色闪烁。
如果在使窗口成为“Key”和“Visible”之前,我“伪造”一轮更新/渲染周期(以便也渲染后台缓冲区,而不是空),闪烁会消失,但仅在使用 ES 时2.0。
我将 kEAGLDrawablePropertyRetainedBacking 设置为 YES,但这两个值似乎都没有任何区别。
使用 ES 1.1 时,闪烁仍然存在。唯一的区别是,如果我在使窗口可见之前执行“刷新”,屏幕将闪烁为我用 glClearColor() 指定的颜色。但如果我不预刷新,闪烁总是黑色的。
我在 Cocos2d 论坛上一次又一次看到关于这个问题的讨论,但即使在那里,这个问题似乎总是在每一个新的 hack 出现后再次出现并困扰你。
尽管如此,我使用的是纯 OpenGL ES(不是 Cocos2d 或任何其他库),但无论我如何在网络上搜索,都找不到任何有类似问题的人。 ..
有什么提示吗?
My application is openGL based and supports ES 1.1 as well as ES 2.0.
My view controller has a view that is an instance of EAGLView (as per Apple's sample code), which in turn uses different "renderer" objects for either ES 1.1 or 2.0 (pretty much standard for anyone who has used the Xcode samples).
I use CADisplayLink to update the screen. I am targeting a minimum of iOS 4.0+ so there should be no problem.
On startup, the first frame after the startup image (Default.png) is shown, is rendered black.
A one-frame, annoying black flicker in between.
If, before making the window Key and Visible I "fake" one round of my update/render cycle (so as to have the back buffer rendered to as well, and not empty), the flicker disappears but only when using ES 2.0.
I have kEAGLDrawablePropertyRetainedBacking set to YES, but neither value seems to make any difference.
When using ES 1.1, the flicker remains. The only difference is that, if I perform the "refresh" prior to making the window visible the screen flickers to the color I specify with glClearColor(). But if I don't pre-refresh, the flicker is invariably black.
I have seen discussions about this problem time and again on the Cocos2d forums, but even there the problem seems to always come back and bite you after every new hack the come up with.
Nevertheless I am using plain-OpenGL ES (NOT Cocos2d or any other library), and yet can't find anyone with a similar problem no matter how I search the web...
Any hints?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
问题的原因与您所诊断的差不多 - 当相关视图控制器立即完成加载时(即,当删除 Default.png 图像时),它还没有任何内容。 CADisplayLink 直到该帧结束时才会触发。
我认为正确的做法是进行完全重绘并出现在 viewDidLoad: 中,因为这就是您要设置不在 NIB 中的视图位的位置。假设它们被实现为单缓冲区或双缓冲区,那么这不应在任一渲染路径中引入帧延迟。
假设还存在其他一些无法诊断的问题,在一种情况下,我有一个应用程序,由于代码的性质超出了我的控制范围,因此无法提前绘制框架(我是一个跨平台端口)只做粘合代码)。所以我所做的就是在我的第一个视图控制器顶部添加一个包含 Default.png 的全屏 UIImageView。然后我等待一帧并删除 UIImageView。无论您的渲染循环如何,这都应该有效。
The cause of the problem is pretty much as you've diagnosed — when the relevant view controller is immediately finished loading (ie, when the Default.png image is removed), it doesn't have any content yet. CADisplayLink doesn't trigger until the end of that frame.
I think the correct thing to do would be to do a full redraw and present in viewDidLoad:, since that's where you're meant to set up bits of the view that weren't in the NIB. That shouldn't introduce a frame of latency in either rendering path, assuming they're implemented as a single or double buffer.
Supposing there is some other undiagnosable problem going on, in one case I had an app where it wasn't possible to draw a frame ahead of time due to the nature of code beyond my control (being a cross-platform port for which I was doing just the glue code). So what I did was add a fullscreen UIImageView containing Default.png on top of my first view controller. I then waited one frame and removed the UIImageView. That should work, whatever your render loop.
我通过在绘制第一帧之前添加额外的presentRenderbuffer(当然前面有glBindRenderbuffer)解决了同样的问题。
由于某种原因,GLView 需要两次 PresentRenderbuffer 调用才能开始显示任何内容。
我想这可能与一些后台缓冲区处理有关,尽管无论如何都很奇怪。
I've solved the very same problem by adding extra presentRenderbuffer (with glBindRenderbuffer ahead, of course) before drawing the first frame.
For some reason GLView requires two presentRenderbuffer calls to start displaying anything.
I guess it may be related to some back-buffer handling, though it is odd anyway.
您需要在 OpenGLView 类的
layoutSubviews
方法中重绘场景。You need to redraw scene in the method
layoutSubviews
of your OpenGLView class.在基于视图的应用程序上打开 eaglview 时,我遇到了类似的问题。我的黑屏闪烁了一秒,然后 opengl 视图打开了。有效的方法是在 EAGLView 类的 initWithCoder 方法中设置 eaglLayer.opaque = NO; 。
I was having a similar problem when opening a eaglview on a view based application. I had a flicker for a flash of a second of black screen and then the opengl view got opened. What worked was just making
eaglLayer.opaque = NO;
ininitWithCoder
method inEAGLView
class.