1

I am trying to draw onto a framebuffer in opengl like I would when drawing directly onto the screen.

I am working off the code presented here: https://stackoverflow.com/a/7324330/681026

I have modified the prepare() method, trying to add in a triangle in the top right corner.

Here is my modified version of the prepare function (the indented parts are the parts I modified):

void prepare()
{   
    static float a=0, b=0, c=0;

    glBindTexture(GL_TEXTURE_2D, 0); 
    glEnable(GL_TEXTURE_2D);
    glBindFramebuffer(GL_FRAMEBUFFER, fb);

    glViewport(0,0,fbo_width, fbo_height);

        glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, 1, 1, 10);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);

    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    glLightfv(GL_LIGHT0, GL_POSITION, light_dir);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color);

    glTranslatef(0,0,-5);

    glRotatef(a, 1, 0, 0); 
    glRotatef(b, 0, 1, 0); 
    glRotatef(c, 0, 0, 1); 

    glutSolidTeapot(0.75);

        glMatrixMode(GL_PROJECTION);
        glPushMatrix();

        glLoadIdentity();
        glOrtho(0, fbo_width, fbo_height, 0, 0, 1); 

        glBegin(GL_TRIANGLES);
        glColor3f(0.0, 1.0, 0.0);
        glVertex3f(0, 0, 0); 
        glVertex3f(1, 0, 0); 
        glVertex3f(0, 1, 0); 
        glEnd();

        glPopMatrix();


    a=fmod(a+0.1, 360.);
    b=fmod(b+0.5, 360.);
    c=fmod(c+0.25, 360.);
}   

That code works when just drawing to the screen, but not here (the triangle is just not there). I suspect it's a simple case of me just not understanding opengl properly. Context here is I'm trying to save a frame drawn by libRocket so it can be redrawn while I update the context in another thread.

EDIT: here's the full code listing:

#include <GL/glew.h>
#include <GL/glut.h>

#include <cmath>
#include <iostream>

using namespace std;

namespace render
{
    int width, height;
    float aspect;

    void init();
    void reshape(int width, int height);
    void display();

    int const fbo_width = 512;
    int const fbo_height = 512;

    GLuint fb, color, depth;
};

void idle();

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );

    glutCreateWindow("FBO test");
    glutDisplayFunc(render::display);
    glutReshapeFunc(render::reshape);
    glutIdleFunc(idle);

    glewInit();

    render::init();
    glutMainLoop();

    return 0;
}

void idle()
{
    glutPostRedisplay();
}

void CHECK_FRAMEBUFFER_STATUS()
{                                                         
    GLenum status;
    status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); 
    switch(status) {
    case GL_FRAMEBUFFER_COMPLETE:
        break;

    case GL_FRAMEBUFFER_UNSUPPORTED:
    /* choose different formats */
        break;

    default:
        /* programming error; will fail on all hardware */
        throw "Framebuffer Error";
    }
}

namespace render
{
    float const light_dir[]={1,1,1,0};
    float const light_color[]={1,0.95,0.9,1};

    void init()
    {
        glGenFramebuffers(1, &fb);
        glGenTextures(1, &color);
        glGenRenderbuffers(1, &depth);

        glBindFramebuffer(GL_FRAMEBUFFER, fb);

        glBindTexture(GL_TEXTURE_2D, color);
        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, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);

        glBindRenderbuffer(GL_RENDERBUFFER, depth);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, fbo_width, fbo_height);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);

        CHECK_FRAMEBUFFER_STATUS();
    }

    void reshape(int width, int height)
    {
        render::width=width;
        render::height=height;
        aspect=float(width)/float(height);
        glutPostRedisplay();
    }

    void prepare()
    {
        static float a=0, b=0, c=0;

        glBindTexture(GL_TEXTURE_2D, 0);
        glEnable(GL_TEXTURE_2D);
        glBindFramebuffer(GL_FRAMEBUFFER, fb);

        glViewport(0,0,fbo_width, fbo_height);

        glClearColor(0.0, 0.0, 0.0, 1.0);
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45, 1, 1, 10);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        glEnable(GL_LIGHT0);
        glEnable(GL_LIGHTING);

        glEnable(GL_DEPTH_TEST);
        glDisable(GL_CULL_FACE);

        glLightfv(GL_LIGHT0, GL_POSITION, light_dir);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color);

        glTranslatef(0,0,-5);

        glRotatef(a, 1, 0, 0);
        glRotatef(b, 0, 1, 0);
        glRotatef(c, 0, 0, 1);

        glutSolidTeapot(0.75);

            glMatrixMode(GL_PROJECTION);
            glPushMatrix();

            glLoadIdentity();
            glOrtho(0, fbo_width, fbo_height, 0, 0, 1);

            glBegin(GL_TRIANGLES);
            glColor3f(0.0, 1.0, 0.0);
            glVertex3f(0, 0, 0);
            glVertex3f(1, 0, 0);
            glVertex3f(0, 1, 0);
            glEnd();
            glPopMatrix();


        a=fmod(a+0.1, 360.);
        b=fmod(b+0.5, 360.);
        c=fmod(c+0.25, 360.);
    }

    void final()
    {
        static float a=0, b=0, c=0;

        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        glViewport(0,0, width, height);

        glClearColor(1.,1.,1.,0.);
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45, aspect, 1, 10);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0,0,-5);

        glRotatef(b, 0, 1, 0);

        b=fmod(b+0.5, 360.);

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, color);

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        glDisable(GL_LIGHTING);

        float cube[][5]=
        {
            {-1, -1, -1,  0,  0},
            { 1, -1, -1,  1,  0},
            { 1,  1, -1,  1,  1},
            {-1,  1, -1,  0,  1},

            {-1, -1,  1, -1,  0},
            { 1, -1,  1,  0,  0},
            { 1,  1,  1,  0,  1},
            {-1,  1,  1, -1,  1},
        };
        unsigned int faces[]=
        {
            0, 1, 2, 3,
            1, 5, 6, 2,
            5, 4, 7, 6,
            4, 0, 3, 7,
            3, 2, 6, 7,
            4, 5, 1, 0
        };

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        glVertexPointer(3, GL_FLOAT, 5*sizeof(float), &cube[0][0]);
        glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), &cube[0][3]);

        glCullFace(GL_BACK);
        glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, faces);

        glCullFace(GL_FRONT);
        glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, faces);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    }

    void display()
    {
        prepare();
        final();

        glutSwapBuffers();
    }
}
Community
  • 1
  • 1
wheybags
  • 627
  • 4
  • 15

2 Answers2

0

You are setting the z of your points in the triangle to 0. Set them to a small negative number (e.g. -3) instead.

I note you are using the deprecated "fixed function pipeline". I strongly recommend you learn and use "modern GL" instead.

Will
  • 73,905
  • 40
  • 169
  • 246
0

You're missing some critical parts. Primarily, you never set up any color and depth buffers in your FBO (frame buffer object). If you go back to the example code you linked, it has calls:

glTexImage2D(...)
glFramebufferTexture2D(...)
glRenderbufferStorage(...)
glFramebufferRenderbuffer(...)

Those calls are needed. They create buffers you render to, and bind them to your FBO.

Edit: It was pointed out that the code was not self contained. Looking at the rendering code, the problem might be with your transformations. You still have your previous tranlations/rotations in play when you render the triangle. You also set the matrix mode to PROJECTION there, and never switch back to MODELVIEW. I believe you need to load the identity matrix into MODELVIEW for your triangle rendering to get what you want.

Reto Koradi
  • 53,228
  • 8
  • 93
  • 133
  • 1
    `fb` isn't declared in the given code, so that code is probably somewhere else. It would definitely help to see the framebuffer initialization though. – Colonel Thirty Two May 08 '14 at 15:16
  • it's in the link, the code in my question is just the one function I modified – wheybags May 08 '14 at 15:17
  • @wheybags: Please don't post partial code. Asking us to debug a delta to code posted elsewhere is not really the idea. See http://stackoverflow.com/help/mcve: "Complete – Provide all parts needed to reproduce the problem" – Reto Koradi May 08 '14 at 16:07
  • Added a second part to the answer. – Reto Koradi May 08 '14 at 16:17
  • I figured it was better to post just the relevant bit to avoid a wall of text, I'll add in the full listing now. I tried adding in glMatrixMode(GL_MODELVIEW); glLoadIdentity(); after the call to glOrtho, but it made no difference. – wheybags May 08 '14 at 16:23