【问题标题】:iPod/iPhone OpenGL ES UIView flashes when updating更新时 iPod/iPhone OpenGL ES UIView 闪烁
【发布时间】:2010-03-14 00:51:04
【问题描述】:

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

处理画线的代码如下:

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 中)。但是,闪光灯使它无法使用。

有人对如何防止“闪光”有想法吗?

【问题讨论】:

    标签: iphone cocoa-touch opengl-es


    【解决方案1】:

    经过大量测试,我找到了解决此问题的方法,但我不确定这是否是最佳实践。

    解决方案是将 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,因为使用它会导致性能降低和内存使用量增加。

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

    【讨论】:

    • 这几乎肯定不是正确的解决方案。你只是在掩盖问题。我也经历过一次,最初得出了同样的结论。
    【解决方案2】:

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

    所以在你的 OpenGLES 视图中,如果你有类似的东西:

    [自我addSubView:...]

    您可以替换它,例如:

    [self.superview addSubView: ...]

    如果你有类似的东西,在你的代码中看不到,但我希望这会有所帮助...... :)

    【讨论】:

      【解决方案3】:

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

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

      我相信将 kEAGLDrawablePropertyRetainedBacking 设置为 YES 会掩盖问题,但不能解决问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-25
        • 2015-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多