2011-11-24 17 views
1

我一整天都在努力寻找答案。OpenGL在从另一个视图返回后绘制黑色屏幕

问题:

我有OpenGL的看法,我在IB创建,初始化所有缓冲区,并设置其DisplayLink的渲染循环。它工作得很好,一切都很好。但后来我尝试创建与根控制这个OpenGL视图,另一个控制器,并使用目前它:

[self presentModalViewController:newPage animated:YES]; 

这很好地显示出来,就像我想要的。它也很好,没有发现问题。它也从IB发起。但只要我使用

[self dismissModalViewControllerAnimated:YES]; 

动画确实发生了,这个视图下去,但它的股价下跌它留下的“垃圾”背后(的观点在黑色背景的部分)和以前的OpenGL视图,住宿黑色。我尝试删除并重新创建displayLink,但没有运气。我试图再次破坏/创建framebuffers,并且设法让它工作一次,但花了很长时间,并且从视图创建它,我不知道这是否是正确的方法。为了更容易,下面是我的代码的一些部分:

- (BOOL)createFrameBuffer 
{ 
    glGenFramebuffersOES(1, &viewFramebuffer); 
    glGenRenderbuffersOES(1, &viewRenderbuffer); 

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 
    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer); 



    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); 
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); 

    if (YES) 
    { 
     glGenRenderbuffersOES(1, &depthRenderbuffer); 
     glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer); 
     glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight); 
     glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer); 
    } 

    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) 
    { 
     NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); 
     return NO; 
    } 

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 

    return YES; 
    } 

    } 

    - (void)destroyFrameBuffer 
    glDeleteFramebuffersOES(1, &viewFramebuffer); 
    viewFramebuffer = 0; 
    glDeleteRenderbuffersOES(1, &viewRenderbuffer); 
    viewRenderbuffer = 0; 

    if(depthRenderbuffer) 
    { 
     glDeleteRenderbuffersOES(1, &depthRenderbuffer); 
     depthRenderbuffer = 0; 
    } 

    - (void)layoutSubviews 


    [EAGLContext setCurrentContext:context]; 

    [self draw:nil]; 

内部init是我的主要init方法。

- (id)internalInit 
{  

     CAEAGLLayer* eaglLayer = (CAEAGLLayer*) super.layer; 
     eaglLayer.opaque = YES; 


     context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; 

     if (!context || ![EAGLContext setCurrentContext:context]) { 
      [self release]; 
      return nil; 
     } 

    [self createFrameBuffer]; 

    [self setupView:self]; 

     [self drawView: nil]; 

     CADisplayLink* displayLink; 
     displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(draw:)]; 
     [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
     [displayLink setFrameInterval:1]; 

    return self; 
} 

setupView:方法基本上创建视口,设置视锥,所有必要的变量和状态。没什么特别的。

在此先感谢所有花费的时间。

+0

其实如果我以同样的方式创建任何其他的UIView(不是openGL),当我解雇它时,我的主要openGL视图仍然是黑色的。但它仍然被渲染(至少我所有的绘制方法都被调用,并且所有的用户输入都被接收和处理)。还有一些来自调试器的帮助,我发现我的frameBuffer,renderBuffer和depthBuffer变量是0(不生成?),所以这可能是我的问题的根源。 – avuthless

+0

通过大量的测试,我发现当我创建另一个opengl视图时,旧的只是冻结。我认为它们以某种方式重叠。虽然我宁愿他们都保持私人对方。我已经将所有方法声明为私有(在.m文件中),我也声明所有变量都是@private,但这并没有帮助。我能找到的唯一解决方案是彻底销毁视图,然后从头开始初始化视图。这对我来说确实有效,但我仍然在寻找正确的答案和方法来解决这个问题。 – avuthless

回答

2

经过一些优化后,我发生了同样的效果,我已经证明在任何情况下都无法正常工作,对于我解散Game Center视图或完成播放MPPlayer电影后出现问题。

从苹果的OpenGL模板时,你会得到一个LayoutSubviews(你可以在上面的窗口在前看不见后得到),你应该销毁并重新创建你的帧缓冲

- (void)layoutSubviews 
{ 
    // The framebuffer will be re-created at the beginning of the next setFramebuffer method call. 
    [self deleteFramebuffer]; 
} 

在此之后,funcion [(EAGLView *)的自我。查看setFramebuffer];应该被调用以再次创建帧缓冲区,原始模板实际上已经在每帧上调用了它,但是只有在它被销毁后才需要调用它。 (我把第一次叫在那里做一个VAR)

我只是把程序在这里:

- (void)setFramebuffer 
{ 
    if (context) 
    { 
     [EAGLContext setCurrentContext:context]; 

     if (!defaultFramebuffer) 
      [self createFramebuffer]; 

     glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer); 
     first = FALSE; 

    } 
} 

- (void)createFramebuffer 
{ 
if (context && !defaultFramebuffer) 
{ 
    NSLog(@"Create Frame Buffer"); 

    [EAGLContext setCurrentContext:context]; 

    // Create default framebuffer object. 
    glGenFramebuffersOES(1, &defaultFramebuffer); 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer); 

    // Create color render buffer and allocate backing store. 
    glGenRenderbuffersOES(1, &colorRenderbuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 

    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer *)self.layer]; 
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &framebufferWidth); 
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &framebufferHeight); 

    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer); 

    // Need a depth buffer 
    glGenRenderbuffersOES(1, &depthRenderbuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer); 
    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, framebufferWidth, framebufferHeight); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer); 

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) 
     NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER_OES)); 
} 

} 

所以这setFramebuffer上被调用的DisplayLink调用的函数。我在MPPlayer游戏中心发出的didfinish通知中首先将var重置为FALSE。

如果你找不到你的问题尝试和调试在EAGL对象级别调用什么,NSLog的每一个函数,看看是否有什么奇怪的事情发生在你的缓冲区或绑定。

+0

好吧,当我尝试重新创建视图,一直在后台我看到,我收到坏渲染缓冲参数(宽度和高度返回0)。但你的解决方案是正确的,我发现更多的人在谈论这个问题,他们都提供了这样的指示。我现在将扫描我的代码中是否存在任何使我无法创建新的渲染缓冲区的缺陷/错误。谢谢您的回答! – avuthless

+0

我已经实现了你的方法,他们确实做得很好。但是,当我尝试与另一个opengl视图,第一个只停止渲染,并没有缓冲区娱乐帮助它。为了测试,我创建了我的opengl场景,并在角落中创建了一个小的子视图,以查看当这个小视图初始化时会发生什么。那么我的主要opengl视图就会挂断。没有任何移动或刷新。输入是好的(至少我认为是这样),但观点没有奏效。看来两个opengl的观点不能相处。 – avuthless

+0

是的,两个opengl的观点是非常不鼓励苹果,但我看到有人这样做,唉,表现糟糕。我会尝试浏览我的浏览器历史记录,看看我能否找到它。 – led42

0

'EAGLView在出现或重新出现问题时是黑色'的另一种可能的解释是您的[EAGLView renderbufferStorage:fromDrawable:]方法未在主线程上调用。从后台调用此方法将导致通常有效的情况,但非正常情况会变黑。可能不是这里提到的确切问题的原因,但足以说明它可能对绝望的谷歌将来在这个页面中陷入困境有用。

0

我有相同的问题,因为glDepthMask(FALSE)背景框架绘图保存到图像,然后不返回正常渲染。希望能帮助到你。

谢谢。

相关问题