Minimal example for creating FBO using OpenGL ES 2.0 on iOS

13,276

Found a solution, and I have updated the code below in case it is useful for someone.

https://github.com/glman74/simpleFBO/

The main issue is that I needed to call in main render:

// reset to main framebuffer
[((GLKView *) self.view) bindDrawable];   

This is because I was using GLKView. The situation is different from the CAEAGLLayer examples.

Share:
13,276
M-V
Author by

M-V

Updated on June 23, 2022

Comments

  • M-V
    M-V almost 2 years

    I am having trouble creating an FBO, and then using that as a texture in my iOS app. I've uploaded a stripped down version of my app on github, which shows the problem. I get just a blank screen with a weird color which I never set. Checking status shows that the FBO was created successfully.

    https://github.com/glman74/simpleFBO

    I have already looked at related stackoverflow questions, and specifically the link below from datenwolf which shows how to set up an FBO using GLUT, but does not use shaders. I am still not sure what I am doing wrong.

    https://github.com/datenwolf/codesamples/blob/master/samples/OpenGL/minimalfbo/

    I am also appending here relevant parts of the code. In the renderFBO method, I am just doing a clear. I would have expected that this solid colored (green) texture would be used when I am rendering the polygon in the main render.

    FBO setup:

    // intialize FBO
    - (void)setupFBO
    {
        fbo_width = 512;
        fbo_height = 512;
    
        glGenFramebuffers(1, &fboHandle);
        glGenTextures(1, &fboTex);
        glGenRenderbuffers(1, &depthBuffer);
    
        glBindFramebuffer(GL_FRAMEBUFFER, fboHandle);
    
        glBindTexture(GL_TEXTURE_2D, fboTex);
        glTexImage2D( GL_TEXTURE_2D,
                     0,
                     GL_RGBA,
                     fbo_width, fbo_height,
                     0,
                     GL_RGBA,
                     GL_UNSIGNED_BYTE,
                     NULL);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_APPLE, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
    
        glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, fbo_width, fbo_height);
        glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_APPLE, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
    
        // FBO status check
        GLenum status;
        status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        switch(status) {
            case GL_FRAMEBUFFER_COMPLETE:
                NSLog(@"fbo complete");
                break;
    
            case GL_FRAMEBUFFER_UNSUPPORTED:
                NSLog(@"fbo unsupported");
                break;
    
            default:
                /* programming error; will fail on all hardware */
                NSLog(@"Framebuffer Error");
                break;
        }
    
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }
    

    FBO render:

    // render FBO 
    - (void)renderFBO
    {
        glBindTexture(GL_TEXTURE_2D, 0);
        glEnable(GL_TEXTURE_2D);
        glBindFramebuffer(GL_FRAMEBUFFER, fboHandle);
    
        glViewport(0,0, fbo_width, fbo_height);
        glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }
    

    Main Render:

    - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
    {
        // render FBO tex
        [self renderFBO];
    
        glViewport(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
        // render main
        glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        glEnable(GL_TEXTURE_2D);
        glActiveTexture(GL_TEXTURE0);
    
        glUniform1i(uSamplerLoc, 0);     
        // Render 
        glUseProgram(_program);
    
        glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
        glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
    
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
        glDisable(GL_TEXTURE_2D);
    }
    

    An ideas on what I might be doing wrong?

    Edit #1:

    I have made some small changes to my code at github. Tried using GL_FRAMEBUFFER instead of GL_DRAW_FRAMEBUFFER_APPLE above. Also added a bind texture call, which was missing. Still doesn't work.

    Edit #2:

    I found a solution. I needed to call in main render:

    // reset to main framebuffer
    [((GLKView *) self.view) bindDrawable];