Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 8 of 8

Thread: Having trouble with 2nd layer / nested FrameBufferObjects

Hybrid View

  1. #1
    Junior Member Newbie
    Join Date
    Feb 2013
    Posts
    5

    Having trouble with 2nd layer / nested FrameBufferObjects

    I'm trying to render to a FrameBufferObject, and then render that to another FrameBufferObject. Since I couldn't get it working in my game engine, I ran out to the net and cobbled together a really basic example in order to remove impacting variables. Even after this, I just can't get it. See here:

    Code :
        uint16 mDisplayHeight = 1000;
        uint16 mDisplayWidth = 1600;
        int32 mVideoFlags;
     
        // Init SDL
        SDL_Init(SDL_INIT_VIDEO);
        mVideoFlags  = SDL_OPENGL;          // Use OpenGL in SDL
        mVideoFlags |= SDL_HWPALETTE;       // Hardware enabled palette
        const SDL_VideoInfo* sdlVideoInfo = SDL_GetVideoInfo();
        if (sdlVideoInfo->hw_available)
            mVideoFlags |= SDL_HWSURFACE;   // Hardware enabled surfaces
        else
            mVideoFlags |= SDL_SWSURFACE;   // Software enabled surfaces
        if (sdlVideoInfo->blit_hw)
            mVideoFlags |= SDL_HWACCEL;     // Hardware enabled blitting
        SDL_SetVideoMode(mDisplayWidth, mDisplayHeight, 32, mVideoFlags);
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
        SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
     
        // Initialize OpenGL
        glewInit();
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glDisable(GL_DEPTH_TEST);
     
        /** First FBO - The Render One **/
        uint32 mFinalFBOTexID = 0;
        uint32 mFinalFBOID = 0;
        glGenFramebuffers(1, &mFinalFBOID);
        glBindFramebuffer(GL_FRAMEBUFFER, mFinalFBOID);
        glGenTextures(1, &mFinalFBOTexID);
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mFinalFBOTexID);
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, mDisplayWidth,
                     mDisplayHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB,
                               mFinalFBOTexID, 0);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        /****/
     
        /** Second FBO - Intermediate **/
        uint32 mSecondRenderTextureID = 0;
        uint32 mSecondRenderTextureFBO = 0;
        glGenFramebuffers(1, &mSecondRenderTextureFBO);
        glBindFramebuffer(GL_FRAMEBUFFER, mSecondRenderTextureFBO);
        glGenTextures(1, &mSecondRenderTextureID);
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mSecondRenderTextureID);
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 300,
                     300, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB,
                               mSecondRenderTextureID, 0);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        /****/
     
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, mDisplayWidth, mDisplayHeight, 0, -1, 1);
        glMatrixMode(GL_MODELVIEW);
     
        glEnable(GL_TEXTURE_RECTANGLE_ARB);
     
        // Execution Loop
        while(true)
        {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
            glBindFramebuffer(GL_FRAMEBUFFER, mFinalFBOID); // X1
            //glBindFramebuffer(GL_FRAMEBUFFER, mSecondRenderTextureFBO); //  X2
     
            // Draw a quad
            glDisable(GL_TEXTURE_RECTANGLE_ARB);
            glColor3f(1.0f, 1.0f, 0.0f);
            glBegin(GL_QUADS);
                glVertex2i(10, 10);
                glVertex2i(50, 10);
                glVertex2i(50, 50);
                glVertex2i(10, 50);
            glEnd();
            glEnable(GL_TEXTURE_RECTANGLE_ARB);
     
            /* X2
            glBindFramebuffer(GL_FRAMEBUFFER, mFinalFBOID);
            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mSecondRenderTextureID);
     
            glBegin(GL_QUADS);
                glTexCoord2i(0, 100);
                glVertex2i(0, 0);
                glTexCoord2i(100, 100);
                glVertex2i(100, 0);
                glTexCoord2i(100, 0);
                glVertex2i(100, 100);
                glTexCoord2i(0, 0);
                glVertex2i(0, 100);
            glEnd();
            */
     
            // Draw the 2D Layer on top
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
            glLoadIdentity();
            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mFinalFBOTexID);
     
            glBegin(GL_QUADS);
                glTexCoord2i(0, mDisplayHeight);
                glVertex2i(0, 0);
                glTexCoord2i(mDisplayWidth, mDisplayHeight);
                glVertex2i(mDisplayWidth, 0);
                glTexCoord2i(mDisplayWidth, 0);
                glVertex2i(mDisplayWidth, mDisplayHeight);
                glTexCoord2i(0, 0);
                glVertex2i(0, mDisplayHeight);
            glEnd();
     
            // Present the information
            SDL_GL_SwapBuffers();
        }

    This code renders a yellow quad without any problems. But, if I uncomment the two X2 blocks and comment out the X1 block, I get a black screen. I can't seem to figure out how to paint to and render that second FBO. What am I missing?
    Last edited by Necreia; 02-14-2013 at 07:11 PM.

  2. #2
    Junior Member Regular Contributor
    Join Date
    Jun 2012
    Posts
    190
    For x1 you have created mFinalFBOTexID and while rendering on default FBO you are binding this texture which is as per expected. But in x2, looks like you have created another texture "mSecondRenderTextureID" and while rendering on default FBO you are binding mFinalFBOTexID. i assume you dont have another texture rendered on x2 which is "mSecondRenderTextureID", if this is so you must bind mFinalFBOTexID to x2 and not mSecondRenderTextureID.

    One more, make sure that you have appropriate height width in glTexImage2D call for second FBO. Try changing it to as per glTeximage2D call for 1st FBO.

  3. #3
    Junior Member Newbie
    Join Date
    Feb 2013
    Posts
    5
    Good catch. After some tinkering and your direction, it now works. So that googlers can pull up a working example-- this works:

    Code :
        uint16 mDisplayHeight = 1000;
        uint16 mDisplayWidth = 1600;
        int32 mVideoFlags;
     
        // Init SDL
        SDL_Init(SDL_INIT_VIDEO);
        mVideoFlags  = SDL_OPENGL;          // Use OpenGL in SDL
        mVideoFlags |= SDL_HWPALETTE;       // Hardware enabled palette
        const SDL_VideoInfo* sdlVideoInfo = SDL_GetVideoInfo();
        if (sdlVideoInfo->hw_available)
            mVideoFlags |= SDL_HWSURFACE;   // Hardware enabled surfaces
        else
            mVideoFlags |= SDL_SWSURFACE;   // Software enabled surfaces
        if (sdlVideoInfo->blit_hw)
            mVideoFlags |= SDL_HWACCEL;     // Hardware enabled blitting
        SDL_SetVideoMode(mDisplayWidth, mDisplayHeight, 32, mVideoFlags);
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
        SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
     
        // Initialize OpenGL
        glewInit();
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glDisable(GL_DEPTH_TEST);
     
        // Create the frame buffers and textures
        unsigned int mFrameBufferTexIDs[2];
        unsigned int mFrameBufferObjectIDs[2];
        for (int i = 0; i < 2; i++)
        {
            glGenFramebuffers(1, &mFrameBufferObjectIDs[i]);
            glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferObjectIDs[i]);
            glGenTextures(1, &mFrameBufferTexIDs[i]);
            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mFrameBufferTexIDs[i]);
            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, mDisplayWidth, mDisplayHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, mFrameBufferTexIDs[i], 0);
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
        }
     
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, mDisplayWidth, mDisplayHeight, 0, -1, 1);
        glMatrixMode(GL_MODELVIEW);
     
        // Framebuffer and texture arrays are as follows:
        // 0 : Final output (what I want to present to the screen)
        // 1 : Intermediate output (what I want to render to and then render THAT to the screen)
        bool renderToIntermediateFBO = true;
     
        while(true)
        {
            if (renderToIntermediateFBO == false)
            {
                glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferObjectIDs[0]);
     
                // Draw a quad with no texture
                glDisable(GL_TEXTURE_RECTANGLE_ARB);
                glColor3f(1.0f, 1.0f, 0.0f);
                glBegin(GL_QUADS);
                    glVertex2i(10, 10);
                    glVertex2i(50, 10);
                    glVertex2i(50, 50);
                    glVertex2i(10, 50);
                glEnd();
                glEnable(GL_TEXTURE_RECTANGLE_ARB);
            }
            else
            {
                glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferObjectIDs[1]);
     
                // Draw a quad with no texture
                glDisable(GL_TEXTURE_RECTANGLE_ARB);
                glColor3f(1.0f, 1.0f, 0.0f);
                glBegin(GL_QUADS);
                    glVertex2i(10, 10);
                    glVertex2i(50, 10);
                    glVertex2i(50, 50);
                    glVertex2i(10, 50);
                glEnd();
                glEnable(GL_TEXTURE_RECTANGLE_ARB);
     
                // Draw the intermediate FBO onto the final FBO
                glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferObjectIDs[0]);
                glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mFrameBufferTexIDs[1]);
                glBegin(GL_QUADS);
                    glTexCoord2i(0, mDisplayHeight);
                    glVertex2i(0, 0);
                    glTexCoord2i(mDisplayWidth, mDisplayHeight);
                    glVertex2i(mDisplayWidth, 0);
                    glTexCoord2i(mDisplayWidth, 0);
                    glVertex2i(mDisplayWidth, mDisplayHeight);
                    glTexCoord2i(0, 0);
                    glVertex2i(0, mDisplayHeight);
                glEnd();
     
                // Draw another untextured quad on the final FBO
                glDisable(GL_TEXTURE_RECTANGLE_ARB);
                glColor3f(0.0f, 1.0f, 1.0f);
                glBegin(GL_QUADS);
                    glVertex2i(20, 20);
                    glVertex2i(60, 20);
                    glVertex2i(60, 60);
                    glVertex2i(20, 60);
                glEnd();
                glEnable(GL_TEXTURE_RECTANGLE_ARB);
            }
     
            // Present the final information to the screen
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
            glLoadIdentity();
            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mFrameBufferTexIDs[0]);
            glColor3f(1.0f, 1.0f, 1.0f);
            glBegin(GL_QUADS);
                glTexCoord2i(0, mDisplayHeight);
                glVertex2i(0, 0);
                glTexCoord2i(mDisplayWidth, mDisplayHeight);
                glVertex2i(mDisplayWidth, 0);
                glTexCoord2i(mDisplayWidth, 0);
                glVertex2i(mDisplayWidth, mDisplayHeight);
                glTexCoord2i(0, 0);
                glVertex2i(0, mDisplayHeight);
            glEnd();
            SDL_GL_SwapBuffers();
        }

  4. #4
    Junior Member Regular Contributor
    Join Date
    Jun 2012
    Posts
    190
    Glad to hear that

  5. #5
    Junior Member Newbie
    Join Date
    Feb 2013
    Posts
    5
    Hmm, well-- this does still leave me with a question. How do I perform this sort of logic with different sized framebufferobjects? If I flip the intermediate Texture to 512x512, I can't get it to work anymore. Is there something else I need to be doing to make FBO's different sizes? Is that even supported?

  6. #6
    Junior Member Regular Contributor
    Join Date
    Jun 2012
    Posts
    190
    AFIK, you can't have texture size greater than that of your attachments, plus all your attachments to FBO should be of equal sizes. But you can create texture of lower size than your FBOs so that at-least you wont get any fault during run but it will left you with loss of FBO data.
    So i would suggest if you have textures of varying sizes, make sure that your FBOs have size greater than your largest possible value of texture size.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •