I am getting into FBOs (Framebuffer Objects) in openGL. Right now, I'm simply trying to render something to an FBO, then use the texture associated with it to render that image to the screen. I have been working on this problem for hours today and yesterday. I've tried copying as closely as I can two different examples, and yet I still have the same problem. I am absolutely stuck.
It seems like what is happening is that the framebuffer object is not actually being binded. In the code, I have two sets of glClear() and glClearColor() commands: the first for drawing to the framebuffer, and the second for drawing to the screen. However, when I comment out the second set, the first set is clearly affecting the screen. If the FBO is binded, shouldn't it receive those commands, and not affect the actual output to the screen directly?
To begin, I use glewInit(), and then I create an FBO, and then a Renderbuffer object and a texture to associate with it, and do all of the necessary steps to put it all together:
glewInit();
int width=512,height=512;
glGenFramebuffers(1, &fbo);
glGenRenderbuffers(1, &rbo);
glGenTextures(1, &fboTex);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindTexture(GL_TEXTURE_2D, fboTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_INT, NULL);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(status==GL_FRAMEBUFFER_COMPLETE);
glBindTexture(GL_TEXTURE_2D,0);
glBindFramebuffer(GL_FRAMEBUFFER,fbo);
Then, I draw to the framebuffer object.
glClearColor(0.5,0.5,0.5,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glColor4f(1.0,0,0,1);
glBegin(GL_QUADS);
glVertex2f(100,100);
glVertex2f(200,100);
glVertex2f(200,250);
glVertex2f(100,200);
glEnd();
I then unbind each of the following three objects:
glBindFramebuffer(GL_FRAMEBUFFER,0);
glBindRenderbuffer(GL_RENDERBUFFER,0);
glBindTexture(GL_TEXTURE_2D,0);
Then I attempt to draw the texture to the window:
glEnable(GL_TEXTURE_2D);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTextureEXT(GL_TEXTURE_2D, fboTex);
glBegin(GL_QUADS);
glTexCoord2f(0,0);glVertex3f(-.5,-.5,0);
glTexCoord2f(1,0);glVertex3f(.5,-.5,0);
glTexCoord2f(1,1);glVertex3f(.5,.5,0);
glTexCoord2f(0,1);glVertex3f(-.5,.5,0);
glEnd();
glDisable(GL_TEXTURE_2D);
glFlush();
This has got to be either some really simple mistake or misunderstanding that somehow evaded eradication when I retyped all this twice, or a driver issue? My driver is supposed to be able to run version 3.2 of openGL...
Any help on this frustrating issue would be great.
EDIT: I found out what I was ultimately doing wrong. I didn't realize that glColor commands affected any drawing done, regardless of whether you have a framebuffer binded at the time or not. I needed to change the glColor back to (1,1,1) after drawing to the FBO, in order to render the FBO's texture later with all of its color.
Without a full code example it's difficult to see what's wrong. For kickstarting your FBO endeavors I provide https://github.com/datenwolf/codesamples/tree/master/samples/OpenGL/minimalfbo
Related
I have a scene with a teapot mesh in it.
I'm using a framgment shader to light it using a source of light whose value is equal to 10.
When the scene is rendered to the default framebuffer, everything seems to be fine.
But, if it's rendered in a custom framebuffer, the result looks like this :
OpenGL seems to prefer triangles defined "at the end of" the mesh.
I want the framebuffer to contain 16bits floats so I can store values larger than 1.0.
Sorry for my English.
I forgot to add a depth renderBuffer and clear it using glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
To do so, add :
GLuint rboDepth;
glGenRenderbuffers(1, &rboDepth);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width(), height());
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
to your framebuffer implementation while it's bound.
Why is "glRenderbufferStorageMultisample" giving me an invalid operation error (1282)?
I'm trying to render a scene into a Multisampled FBO with color/depth buffers only (no textures here) & then resolve that Multisampled FBO into a simple FBO that has color/depth textures, but OpenGL just won't let me...
glEnable(GL_MULTISAMPLE);
glGenFramebuffers(1, &m_Id);
glBindFramebuffer(GL_FRAMEBUFFER, m_Id);
glGenRenderbuffers(1, &m_ColorId);
glBindRenderbuffer(GL_RENDERBUFFER, m_ColorId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numOfSamples, GL_RGBA8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_ColorId);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
The line that gives me error is "glRenderbufferStorageMultisample", interestingly enough though "glRenderbufferStorage" doesn't...
According to the documentation at: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glRenderbufferStorageMultisample.xhtml, you should check the values of your parameters (used for the glRenderbufferStorageMultisample call against) some OpenGL macros.
Based on the details provided, a check on numOfSamples value (currently 32) it's my best suggestion. I believe it may be too high.
The maximum value for numOfSamples may be even limited by the capabilities of your video card.
Hope this may help,
Stefano
windows
using glew
I'm trying to render offscreen and save the img opengl rendered to a png file.
I followed a highly rated answer on stackoverflow:
How to render offscreen on OpenGL?
But the png file I get is only a black screen.
Here's my code relating to it:
glutCreateWindow(argv[0]);
if(GLEW_OK!=glewInit())
{
return -1;
}
initScene();
GLuint fbo, render_buf;
glGenFramebuffers(1,&fbo);
glGenRenderbuffers(1,&render_buf);
glBindRenderbuffer(GL_RENDERBUFFER,render_buf);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, viewport.w, viewport.h);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_buf);
//Before drawing
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo);
glClear(GL_COLOR_BUFFER_BIT); // clear the color buffer
glMatrixMode(GL_MODELVIEW); // indicate we are specifying camera transformations
glLoadIdentity(); // make sure transformation is "zero'd"
//draw...
//glBegin(GL_POINTS) glColor3f, glVertex2f
//glFlush();
glFinish();
/*glutDisplayFunc(myDisplay);
glutPostRedisplay();*/
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
savePNG(outputPNGName,0,0,viewport.w,viewport.h);
//At deinit:
glDeleteFramebuffers(1,&fbo);
glDeleteRenderbuffers(1,&render_buf);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,0);
How to solve the problem?
Thank you
savePNG (related code):
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *)image);
There are at least two problems in this code:
GL_RGB8 is not a valid format for a renderbuffer. From the glRenderbufferStorage() man page:
internalformat specifies the internal format to be used for the renderbuffer object's storage and must be a color-renderable, depth-renderable, or stencil-renderable format.
Table 8.13 in the latest spec document (4.5, downloadable from https://www.opengl.org/registry) lists all formats, with a column showing which of them are color-renderable. RGB8 does not have a checkmark in that column. You can use GL_RGBA8 instead, which is color-renderable.
You may also want to check out the glCheckFramebufferStatus() function, which allows you to check if your framebuffer setup is valid.
While we don't see the code for savePNG(), there is no way it can know that you want to read the pixel data from your FBO. It will most likely use glReadPixels(), which reads data from the current read framebuffer, while your code only sets the draw framebuffer. Before calling savePNG(), add this call to set the read framebuffer to your FBO:
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
I have been trying to implement deferred rendering for 2 weeks. But all of the meshes in my test program are culled reversely. The code above should be the correct way to render a model. Every example i looked at draws the objects like that. But here is the result when i use GL_BACK as cull face:
And this is the GL_FRONT:
GL_FRONT should have been the result i expected from GL_BACK. Strange thing is when I set glFrontFace to GL_CW, everything disappears. So this problem is not about winding. I spent all my day on searching information about this. Only thing i found is something about depth buffers. But I can't see any problems in creation. Just because of this problem, I can't correctly do stencil pass for spot light rendering. I enable GL_DEPTH_TEST in geometry pass. This is what i attach to my fbo as depth buffer
glGenRenderbuffers(1, &depthTexture);
glBindRenderbuffer(GL_RENDERBUFFER, depthTexture);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthTexture);
The main question is, what are the possibilities that would cause a reversed backface culling ?
I need to be able to render with multiple processes at same time, using OpenGL.
I'm using FBO to render into a texture. I read the pixels by glGetTexImage() multiple times in that one process (tiled rendering).
Then I launched multiple programs to run at same time and noticed that sometimes it works and sometimes it doesn't. Sometimes the whole image is corrupted (repeats only one tile), sometimes only small part is corrupted. I also noticed earlier that I was not able to use 4096x4096 size FBO texture for some reason, and the errors from that texture size was same as this "multiple processes at once" tiling error, so I thought it could be something to do with the program trying to get a texture that is not yet fully rendered at all? I also noticed that the smaller texture I use, the more processes I can run at the same time. My GFX card memory is 256 MB I think. But even with 8 processes of 1024x1024 size texture size it uses only 33 MB of memory at worst, so it cant be my GFX card memory limitations.
The tiling error looks like it doesn't get the new tile pixel data, so it uses the old buffer again.
What can I do to prevent the corruption of my rendering?
Here is my rendering code structure:
for(y...){
for(x...){
// set viewport & translatef
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
// glclear()
render_tile();
glFlush();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, textureId);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
glBindTexture(GL_TEXTURE_2D, 0);
copy_tile_pixels_to_output_image();
}
}
And here is the FBO initialization (only opengl related commands are shown):
// texture:
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
// FBO:
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, TEXTURE_WIDTH, TEXTURE_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboId);
checkFramebufferStatus(); // will exit if errors found. none found, however.
glBindFramebuffer(GL_FRAMEBUFFER, 0);
Edit: as datenwolf noticed, the problem goes away by using glReadPixels(). But im not still sure why, so it would be good to know whats happening under the hood, to be sure it will not make such errors in any case in the future!
The FBO itself is just an abstract object without its own backing image storage. Basically the FBO itself consists of only slots into which you can plug image sinks and sources. Textures can act as such, but there are also renderbuffers, which serve kind of the same purpose, but cannot be used as a texturing sample source
You can read back directly from a bound FBO using glReadPixels.