3
votes

I'm creating an iPhone game using OpenGL, and I want to draw onto an offscreen framebuffer, then using that framebuffer as a texture for drawing on the actual screen. I based my code off Apple's and the GLSprite example, but it seems I'm not doing it right when it comes to switching the drawing target, as I only get a blank texture. The code I'm using is below. What is wrong? What is the best way to render a texture on the fly?

The Creating an Offscreen Framebuffer below is giving me the 8cd6 error code.

Creating the Screen Framebuffer

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;
}

Creating an Offscreen Framebuffer

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);
}

Drawing, Loop:

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];
2
As a note, 0x8CD6 is GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES (see glext.h).Brad Larson♦
So... What am I doing wrong? How do I fix it?HLorenzi
Check out the code in this question: stackoverflow.com/questions/22548208/… it should helps. The key point is after you draw texture to offscreen FBO, you need to rebind back to the previous default framebuffer. And then you bind the previous texture and then draw it on screen. Hope this helps.Zhao

2 Answers

4
votes

The problem is simple: you've forgotten to draw to the screen. You know, the default framebuffer, what you get when you do glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); The thing you were rendering to just fine before writing this code.

There is no such thing as a "onscreen" framebuffer object. All user-defined FBOs are by definition, off-screen.

You shouldn't have this viewFramebuffer FBO at all. Instead, you should draw to your texture, then use that texture to draw to the default framebuffer.

0
votes

Given that you're getting a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES, you at least have a problem with the creation of your offscreen framebuffer. Looking at your code, nowhere do I see the creation of a color renderbuffer for this offscreen framebuffer (when rendering to a CAEAGLLayer, the layer itself creates the color renderbuffer).

I believe that you'll need to add something like the following in your offscreen framebuffer creation code (you will need to add the OES suffix to one or more functions here, because these are from an OpenGL ES 2.0 application):

    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);