views:

678

answers:

3

I'm trying to create an offscreen render buffer in OpenGL ES on the iPhone. I've created the buffer like this:

     glGenFramebuffersOES(1, &offscreenFramebuffer);
 glBindFramebufferOES(GL_FRAMEBUFFER_OES, offscreenFramebuffer);

 glGenRenderbuffersOES(1, &offscreenRenderbuffer);
 glBindRenderbufferOES(GL_RENDERBUFFER_OES, offscreenRenderbuffer);
 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, offscreenRenderbuffer);

But I'm confused on how to render the storage. Apple's documentation says to use the EAGLContext renderBufferStorage:fromDrawable: method, but this seems to only work for one render buffer (the main one being displayed). If I use the normal OpenGL function glRenderBufferStorageOES, then I can't seem to get it to display. Here's the code:

     // this is in the initialization section:
 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGB8_OES, backingWidth, backingHeight);

 // and this is when I'm trying to draw to it and display it:
 glBindFramebufferOES(GL_FRAMEBUFFER_OES, offscreenFramebuffer);
 GLfloat vc[] = {
  0.0f, 0.0f, 0.0f,
  10.0f, 10.0f, 10.0f,
  0.0f, 0.0f, 0.0f,
  -10.0f, -10.0f, -10.0f,   
 };

 glLoadIdentity();
 glEnableClientState(GL_VERTEX_ARRAY);
 glVertexPointer(3, GL_FLOAT, 0, vc);
 glDrawArrays(GL_LINES, 0, 4);
 glDisableClientState(GL_VERTEX_ARRAY);

 glBindRenderbufferOES(GL_RENDERBUFFER_OES, offscreenRenderbuffer);
 [context presentRenderbuffer:GL_RENDERBUFFER_OES];

Doing it this way, nothing is displayed on the screen. However, if I switch out the references to "offscreen...Buffer" to the buffers that were created with the renderBufferStorage method, it works fine.

Any suggestions?

+1  A: 

You cannot present an normal renderbuffer (created with glRenderbufferStorage), it is always offscreen. presentRenderbuffer: can only be used for renderbuffers that were created using the renderbufferStorage:fromDrawable:. If you checked the return value of that presentRenderbuffer:, you should observe it failing.

What are you trying to do?

Frogblast
I'm writing a game in which I'm drawing things to the screen that should be persistent from frame to frame. I would like to draw these persistent things to an offscreen buffer, and then on each frame "blit" this to the screen and draw the non-persistent/volatile things on top of it. I would really like to avoid having to maintain a list of the persistent objects and re-create them each frame, since the number of objects could get unwieldy very quickly.
David Ensminger
+1  A: 

Since you can't use presentRenderbuffer with an offscreen FBO, you should associate it with a texture object using glFramebufferTexture2DOES, then render a textured full-screen quad.

prideout
A: 

@david good idea.. what you need to do is what @prideout said.. create a texture and render to it.. and use the texture on a quad every time. Make sure you draw to the texture only once, as in your case things are persistent.

- (void)setUpTextureBuffer 
{
 glGenFramebuffersOES(1, &texturebuffer); 
 glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturebuffer);

 // create the texture
 glGenTextures(1, &canvastexture); 
 glBindTexture(GL_TEXTURE_2D, canvastexture); 
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, canvastexture, 0);

 GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); 
 if(status != GL_FRAMEBUFFER_COMPLETE_OES) { 
  NSLog(@"failed to make complete framebuffer object %x", status);
 }

 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

 glClearColor(1.0, 1.0, 1.0, 1.0);
 glViewport(0, 0, 512, 512);
 glClear(GL_COLOR_BUFFER_BIT);
}



//setTargetToTexture() function

 glBindFramebufferOES(GL_FRAMEBUFFER_OES, tbuffer);
 glBindTexture(GL_TEXTURE_2D, allbrushes);
 glViewport(0, 0, 512, 512);

//reset pointers after finishing drawing to textures

 glViewport(0, 0, BWIDTH, BHEIGHT);
 glVertexPointer(2, GL_FLOAT, 0, canvas);   //canvas vertices
 glTexCoordPointer(2, GL_FLOAT, 0, texels);
 glBindTexture(GL_TEXTURE_2D, boundtexture);   //bind to the texture which is the special render target 
 glBindFramebufferOES(GL_FRAMEBUFFER_OES, fbuffer); //back to normal framebuffer
Quakeboy