OpenGL 中的离屏帧缓冲区
Posted
技术标签:
【中文标题】OpenGL 中的离屏帧缓冲区【英文标题】:Offscreen Framebuffers in OpenGL 【发布时间】:2012-01-30 01:13:45 【问题描述】:我正在使用 OpenGL 创建一个 iPhone 游戏,我想在屏幕外帧缓冲区上绘制,然后将该帧缓冲区用作在实际屏幕上绘制的纹理。我的代码基于Apple's 和 GLSprite 示例,但在切换绘图目标时我似乎做得不对,因为我只得到一个空白纹理。我正在使用的代码如下。怎么了?动态渲染纹理的最佳方式是什么?
下面的 Creating an Offscreen Framebuffer 给了我 8cd6 错误代码。
创建屏幕帧缓冲区
glGenFramebuffersOES(1, &viewFramebuffer);
glGenRenderbuffersOES(1, &viewRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)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(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
return NO;
创建一个离屏帧缓冲区
glGenFramebuffers(1, &offscreenFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, offscreenFramebuffer);
glGenTextures(1,&framebufferTexture);
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferTexture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
NSLog(@"ERROR: %x", status);
绘图,循环:
glBindTexture(GL_TEXTURE_2D,textureFromFile); //Switch to a texture from a file
glBindFramebufferOES(GL_FRAMEBUFFER_OES, offscreenFramebuffer); //Switch to the offscreen framebuffer
//Render the texture to be used later
glBindTexture(GL_TEXTURE_2D,framebufferTexture); //Switch to the offscreen framebuffer's texture
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); //Switch to the screen framebuffer
//Do the drawing using the texture rendered just before, and present this to the screen.
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
【问题讨论】:
请注意,0x8CD6 是GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES
(参见 glext.h)。
那么...我做错了什么?我该如何解决?
查看此问题中的代码:***.com/questions/22548208/… 它应该会有所帮助。关键是在将纹理绘制到屏幕外 FBO 之后,需要重新绑定回之前的默认帧缓冲区。然后你绑定之前的纹理,然后在屏幕上绘制它。希望这会有所帮助。
【参考方案1】:
问题很简单:您忘记了在屏幕上绘图。您知道,默认帧缓冲区,当您执行 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
时得到的内容,您在编写此代码之前渲染得很好。
没有“屏幕上”帧缓冲对象这样的东西。根据定义,所有用户定义的 FBO 都在屏幕外。
你根本不应该拥有这个viewFramebuffer
FBO。相反,您应该绘制到纹理,然后使用该纹理绘制到默认帧缓冲区。
【讨论】:
Nicol:通过创建这个“viewFramebuffeR”,他的代码是正确的。 ios 需要有特殊的“viewFramebuffer”。通过渲染它,您正在屏幕上渲染。您可以使用 EAGLContext 类中的 renderbufferStorage 方法,通过附加特殊的渲染缓冲区来创建此帧缓冲区。见这里:developer.apple.com/library/IOs/#documentation/3DDrawing/… 我在另一个question 上看到过类似这样的一些代码,它使用glFramebufferTexture2DOES(),而不是glFramebufferTexture2D()...我真的不明白这个OES 的东西(有很多有和没有这个后缀的函数),但我会尝试使用该代码。 现在我看到当我在上面运行“创建屏幕外帧缓冲区”时收到错误代码 8cd6。不知道有没有帮助... 好吧,现在我设法通过使用不太好但我的游戏可以接受的 glCopyTexImage2D() 动态渲染我的纹理。我只需要在加载时渲染纹理,所以用完我的屏幕缓冲区或滞后游戏不是问题。【参考方案2】:鉴于您获得了GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES
,您至少在创建屏幕外帧缓冲区时遇到了问题。查看您的代码,我看不到为这个屏幕外帧缓冲区创建颜色渲染缓冲区(当渲染到 CAEAGLLayer 时,图层本身会创建颜色渲染缓冲区)。
我相信您需要在屏幕外帧缓冲区创建代码中添加类似以下内容(您需要在此处将OES
后缀添加到一个或多个函数,因为这些来自 OpenGL ES 2.0 应用程序) :
glGenRenderbuffers(1, &renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, bufferSize.width, bufferSize.height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
【讨论】:
但是我想当你渲染到一个纹理时,你不需要设置一个颜色缓冲区。我没有见过这样的例子。 @HLorenzi - 我一直假设具有纹理目标的 FBO 仍然需要颜色渲染缓冲区,因此有一个目标可以将场景渲染到其中。也许我错了。使用您的 FBO 创建仍然存在问题,需要先处理好,然后才能正常工作。可能是因为没有上下文处于活动状态,如下所述:***.com/a/2907636/19679以上是关于OpenGL 中的离屏帧缓冲区的主要内容,如果未能解决你的问题,请参考以下文章