我正在开发一个在 OpenGL ES 中使用大纹理的 iPad 应用程序。当场景第一次加载时,我在天花板上看到了一个巨大的黑色伪影,持续了几帧,如下图所示。就好像尚未填充更高级别的 mipmap。在随后的帧中,天花板正确显示。
当我开始使用 mipmapping 时,这个问题才开始出现。一种可能的解释是 glGenerateMipmap() 调用异步完成它的工作,产生一些 mipmap 创建工作者(在单独的进程中,或者可能在 GPU 中)并返回。
这是可能的,还是我叫错了树?
在单个上下文中,所有操作似乎都严格按顺序执行。但是,在您最近的回复中,您提到使用第二个线程。为此,您必须创建第二个共享上下文:重新进入 OpenGL 上下文始终是非法的。如果已经使用共享上下文,则仍然必须遵循一些同步规则,记录在http://developer.apple.com/library/ios/ipad/#DOCUMENTATION/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithOpenGLESContexts/WorkingwithOpenGLESContexts.html
它应该是同步的;OpenGL 本身并没有任何真正的线程概念(除了 CPU 和 GPU 之间的隐式异步对话)。
一个很好的诊断方法是切换到GL_LINEAR_MIPMAP_LINEAR
. 如果分辨率较低的 mip 贴图直到稍后才到达确实是一个问题,那么您会看到天花板上的麻烦区域相互融合,而不是当前的黑色或正确效果。
根据输出的第二个猜测是某种深度缓冲区清除问题。
我按照@Tommy 的建议切换到GL_LINEAR_MIPMAP_LINEAR
. 现在黑色或正确效果变为正确和黑色之间的淡入淡出。
我猜虽然我们都知道 OpenGL 是一个管道(因此是异步的,除非您正在检索状态或显式同步),但我们往往会忘记它。在这种情况下,我确实做到了,我不是在绘制,而是在加载和设置纹理。
一旦我确认了问题的性质,我在加载所有纹理后添加了一个 glFinish(),问题就消失了。(顺便说一句,我的绘制循环在前台,而我的纹理加载循环 - 因为它非常耗时并且会损害交互性 - 在后台。另外,由于这可能因平台而异,我在 iPad 2 上使用 iOS5 )