0

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);
Noam M
  • 3,156
  • 5
  • 26
  • 41
shrekshao
  • 388
  • 4
  • 12
  • Have to tried rendering onto a texture and display a quad with it in your scene? Would be good to make sure your framebuffer is working. – Iggy Sep 21 '14 at 21:11
  • Also ensure - by leaving the system framebuffer active - that you really draw anything visible (happens all the time...) ;) If this and @Iggy 's solution don't help use e.g. [gDebugger](http://www.gremedy.com/) to have a look into your renderbuffer contents to be sure your savePNG is not the problem... – Thomas Sep 21 '14 at 21:20
  • Thanks, I've updated my savePNG code... @lggy can you share a link on how to render to texture? – shrekshao Sep 21 '14 at 21:26

1 Answers1

5

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);
    
Reto Koradi
  • 53,228
  • 8
  • 93
  • 133
  • Thank you! I've updated the related code in savePNG, I've also corrected the site I followed. I've changed `GL_RGBA8` but still not working. The `glCheckFramebufferStatus(GL_FRAMEBUFFER)` returns 36053 – shrekshao Sep 21 '14 at 21:56
  • @shrekshao: You should always print out OpenGL enum values in hexadecimal, that will make looking them up a lot easier. In this case, that corresponds to **0x8CD5**, which is `GL_FRAMEBUFFER_COMPLETE`. Nobody's going to know what that number is by itself though, especially in base-10 ;) – Andon M. Coleman Sep 21 '14 at 22:06
  • 36053 is `GL_FRAMEBUFFER_COMPLETE`, so that part should be fine. If you set the read framebuffer, you should be getting data. Also make sure that your `viewport.w` and `viewport.h` values are correct. – Reto Koradi Sep 21 '14 at 22:07
  • Thanks. viewport.w = 400 , viewport.h =400, I get a 400x400 png . I think this part is right. But my image is still black. Is the problem within my drawing part? I only use `glBegin(GL_POINT)`, `glColor3f`, `glVertex2f` in drawing @RetoKoradi – shrekshao Sep 21 '14 at 23:06
  • Try setting the clear color to something other than black, using `glClearColor()`. Then you'll see if the reading works without needing any drawing. Did you bind `GL_READ_FRAMEBUFFER`? – Reto Koradi Sep 21 '14 at 23:27
  • @RetoKoradi Yes, the `glClearColor()` works. I saw the change in the color in the output image. And I do bind `GL_READ_FRAMEBUFFER`. So the problem is with the drawing? I might try some other drawing commands. Thanks. – shrekshao Sep 21 '14 at 23:47