OpenGL帧缓冲区:可以清除它,但不能绘制它
在 Mac 上,我有一个 OpenGL 设置,除了帧缓冲区外,它工作得很好 - 纹理工作等。所以我知道纹理已启用,我有一个有效的上下文,等等。所有工作都完美,直到我尝试创建一个帧缓冲区。
我使用 glGenFramebuffers、glBindFramebuffer 和 glFramebufferTexture2D 创建了一个帧缓冲区,并且 glCheckFramebufferStatus 返回 GL_FRAMEBUFFER_COMPLETE。如果我随后调用 glClear,然后调用 glGetTexImage,则返回的数据显示 glClear 按其应有的方式作用于绑定到帧缓冲区的纹理。我可以将 glClearColor 设置为我想要的任何内容,并且 glClear 正确设置纹理数据。
但好消息就到此为止了。无论我使用 VBO 还是 glBegin/glEnd,我都无法将任何内容绘制到帧缓冲区中。绑定到帧缓冲区的纹理中的纹理数据不会受到绘制调用的影响(尽管 glClear 结果仍然出现)。即使我在调用 glGetTexImage 之前调用 glFlush 和 glFinish 也是如此。另外,glGetError 对于我的任何调用都没有返回错误。
我在下面发布了一些示例代码,这些代码是我在程序中的相关点添加的,只是为了尝试解决这个问题,以防给任何人一个想法。 (这不包括 glClear 调用,但我从同一点的单独测试中知道它可以正常工作)。
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbTexID, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
Debugger();
glEnable(GL_TEXTURE_2D);
glCullFace(GL_NONE);
glGenTextures(1,(GLuint*)&tex);
glBindTexture(GL_TEXTURE_2D,tex);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,1024,1024,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1024, 1024, 0, -5000, 5000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, 1024, 1024);
glColor4f(1,1,1,1);
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(1024, 0);
glTexCoord2f(0, 1);
glVertex2f(0, 1024);
glEnd();
glFlush();
glFinish();
unsigned char *dd = new unsigned char[1024*1024*4];
glBindTexture(GL_TEXTURE_2D, fbTexID); //I've tried calling glBindFramebuffer(GL_FRAMEBUFFER,0) before this bind - makes no difference
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, dd);
delete dd;
On a Mac, I've got an OpenGL setup that is working just fine apart from framebuffers - texturing works, etc. So I know that texturing is enabled, I have a valid context, etc. All works flawlessly until I try to create a framebuffer.
I created a framebuffer with glGenFramebuffers, glBindFramebuffer, and glFramebufferTexture2D, and glCheckFramebufferStatus is returning GL_FRAMEBUFFER_COMPLETE. If I then call glClear, followed by a call to glGetTexImage, the returned data shows that the glClear acted on the texture bound to the framebuffer just as it should. I can set glClearColor to anything I want, and the glClear sets the texture data correctly.
But that's where the good news stops. I can't draw anything into the framebuffer, whether I use VBOs or glBegin/glEnd. The texture data from the texture bound to the framebuffer is untouched by the draw calls (though the glClear results still appear). This is all true even if I call glFlush and glFinish before the glGetTexImage call. Also, glGetError is returning no error as to any of my calls.
I've posted below some sample code that I added at a relevant point in the program just to try to work on this issue, in case that gives anyone an idea. (This doesn't include the glClear call, but I know from separate testing at the same point that that works OK).
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbTexID, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
Debugger();
glEnable(GL_TEXTURE_2D);
glCullFace(GL_NONE);
glGenTextures(1,(GLuint*)&tex);
glBindTexture(GL_TEXTURE_2D,tex);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,1024,1024,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1024, 1024, 0, -5000, 5000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, 1024, 1024);
glColor4f(1,1,1,1);
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(1024, 0);
glTexCoord2f(0, 1);
glVertex2f(0, 1024);
glEnd();
glFlush();
glFinish();
unsigned char *dd = new unsigned char[1024*1024*4];
glBindTexture(GL_TEXTURE_2D, fbTexID); //I've tried calling glBindFramebuffer(GL_FRAMEBUFFER,0) before this bind - makes no difference
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, dd);
delete dd;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的纹理不起作用,因为它已被绑定!
您不能将 FBO 上的绑定纹理作为渲染目标!
这是没有太多记录的事情,但是当你思考它时就有意义了
驱动程序开发人员也需要一些保护措施,以防万一您做了一些奇怪的事情,例如同时读取和写入同一纹理
Your texture did not work because it was bound!
You cannnot have a bound texture work on a FBO as a rendertarget!
This is something that isn't very documented, but makes sense when you think about it
The driver developers need some safeguards too, just in case you do something weird like reading and writing to the same texture at the same time
好的,回答了我自己的问题。看来您生成的作为帧缓冲区绘制的表面的纹理必须在生成帧缓冲区之后生成。所以,这可行:
但这不行:
我在任何地方都没有看到这个问题,这似乎令人惊讶,但我的代码仅通过移动纹理的生成就从不工作变为工作。
OK, answered my own question. It seems that the texture you generate to be the surface that the frame buffer draws to must be generated after the frame buffer is generated. So, this works:
but this does not:
I don't see this addressed anywhere, and it seems surprising, but my code went from not working to working just by moving the generation of the texture.
这是我前段时间写的 FBO 测试:
也许这个参考有帮助
This is a FBO test I wrote some time ago:
Maybe this reference helps
这是我不久前编写的 FBO“基准”。
set_fbo_size()
有一个 Works For Me(TM) 的创建序列。Here's a FBO "benchmark" I wrote a while ago.
set_fbo_size()
has a creation sequence that Works For Me(TM).