I made a simple game for the iPhone using OpenGL ES. Everything works fine except for this problem:
我使用OpenGL ES为iPhone做了一个简单的游戏。除了这个问题,一切正常:
I turn the phone completely off, then back on, then launch my app and I get this wierd flickering! Every other frame is correct... the incorrect frames are just the same frame over and over again. If I quit the app, launch it again everything is fine. If I quit and restart 10 times in a row everything is fine every time.
我完全关闭手机,然后重新打开,然后启动我的应用程序,我得到了这个奇怪的闪烁!每隔一帧都是正确的...不正确的帧一遍又一遍地是同一帧。如果我退出应用程序,再次启动它一切都很好。如果我连续几次退出并重启10次,那么一切都很好。
But if I turn the phone off, then back on, then launch the app I get the same flickering the first time I launch the app.
但是,如果我关闭手机,然后再打开,然后启动应用程序,我第一次启动应用程序时会得到相同的闪烁。
Why is this happening?!
为什么会这样?!
Has anyone else had this problem?
有没有其他人有这个问题?
Cheers!
5 个解决方案
#1
3
Apple published additional information about this issue:
Apple发布了有关此问题的其他信息:
Q: My OpenGL ES application flickers. Especially when running on iPhone 3GS, the flickering seems to happen every frame. How do I fix this problem?
问:我的OpenGL ES应用程序闪烁。特别是在iPhone 3GS上运行时,每一帧都会出现闪烁现象。我该如何解决这个问题?
A: By default, the contents of a renderbuffer are invalidated after it is presented to the screen (by calling -EAGLContext/presentRenderbuffer:). Your application must completely redraw the contents of the renderbuffer every time you draw a frame, otherwise you may observe flickering or other unexpected results.
答:默认情况下,渲染缓冲区的内容在显示到屏幕后会失效(通过调用-EAGLContext / presentRenderbuffer :)。每次绘制框架时,您的应用程序必须完全重绘渲染缓冲区的内容,否则您可能会观察到闪烁或其他意外结果。
You must provide a color to every pixel on the screen. At the beginning of your drawing code, it is a good idea to use glClear() to initialize the color buffer. A full-screen clear of each of your color, depth, and stencil buffers (if you're using them) at the start of a frame can also generally improve your application's performance.
您必须为屏幕上的每个像素提供一种颜色。在绘图代码的开头,最好使用glClear()来初始化颜色缓冲区。在帧开始时全屏清除每个颜色,深度和模板缓冲区(如果您正在使用它们)通常也可以提高应用程序的性能。
If your application needs to preserve the drawable contents between frames, you can add the option kEAGLDrawablePropertyRetainedBacking = YES to your CAEAGLLayer object's drawableProperties property. Using this option requires additional memory and can reduce your application's performance.
如果应用程序需要在帧之间保留可绘制内容,则可以将选项kEAGLDrawablePropertyRetainedBacking = YES添加到CAEAGLLayer对象的drawableProperties属性中。使用此选项需要额外的内存,可能会降低应用程序的性能。
#2
1
Hmm. I haven't done much with OpenGL on the iPhone, but I have to say I haven't noticed this behavior with other applications. I'd suspect it's something to do with how you're switching active framebuffers.
嗯。我没有在iPhone上使用OpenGL做太多,但我不得不说我没有注意到其他应用程序的这种行为。我怀疑它与你如何切换活动帧缓冲区有关。
Maybe take a look at some of the sample code, and see what you're doing differently?
也许看看一些示例代码,看看你的做法有何不同?
#3
1
I believe this issue has to do with a corruption in the vertex buffer that occurs when the iphone OS takes control of the application(lock and resume, or warning popup). I have this issue as well but have not found a suitable fix, it seems to be one or more objects in the scene. We use a texture atlas and none of the other objects that share the texture seem to be affected. Perhaps destroying and recreating your vertex buffers will fix the issue.
我相信这个问题与顶层缓冲区中的损坏有关,当iphone OS控制应用程序(锁定和恢复,或警告弹出窗口)时会发生这种情况。我也有这个问题但是没有找到合适的修复,它似乎是场景中的一个或多个对象。我们使用纹理图集,并且共享纹理的其他对象似乎都没有受到影响。也许破坏和重新创建顶点缓冲区将解决问题。
#4
1
Is it possible you are calling glRenderBuffer() and sending the presentRenderBuffer message to your EAGLContext without having done any OpenGL updates, that is, no new glDrawElements or glDrawArrays. If you do this without kEAGLDrawablePropertyRetainedBacking set to YES, then you can get an annoying flicker.
是否有可能在没有进行任何OpenGL更新的情况下调用glRenderBuffer()并将presentRenderBuffer消息发送到您的EAGLContext,即没有新的glDrawElements或glDrawArrays。如果在没有将kEAGLDrawablePropertyRetainedBacking设置为YES的情况下执行此操作,则可能会出现烦人的闪烁。
Take a look a the kEAGLDrawablePropertyRetainedBacking on your CAEAGLLayer's drawableProperties property. This property determines the behavior of the drawable surface after it has displayed its contents. If this property is set to NO, then the contents are not retained and therefore not guaranteed to remain unchanged after display. If you set it to YES, then the contents are retained and will remain unchanged after display.
看一下CAEAGLLayer的drawableProperties属性中的kEAGLDrawablePropertyRetainedBacking。此属性确定可绘制曲面显示其内容后的行为。如果此属性设置为NO,则不保留内容,因此不保证在显示后保持不变。如果将其设置为YES,则内容将保留,并在显示后保持不变。
I believe setting kEAGLDrawablePropertyRetainedBacking to YES will mask the issue, but not fix it.
我相信将kEAGLDrawablePropertyRetainedBacking设置为YES会掩盖问题,但不能修复它。
#5
1
I had the same problem with the flashing/flicker alternating between the current image and a fixed image... it would happen on a 3GS, but not a 3G, first gen, or the simulator.
我在当前图像和固定图像之间交替闪烁/闪烁时遇到了同样的问题......它会发生在3GS上,而不是3G,第一代或模拟器。
In my case the problem was caused when I would set up the context in ESRenderer, but not actually draw anything, i.e. in the code below [scene draw] didn't draw anything in certain states. On the older iPhones and the Sim, when you don't draw anything, it didn't seem to flip the OpenGL buffers... but on the 3GS it does. Anyway, my workaround was to stop animation in those states (i.e. stop the timer that calls the draw rountine) when I was not drawing anything.
在我的情况下,问题是在我在ESRenderer中设置上下文时引起的,但实际上并没有绘制任何内容,即在下面的代码中[场景绘制]在某些状态下没有绘制任何内容。在较旧的iPhone和Sim上,当你没有绘制任何东西时,它似乎没有翻转OpenGL缓冲区......但是在3GS上它确实如此。无论如何,我的解决方法是在我没有绘制任何东西时停止那些状态中的动画(即停止调用绘制rountine的计时器)。
- (void) draw
{
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
//Render the GLScene...
[scene draw];
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
#1
3
Apple published additional information about this issue:
Apple发布了有关此问题的其他信息:
Q: My OpenGL ES application flickers. Especially when running on iPhone 3GS, the flickering seems to happen every frame. How do I fix this problem?
问:我的OpenGL ES应用程序闪烁。特别是在iPhone 3GS上运行时,每一帧都会出现闪烁现象。我该如何解决这个问题?
A: By default, the contents of a renderbuffer are invalidated after it is presented to the screen (by calling -EAGLContext/presentRenderbuffer:). Your application must completely redraw the contents of the renderbuffer every time you draw a frame, otherwise you may observe flickering or other unexpected results.
答:默认情况下,渲染缓冲区的内容在显示到屏幕后会失效(通过调用-EAGLContext / presentRenderbuffer :)。每次绘制框架时,您的应用程序必须完全重绘渲染缓冲区的内容,否则您可能会观察到闪烁或其他意外结果。
You must provide a color to every pixel on the screen. At the beginning of your drawing code, it is a good idea to use glClear() to initialize the color buffer. A full-screen clear of each of your color, depth, and stencil buffers (if you're using them) at the start of a frame can also generally improve your application's performance.
您必须为屏幕上的每个像素提供一种颜色。在绘图代码的开头,最好使用glClear()来初始化颜色缓冲区。在帧开始时全屏清除每个颜色,深度和模板缓冲区(如果您正在使用它们)通常也可以提高应用程序的性能。
If your application needs to preserve the drawable contents between frames, you can add the option kEAGLDrawablePropertyRetainedBacking = YES to your CAEAGLLayer object's drawableProperties property. Using this option requires additional memory and can reduce your application's performance.
如果应用程序需要在帧之间保留可绘制内容,则可以将选项kEAGLDrawablePropertyRetainedBacking = YES添加到CAEAGLLayer对象的drawableProperties属性中。使用此选项需要额外的内存,可能会降低应用程序的性能。
#2
1
Hmm. I haven't done much with OpenGL on the iPhone, but I have to say I haven't noticed this behavior with other applications. I'd suspect it's something to do with how you're switching active framebuffers.
嗯。我没有在iPhone上使用OpenGL做太多,但我不得不说我没有注意到其他应用程序的这种行为。我怀疑它与你如何切换活动帧缓冲区有关。
Maybe take a look at some of the sample code, and see what you're doing differently?
也许看看一些示例代码,看看你的做法有何不同?
#3
1
I believe this issue has to do with a corruption in the vertex buffer that occurs when the iphone OS takes control of the application(lock and resume, or warning popup). I have this issue as well but have not found a suitable fix, it seems to be one or more objects in the scene. We use a texture atlas and none of the other objects that share the texture seem to be affected. Perhaps destroying and recreating your vertex buffers will fix the issue.
我相信这个问题与顶层缓冲区中的损坏有关,当iphone OS控制应用程序(锁定和恢复,或警告弹出窗口)时会发生这种情况。我也有这个问题但是没有找到合适的修复,它似乎是场景中的一个或多个对象。我们使用纹理图集,并且共享纹理的其他对象似乎都没有受到影响。也许破坏和重新创建顶点缓冲区将解决问题。
#4
1
Is it possible you are calling glRenderBuffer() and sending the presentRenderBuffer message to your EAGLContext without having done any OpenGL updates, that is, no new glDrawElements or glDrawArrays. If you do this without kEAGLDrawablePropertyRetainedBacking set to YES, then you can get an annoying flicker.
是否有可能在没有进行任何OpenGL更新的情况下调用glRenderBuffer()并将presentRenderBuffer消息发送到您的EAGLContext,即没有新的glDrawElements或glDrawArrays。如果在没有将kEAGLDrawablePropertyRetainedBacking设置为YES的情况下执行此操作,则可能会出现烦人的闪烁。
Take a look a the kEAGLDrawablePropertyRetainedBacking on your CAEAGLLayer's drawableProperties property. This property determines the behavior of the drawable surface after it has displayed its contents. If this property is set to NO, then the contents are not retained and therefore not guaranteed to remain unchanged after display. If you set it to YES, then the contents are retained and will remain unchanged after display.
看一下CAEAGLLayer的drawableProperties属性中的kEAGLDrawablePropertyRetainedBacking。此属性确定可绘制曲面显示其内容后的行为。如果此属性设置为NO,则不保留内容,因此不保证在显示后保持不变。如果将其设置为YES,则内容将保留,并在显示后保持不变。
I believe setting kEAGLDrawablePropertyRetainedBacking to YES will mask the issue, but not fix it.
我相信将kEAGLDrawablePropertyRetainedBacking设置为YES会掩盖问题,但不能修复它。
#5
1
I had the same problem with the flashing/flicker alternating between the current image and a fixed image... it would happen on a 3GS, but not a 3G, first gen, or the simulator.
我在当前图像和固定图像之间交替闪烁/闪烁时遇到了同样的问题......它会发生在3GS上,而不是3G,第一代或模拟器。
In my case the problem was caused when I would set up the context in ESRenderer, but not actually draw anything, i.e. in the code below [scene draw] didn't draw anything in certain states. On the older iPhones and the Sim, when you don't draw anything, it didn't seem to flip the OpenGL buffers... but on the 3GS it does. Anyway, my workaround was to stop animation in those states (i.e. stop the timer that calls the draw rountine) when I was not drawing anything.
在我的情况下,问题是在我在ESRenderer中设置上下文时引起的,但实际上并没有绘制任何内容,即在下面的代码中[场景绘制]在某些状态下没有绘制任何内容。在较旧的iPhone和Sim上,当你没有绘制任何东西时,它似乎没有翻转OpenGL缓冲区......但是在3GS上它确实如此。无论如何,我的解决方法是在我没有绘制任何东西时停止那些状态中的动画(即停止调用绘制rountine的计时器)。
- (void) draw
{
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
//Render the GLScene...
[scene draw];
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}