更新时出现iPod/iPhone OpenGL ES UIView闪烁

问题描述:

我有一个简单的iPhone应用程序,它使用OpenGL ES(v1)根据用户的触摸绘制一条线。在XCode模拟器中,代码完美工作。但是,当我将应用程序安装到iPod或iPhone上时,绘制线条时,OpenGL ES视图会“闪烁”。如果我禁用线条绘制,则闪光灯消失。通过“闪光灯”,我的意思是背景图像(这是一个OpenGL纹理)瞬间消失,然后再次出现。看起来好像整个场景被完全擦除和重绘。更新时出现iPod/iPhone OpenGL ES UIView闪烁

它处理线描的代码如下:

renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end 
{ 
    static GLfloat*  vertexBuffer = NULL; 
    static NSUInteger vertexMax = 64; 
    NSUInteger   vertexCount = 0, 
    count, 
    i; 

    //Allocate vertex array buffer 
    if(vertexBuffer == NULL) 
     vertexBuffer = malloc(vertexMax * 2 * sizeof(GLfloat)); 

    //Add points to the buffer so there are drawing points every X pixels 
    count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y))/kBrushPixelStep), 1); 
    for(i = 0; i < count; ++i) { 
     if(vertexCount == vertexMax) { 
      vertexMax = 2 * vertexMax; 
      vertexBuffer = realloc(vertexBuffer, vertexMax * 2 * sizeof(GLfloat)); 
     } 

     vertexBuffer[2 * vertexCount + 0] = start.x + (end.x - start.x) * ((GLfloat)i/(GLfloat)count); 
     vertexBuffer[2 * vertexCount + 1] = start.y + (end.y - start.y) * ((GLfloat)i/(GLfloat)count); 
     vertexCount += 1; 
    } 

    //Render the vertex array 
    glVertexPointer(2, GL_FLOAT, 0, vertexBuffer); 
    glDrawArrays(GL_POINTS, 0, vertexCount); 

    //Display the buffer 
    [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 
} 

(该功能是基于从GLPaint样品应用相同的名称的功能) 对于我的寿命,我可以不知道为什么这会导致屏幕闪烁。该线条正确绘制(无论是在模拟器和iPod中)。但是,闪光灯使其无法使用。

任何人都有如何防止“闪光灯”的想法?

经过多次测试,我找到了解决此问题的方法,但我不确定这是否是最佳做法。

解决方法是将kEAGLDrawablePropertyRetainedBacking从NO更改为YES。这停止了​​闪烁。具体而言,编码设置OpenGL的观点现在看起来是这样的:

CAEAGLLayer *eaglLayer = (CAEAGLLayer*) self.layer; 
eaglLayer.opaque = YES; 
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithBool:YES], 
           kEAGLDrawablePropertyRetainedBacking, 
           kEAGLColorFormatRGB565, kEAGLDrawablePropertyColorFormat, nil]; 

同样,我不知道,如果是使用RetainedBacking战略的一个最佳实践,但它停止闪烁。根据http://developer.apple.com/iphone/library/documentation/iPhone/Reference/EAGLDrawable_Ref/EAGLDrawable/EAGLDrawable.html#jumpTo_6,只有在某些情况下,才应将RetainedBacking设置为YES。

只有当您需要内容保持不变时才建议将该值设置为YES,因为使用它可能会导致性能下降和额外的内存使用量。

目前尚不清楚性能或内存如何受到影响,但这一改变完全阻止了我所看到的所有“闪烁”。

+0

这几乎绝对不是正确的解决方案。你只是掩盖了这个问题。我也经历了这一次,最初得出了同样的结论。 – 2010-03-13 16:52:59

我有一次完全相同的问题。 我有一个UIWindow,我在其中放置了一个OpenGLES UIView。 绘图过程很好,直到我试图在OpenGLES视图中添加一个子视图(UIImageView)。屏幕闪烁。 我能够通过添加UIImageView作为UIWindow的子视图来解决问题。 看来OpenGLES渲染不喜欢子视图...

在OpenGLES

所以查看,如果你有这样的:

[自我addSubView:...]

你可以取代它举例来说,通过:

[self.superview addSubView:...]

不能在你的代码中看到,如果你有类似的东西,但我希望这将有助于有点...:)

是否有可能您正在调用glRenderBuffer()并将presentRenderBuffer消息发送到您的EAGLContext而未执行任何OpenGL更新,即没有新的glDrawElements或glDrawArrays。也许你正在代码中的另一处发送presentRenderBuffer消息?如果您在没有将kEAGLDrawablePropertyRetainedBacking设置为YES的情况下执行此操作,则可能会出现恼人的闪烁。

看看你的CAEAGLLayer的drawableProperties属性上的kEAGLDrawablePropertyRetainedBacking。该属性确定了可绘制表面在显示其内容后的行为。如果此属性设置为NO,则内容不会保留,因此不能保证在显示后保持不变。如果将其设置为YES,则内容将保留并在显示后保持不变。

我认为将kEAGLDrawablePropertyRetainedBacking设置为YES会掩盖问题,但无法解决问题。