【问题标题】:iPhone OpenGL First Frame BlackiPhone OpenGL 第一帧黑色
【发布时间】:2011-07-04 04:16:29
【问题描述】:

我的应用程序基于 openGL,支持 ES 1.1 和 ES 2.0。

我的视图控制器有一个视图,它是 EAGLView 的一个实例(根据 Apple 的示例代码),它反过来为 ES 1.1 或 2.0 使用不同的“渲染器”对象(对于使用过 Xcode 示例的任何人来说,这几乎是标准)。

我使用 CADisplayLink 来更新屏幕。我的目标是至少 iOS 4.0+,所以应该没有问题。

在启动时,显示启动图像 (Default.png) 之后的第一帧被渲染为黑色。 中间出现一帧烦人的黑色闪烁。

如果在制作窗口键和可见之前我“伪造”了一轮更新/渲染周期(以便将后台缓冲区也渲染到,而不是空的),闪烁消失但仅使用 ES 2.0 时

我将 kEAGLDrawablePropertyRetainedBacking 设置为 YES,但是这两个值似乎都没有任何区别。

使用 ES 1.1 时,闪烁仍然存在。唯一的区别是,如果我在使窗口可见之前执行“刷新”,屏幕会闪烁到我使用 glClearColor() 指定的颜色。但是如果我不预刷新,闪烁总是黑色的。

我在 Cocos2d 论坛上一次又一次地看到关于这个问题的讨论,但即使在那里,问题似乎总是会在每次提出新的 hack 后再次出现并咬你。

尽管如此,我使用的是普通 OpenGL ES(NOT Cocos2d 或任何其他库),但无论我如何搜索都找不到有类似问题的人网络...

有什么提示吗?

【问题讨论】:

    标签: iphone opengl-es splash-screen flicker default.png


    【解决方案1】:

    问题的原因与您所诊断的差不多——当相关的视图控制器立即完成加载时(即,当 Default.png 图像被删除时),它还没有任何内容。 CADisplayLink 直到该帧结束才会触发。

    我认为正确的做法是进行完整的重绘并呈现在 viewDidLoad: 中,因为您应该在此处设置不在 NIB 中的视图位。这不应该在任一渲染路径中引入延迟帧,假设它们是作为单缓冲区或双缓冲区实现的。

    假设还有其他一些无法诊断的问题,在一种情况下,我有一个应用程序,由于我无法控制的代码性质(作为跨平台端口我正在做的只是胶水代码)。所以我所做的是在我的第一个视图控制器之上添加一个包含 Default.png 的全屏 UIImageView。然后我等待了一帧并删除了 UIImageView。无论您的渲染循环如何,这都应该有效。

    【讨论】:

    • 好吧,我根本没有使用 UIView 或 NIB,但是 OpenGL 视图被设置为 UIViewController 后代的“视图”属性,所以我应该尝试使用 viewdidLoad。无论如何,我通过在 OpenGL 视图对象的 init 方法的末尾强制调用 layoutSubviews 来解决它。我发现空白一直持续到系统调用该方法,所以我让它“更早”执行,现在它可以工作了。
    • 快速评论几年太晚了:如果将来计划调用layoutSubviews,则强制立即执行layoutSubviews 的正确方法是调用layoutIfNeeded。或者,如果您绝对需要调用,请使用 setNeedsLayout / layoutIfNeeded 对。根据文档,您绝对不应该直接调用layoutSubviews。可能你知道,但我认为值得记录。
    【解决方案2】:

    我通过在绘制第一帧之前添加额外的 presentRenderbuffer(当然是前面的 glBindRenderbuffer)解决了同样的问题。 出于某种原因,GLView 需要两个 presentRenderbuffer 调用才能开始显示任何内容。 我想这可能与一些后台缓冲区处理有关,尽管这很奇怪。

    【讨论】:

      【解决方案3】:

      您需要在 OpenGLView 类的方法layoutSubviews 中重绘场景。

      -(void)layoutSubviews {
          GLint backingWidth, backingHeight;
      
          glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
          [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
          glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
          glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
      
          glViewport(0, 0, backingWidth, backingHeight);
          glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
      
          [scene draw];
          [context presentRenderbuffer:GL_RENDERBUFFER];
      }
      

      【讨论】:

        【解决方案4】:

        在基于视图的应用程序上打开 eaglview 时,我遇到了类似的问题。我有一秒钟的黑屏闪烁,然后打开了opengl视图。起作用的只是在EAGLView 类中的initWithCoder 方法中创建eaglLayer.opaque = NO;

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-04-10
          • 2023-03-02
          • 2021-12-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-13
          相关资源
          最近更新 更多