我整天都在苦苦寻找答案。
问题:
我有OpenGL视图,我在IB中创建它,初始化所有缓冲区并在displayLink中设置其渲染循环。它很棒,一切都很好。但后来我尝试在根控制器中使用此openGL视图创建另一个控制器并使用以下方式显示它:
[self presentModalViewController:newPage animated:YES];
它显示得很好,就像我想要的那样。它也很好用,没有发现任何问题。它也是从IB发起的。但是一旦我使用
[self dismissModalViewControllerAnimated:YES];
动画确实发生了,视图确实发生了变化,但是当它下降时,它背后留下“垃圾”(黑色背景中的部分视图),之前的openGL视图保持黑色。我尝试删除并重新创建displayLink,但没有运气。我试图再次破坏/创建帧缓冲区,我确实设法让它工作一次,但它花了很长时间,因为我从视图创建它,我不知道这是否是正确的方法。为了使它更容易,这是我的代码的一些部分:
- (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 :(得分:2)
在我完成一些优化之后我发生了同样的效果,但事实证明,在解除游戏中心视图或完成播放MPPlayer电影之后,问题就出现了。
当您获得LayoutSubviews(在顶部窗口消失后将会获得)时,从apple的opengl模板中,您应该销毁并重新创建帧缓冲区
- (void)layoutSubviews
{
// The framebuffer will be re-created at the beginning of the next setFramebuffer method call.
[self deleteFramebuffer];
}
之后的功能[(EAGLView *)self.view 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));
}
}
因此在从displaylink调用的函数上调用此setFramebuffer。我在MPPlayer游戏中心的完成通知中首先将var重置为FALSE。
如果找不到问题,请尝试调试在EAGL对象级别调用的内容,NSLog在那里查看每个函数,看看是否有任何奇怪的事情发生缓冲区或绑定。
答案 1 :(得分:0)
“EAGLView在出现或重新出现时是黑色”的另一个可能的解释是,您的[EAGLView renderbufferStorage:fromDrawable:]
方法未在主线程上调用。从后台调用此方法将导致通常有效但偶尔会变黑的情况。可能不是这里所说的确切问题的原因,但足够晦涩,以至于它可能对绝望的google在将来绊倒这个页面时有用。
答案 2 :(得分:0)
我有同样的问题,因为glDepthMask(FALSE)用于背景框架绘制以将其保存到图像,然后没有返回正常渲染。希望它有所帮助。
感谢。