3

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];
HLorenzi
  • 480
  • 7
  • 17
  • As a note, 0x8CD6 is `GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES` (see glext.h). – Brad Larson Jan 30 '12 at 19:54
  • So... What am I doing wrong? How do I fix it? – HLorenzi Jan 30 '12 at 20:14
  • Check out the code in this question: http://stackoverflow.com/questions/22548208/render-to-texture-then-render-texture-to-screen-in-ios 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 Sep 12 '15 at 01:08

2 Answers2

4

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.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Nicol: his code is correct by creating this "viewFramebuffeR". iOS requires to have special "viewFramebuffer". By rendering to it, you are rendering on screen. You create this framebuffer by attaching to it special renderbuffer, using renderbufferStorage method from EAGLContext class. See here: http://developer.apple.com/library/IOs/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithEAGLContexts/WorkingwithEAGLContexts.html#//apple_ref/doc/uid/TP40008793-CH103-SW8 – Mārtiņš Možeiko Jan 30 '12 at 05:38
  • I've seen some code on another [question](http://stackoverflow.com/questions/1853551/draw-to-offscreen-renderbuffer-in-opengl-es-iphone) like this, and it used glFramebufferTexture2DOES(), instead of glFramebufferTexture2D()... I don't really get this OES thing (there are many functions with and without this suffix), but I'll try using that code. – HLorenzi Jan 30 '12 at 12:53
  • Now I've seen I'm getting the error code 8cd6 when I run "Creating an Offscreen Framebuffer" above. Don't know if that helps... – HLorenzi Jan 30 '12 at 16:30
  • Well, now I managed to render my texture on the fly by using the not-so-great but acceptable for my game glCopyTexImage2D(). I just need to render the texture at loading time, so using up my screen buffer or lagging the gameplay are not a problem. – HLorenzi Jan 31 '12 at 00:33
0

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); 
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
  • But I thought when you are rendering to a texture, you don't need to set up a color buffer. No examples I've seen does that. – HLorenzi Jan 31 '12 at 00:35
  • @HLorenzi - I'd always operated under the assumption that a color render buffer was still required for FBOs with texture targets, so that there was a target to render the scene into. Perhaps I was wrong. There still is a problem with the creation with your FBO, which needs to be taken care of before anything will work. Perhaps it is due to no context being active, as described here: http://stackoverflow.com/a/2907636/19679 – Brad Larson Jan 31 '12 at 17:26