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 9 of 9

Thread: Rendering to Multiple Textures Separately

  1. #1
    Intern Contributor
    Join Date
    Jun 2008
    Posts
    63

    Rendering to Multiple Textures Separately

    Hi. I'm trying to render to multiple FBOs with texture storage. Ultimately, the rendered content will change for each, so multiple render targets is not an option. However, with N FBOs, only the last contains the correct color data. Every prior texture contains the default framebuffer color data in a viewport whose size is the same as the default framebuffer's. What would cause this?

    Here's the FBO initialization:
    Code :
      glGenFramebuffers(3, fids);
      glGenTextures(3, tids);
     
      for (int i = 0; i < 3; ++i) {
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fids[i]);
        glActiveTexture(GL_TEXTURE0 + i);
        glBindTexture(GL_TEXTURE_2D, tids[i]);
     
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_FLOAT, NULL);
     
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tids[i], 0);
      }

    The framebuffers are framebuffer complete. Here's the drawing routine:
    Code :
      for (int i = 0; i < 3; i++) {
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fids[i]);
        glViewport(0, 0, 1024, 1024);
        glClear(GL_COLOR_BUFFER_BIT);
        // render a bunch of lines in white
      }
      glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
      // render a bunch of lines in red

    And that leads to this result:


    Only the last FBO's texture is correct. The others contain the default FBO content, sized at 512x512.

    Your wisdom is appreciated.

    - Chris

  2. #2
    Member Regular Contributor
    Join Date
    Oct 2010
    Location
    France
    Posts
    458

    Re: Rendering to Multiple Textures Separately

    Do you draw the same lines each times (for the 3 FBO and for the default buffer) ? If not, all your textures have the same lines, only the color changes.

    Can you try to call to glTexture2D out of the FBO ? Plus, I'm not sure ActiveTexture is usefull inside FBO.

  3. #3
    Intern Contributor
    Join Date
    Jun 2008
    Posts
    63

    Re: Rendering to Multiple Textures Separately

    Yes, I intentionally draw the same lines for now, just using a different color.

    - Chris

  4. #4
    Member Regular Contributor
    Join Date
    Oct 2010
    Location
    France
    Posts
    458

    Re: Rendering to Multiple Textures Separately

    Try to draw different things to ensure what is drawn inside your different FBO.

    For me, everything else is OK (but the texture creation I do outside from FBO).

  5. #5
    Intern Contributor
    Join Date
    Jun 2008
    Posts
    63

    Re: Rendering to Multiple Textures Separately

    It really is the default framebuffer content in textures 1 to N-1. If I don't draw anything to the default framebuffer, I get the clear color in the textures.

    - Chris

  6. #6
    Member Regular Contributor
    Join Date
    Nov 2003
    Location
    Czech Republic
    Posts
    317

    Re: Rendering to Multiple Textures Separately

    The code should work well. Probably the error is elsewhere.

    Few tips:
    - There is no need use more texture units. Just call glActiveTexture(GL_TEXTURE0); once.
    - It does not hurt to call glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); and glBindTexture(GL_TEXTURE_2D, 0); after your init code. It helps avoiding unintentional modification.
    - Try calling glCheckFramebufferStatus after glFramebufferTexture2D(). It should return GL_FRAMEBUFFER_COMPLETE.

  7. #7
    Intern Contributor
    Join Date
    Jun 2008
    Posts
    63

    Re: Rendering to Multiple Textures Separately

    Quote Originally Posted by mfort
    The code should work well. Probably the error is elsewhere.
    What's odd is that this problem first manifested itself in the project that a student of mine was working on. He has a decent ATI card and runs under Windows. He sent me his initialization and draw methods only.

    I took his code and inserted it into a completely separate renderer on my Linux laptop with an NVIDIA GeForce Go 7300 and saw the exact same problem that he did.

    Different manufacturers, drivers, renderers, and developers, same bug. It seems like we're violating the specification somewhere.

    Quote Originally Posted by mfort
    Few tips:
    - It does not hurt to call glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); and glBindTexture(GL_TEXTURE_2D, 0); after your init code. It helps avoiding unintentional modification.
    - Try calling glCheckFramebufferStatus after glFramebufferTexture2D(). It should return GL_FRAMEBUFFER_COMPLETE.
    Binding the default FBO and unbinding the texture after setup has no impact. I do check for framebuffer completeness.

    - Chris

  8. #8
    Member Regular Contributor
    Join Date
    Oct 2010
    Location
    France
    Posts
    458

    Re: Rendering to Multiple Textures Separately

    You use a specific texture unit when creating your FBO. Maybe you should do the same when rendering to the FBO ? Do you have any special reason to use glActiveTexture ?
    At last you can try to not use any texture unit at all.

    I don't think you violate the specifications, maybe just some mismatches.

  9. #9
    Intern Contributor
    Join Date
    Jun 2008
    Posts
    63

    Re: Rendering to Multiple Textures Separately

    I think the problem was a mirage. When I actually apply the textures to geometry, they all look identical and just fine. It's only when I inspect them in gDEBugger that they are wrong.

    I'm going to offer them the following self-contained example that reproduces the problem:

    Code :
    #define GL_GLEXT_PROTOTYPES
    #include <GL/glut.h>
     
    /* ------------------------------------------------------------------------- */
     
    GLuint fids[3];
    GLuint tids[3];
     
    /* ------------------------------------------------------------------------- */
     
    void initialize() {
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
     
      glGenFramebuffers(3, fids);
      glGenTextures(3, tids);
     
      for (int i = 0; i < 3; ++i) {
        glBindTexture(GL_TEXTURE_2D, tids[i]);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fids[i]);
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tids[i], 0);
      }
     
      glBindTexture(GL_TEXTURE_2D, 0);
      glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
      glLineWidth(5.0f);
    }
     
    /* ------------------------------------------------------------------------- */
     
    void display() {
      // Draw horizontal lines to textures
      for (int i = 0; i < 3; i++) {
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fids[i]);
        glViewport(0, 0, 1024, 1024);
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        glBegin(GL_LINES);
        glVertex2f(-1.0f, 0.0f);
        glVertex2f(1.0f, 0.0f);
        glEnd();
      }
     
      glColor3f(1.0f, 0.0f, 0.0f);
     
     
      // Draw vertical line to default FBO
      glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
      glViewport(0, 0, 512, 512);
      glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
      glClear(GL_COLOR_BUFFER_BIT);
      glBegin(GL_LINES);
      glVertex2f(0.0f, -1.0f);
      glVertex2f(0.0f, 1.0f);
      glEnd();
     
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
      glBindTexture(GL_TEXTURE_2D, tids[0]);
      glEnable(GL_TEXTURE_2D);
      glBegin(GL_QUADS);
      glTexCoord2f(0.0f, 0.0f);
      glVertex2f(0.5f, 0.5f);
      glTexCoord2f(1.0f, 0.0f);
      glVertex2f(1.0f, 0.5f);
      glTexCoord2f(1.0f, 1.0f);
      glVertex2f(1.0f, 1.0f);
      glTexCoord2f(0.0f, 1.0f);
      glVertex2f(0.5f, 1.0f);
      glEnd();
      glDisable(GL_TEXTURE_2D);
     
      glutSwapBuffers();
    }
     
    /* ------------------------------------------------------------------------- */
     
    int main(int argc, char **argv) {
      glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
      glutInitWindowSize(512, 512);
      glutInit(&amp;argc, argv);
      glutCreateWindow("Boo, FBOs!");
      initialize();
      glutDisplayFunc(display);
      glutIdleFunc(display);
      glutMainLoop();
     
      return 0;
    }
     
    /* ------------------------------------------------------------------------- */

    - Chris

Posting Permissions

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