【问题标题】:iOS and multiple OpenGL viewsiOS 和多个 OpenGL 视图
【发布时间】:2011-11-13 11:58:19
【问题描述】:

我目前正在开发一个 iPad 应用程序,它使用 OpenGL 在多个 OpenGL 视图中绘制一些非常简单(不超过 1000 或 2000 个顶点)旋转模型。 目前在一个网格中有 6 个视图,每个视图都有自己的显示链接来更新绘图。由于模型的简单性,这是迄今为止最简单的方法,我没有时间编写完整的 OpenGL 接口。

目前,它在性能方面表现良好,但存在一些令人讨厌的故障。前 3 个 OpenGL 视图显示没有问题,后 3 个仅显示几个三角形(同时仍保留旋转模型的能力)。还有一些情况下 glDrawArrays 调用直接进入 EXC_BAD_ACCESS(尤其是在模拟器上),这告诉我缓冲区有问题。

我检查的(以及双重和三重检查)是:

  • 缓冲区分配似乎没问题
  • 在 dealloc 时释放所有资源
  • 仪器显示一些警告,但似乎没有任何相关内容

我认为这可能与我同时绘制多个视图有关,那么我应该在那里做任何已知的事情吗?每个视图都有自己的上下文,但也许我做错了什么......

另外,我刚刚注意到,在模拟器中,受影响的视图在所有顶点的正确绘图和只有少数顶点的错误绘图之间闪烁。

无论如何,如果您有任何想法,谢谢分享!

【问题讨论】:

    标签: ios opengl-es opengl-es-2.0


    【解决方案1】:

    好的,我将回答我自己的问题,因为我终于找到了发生的事情。导致所有这些问题的原因是缺少一条小线。

    基本上,要同时显示多个 OpenGL 视图,您需要:

    • 或者,每个视图相同的上下文。在这里,您必须注意不要同时使用多个线程进行绘制(即以某种方式锁定上下文,如 this answer 中所述。并且您必须每次在每一帧上重新绑定帧缓冲区和渲染缓冲区.
    • 或者,您可以为每个视图使用不同的上下文。然后,您必须在每一帧重新设置上下文,因为其他显示链接可能(并且会在我的情况下)导致您的 OpenGL 调用使用错误的数据。此外,由于您的上下文被保留,因此无需重新绑定帧缓冲区和渲染缓冲区。

    另外,在每一帧之后调用 glFlush(),告诉 GPU 完成每一帧的完全渲染。

    就我而言(第二个),渲染每一帧的代码(在 iOS 中)如下所示:

    - (void) drawFrame:(CADisplayLink*)displayLink {
      // Set current context, assuming _context
      // is the class ivar for the OpenGL Context
      [EAGLContext setCurrentContext:_context]
    
      // Clear whatever you want
      glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    
      // Do matrix stuff
      ...
      glUniformMatrix4fv (...);
    
      // Set your viewport
      glViewport (0, 0, self.frame.size.width, self.frame.size.height);
    
      // Bind object buffers
      glBindBuffer (GL_ARRAY_BUFFER, _vertexBuffer);
      glVertexAttribPointer (_glVertexPositionSlot, 3, ...);
    
      // Draw elements
      glDrawArrays (GL_TRIANGLES, 0, _currentVertexCount);
    
      // Discard unneeded depth buffer
      const GLenum discard[] = {GL_DEPTH_ATTACHMENT};
      glDiscardFramebufferEXT (GL_FRAMEBUFFER, 1, discard);
    
      // Present render buffer
      [_context presentRenderbuffer:GL_RENDERBUFFER];
    
      // Unbind and flush
      glBindBuffer (GL_ARRAY_BUFFER, 0);
      glFlush();
    }
    

    编辑

    我要编辑这个答案,因为我发现运行多个 CADisplayLinks 可能会导致一些问题。您必须确保将 CADisplayLink 实例的 frameInterval 属性设置为 0 或 1 以外的值。否则,运行循环将只有时间调用第一个渲染方法,然后它会一次又一次地调用它。就我而言,这就是为什么只有一个物体在移动的原因。现在,它设置为 3 或 4 帧,运行循环有时间调用所有的渲染方法。

    这仅适用于设备上运行的应用程序。模拟器速度很快,不关心这些。

    【讨论】:

      【解决方案2】:

      当你想要多个 UIViews 是 openGLViews 时会变得很棘手,

      在这个网站上你应该可以阅读所有相关信息:Using multiple openGL Views and uikit

      【讨论】:

      • 感谢您的链接;)但是,我为每个视图使用不同的上下文,因为除了着色器之外,我没有使用任何共享的东西。我尝试在每一帧的开头再次绑定帧和渲染缓冲区,但问题仍然存在......
      猜你喜欢
      • 2012-08-23
      • 1970-01-01
      • 1970-01-01
      • 2014-06-25
      • 1970-01-01
      • 2012-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多