FBO works for my unit test, but failed with my app

Hi, all.

attached is my piece of my code for FBO initialization. It works OK with my unit test.
The problem is: when integrate this part into my apps code, it fails at the assertion point: says “GL_FRAMEBUFFER_UNSUPPORTED_EXT”,
And if I change all the GL_TEXTURE_2D to GL_TEXTURE_RECTANGLE_ARB , it doesn’t complain.

seems somewhere my apps disabled some of the GL features? what could be?

can anybody gave me a clue? tks

glxinfo:
(server glx vendor string: NVIDIA Corporation
server glx version string: 1.4
client glx vendor string: NVIDIA Corporation
client glx version string: 1.4
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: Quadro FX 4500/PCI/SSE2
)

[b]    glGenFramebuffersEXT(1, &fbo);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

    // init texture for FBO
    glGenTextures( 1, & tex);
    glBindTexture( GL_TEXTURE_2D, tex);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexImage2D(GL_TEXTURE_2D , 0, GL_RGBA, texW, texH, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

    // bind texture
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 
                              GL_COLOR_ATTACHMENT0_EXT, 
                              GL_TEXTURE_2D ,tex,0);

    GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    assert(status == GL_FRAMEBUFFER_COMPLETE_EXT); [/b]
[/b][/QUOTE]

What values are you assigning texW & texH? Also, do you have NP2 textures?

texW and texH is 512* 512. should be OK.
the strange things is: it works with my unit test!!!

And what is your “unit test” ?

IIRC, you get FRAMEBUFFER_INCOMPLETE if you don’t flip the texture min filter off of MIPmap. Also, if your FBO doesn’t have a depth buffer, disable depth test and depth writes:


glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST
glDisable( GL_DEPTH_TEST )
glDepthMask( GL_FALSE )

Also, for clarity, use GL_RGBA8 for your texture’s internal format.

Here is my unit test:

[b]
#include <iostream>
#include <cassert>
#include<GL/glew.h>
#include<GL/glut.h>
#include<GL/glext.h>

#include "textfile.h"


using namespace std;


float angle = 0.0;
int in_tex = 0;
int out_tex = 1;

int iter = 20;

// texture handle for ping pong
GLuint tex[2];

unsigned char* data;
// initial texture
GLuint init_tex;
int width = 512;
int height = 128;

// fbo handle
GLuint fbo;
GLenum att_point[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};


// shader variables
GLuint v, f, p1, p2, f2;
char *vs,*fs,*fs2;


static bool 
checkFBOErrors()
{
    unsigned fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    if (fbo_status != GL_FRAMEBUFFER_COMPLETE_EXT) {
    std::cout << "error creating fbo, framebufferstatus is not complete:" << std::endl;
    std::string error;
    
    switch (fbo_status) {
        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:          error.assign("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT");break;
        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:  error.assign("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT");break;
        case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:          error.assign("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT");break;
        case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:             error.assign("GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT");break;
        case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:         error.assign("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT");break;
        case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:         error.assign("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT");break;
        case GL_FRAMEBUFFER_UNSUPPORTED_EXT:                    error.assign("GL_FRAMEBUFFER_UNSUPPORTED_EXT");break;
    }
    std::cout << "error: " << error << std::endl;
    return false;
}

}
//
//
// shader program
void setShaders() 
{ 
    // v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
    f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
    f2 = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
    
    
    // vs = textFileRead("toon.vert");
    fs = textFileRead("toon.frag");
    fs2 = textFileRead("toon2.frag");
    
    const char * ff = fs;
    const char * ff2 = fs2;
    //  const char * vv = vs;
    
    // glShaderSourceARB(v, 1, &vv,NULL);
    glShaderSourceARB(f, 1, &ff,NULL);
    glShaderSourceARB(f2, 1, &ff2,NULL);
    
    // free(vs);
    free(fs); free(fs2);
    
    // glCompileShaderARB(v);
    glCompileShaderARB(f);
    glCompileShaderARB(f2);
    
    p1 = glCreateProgramObjectARB();
    glAttachObjectARB(p1,f);
    // glAttachObjectARB(p1,v);  
    glLinkProgramARB(p1);

    p2 = glCreateProgramObjectARB();
    glAttachObjectARB(p2,f2);
    // glAttachObjectARB(p2,v);  
    glLinkProgramARB(p2);

    
}

void InitGLExtensions()
{
    // Init GLEW
    if (glewInit() != GLEW_OK)
    {
    cout << "Error: Can't initialize GLEW" << endl;
    exit(-1);
    }
    else
    {
    cout<<"GLEW IS INITIALIZED OK!!"<<endl;
    }
    
    if (!GLEW_EXT_framebuffer_object)
    {
    cout << "Error: EXT_framebuffer_object is not supported." << endl;
    exit(-1);
    }
    else
    cout<<"FRAME BUFFER OBJECT IS INITIALIZED OK!!"<<endl;
    
}


void initTextures()
{
    // allocate texture name
    glGenTextures(1, &init_tex);
    
    // 
    // generate test 8 bit image
    //
    data = (unsigned char*) malloc(width * height *sizeof(unsigned char));
    // init texture info
    for(int row = 0; row < height; row++)
    {
    for( int col = 0; col < width; col++ )
    {
        int pos = row*width + col;
        if( row % 32==0 || col % 32==0)
        {
        data[pos] = 255;
        }
        else data[pos] = 0;
    }
    }
    glBindTexture(GL_TEXTURE_2D, init_tex);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR/*GL_NEAREST*/ );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/* GL_NEAREST*/);
    /*
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
         GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
    */
    //free(data);
}


// create FBO and two textures used for Ping Pong
// attach these two textures to FBO
void InitFBO()
{
    // Create FBO
    glGenFramebuffersEXT(1, &fbo);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    

    // Initialize ping pong texture 1, bind to fbo
    glGenTextures(1, &tex[0]);
    glBindTexture(GL_TEXTURE_2D, tex[0]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
    
    // Attach Texture to Framebuffer Color Buffer
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, att_point[in_tex], GL_TEXTURE_2D, tex[in_tex], 0);
    
    checkFBOErrors();

    // Initialize ping pong texture 2, bind to fbo   
    glGenTextures(1, &tex[1]);
    glBindTexture(GL_TEXTURE_2D, tex[1]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
    
    // Attach Texture to Framebuffer Color Buffer
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, att_point[out_tex], GL_TEXTURE_2D, tex[out_tex], 0);

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
     
    
}

void ReleaseFBO()
{
    glDeleteFramebuffersEXT(1, &fbo);
}


void changeSize(int w, int h) {

    // Prevent a divide by zero, when window is too short
    // (you cant make a window of zero width).
    if(h == 0)
        h = 1;

    float ratio = 1.0* w / h;

    // Reset the coordinate system before modifying
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-width/2, width/2, -height/2, height/2);
    // Set the viewport to be the entire window
    //glViewport(0, 0, w, h);

    // Set the correct perspective.
    //gluPerspective(45,ratio,1,1000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glViewport(0, 0, w, h);
/*
    gluLookAt(0.0,0.0,0.0, 
              0.0,0.0,-1.0,
              0.0f,1.0f,0.0f);
*/
}

void shaderDraw()
{
    glBegin(GL_POLYGON);
    glTexCoord2f(0.0f, 0.0f); 
    glVertex3f(-width/2, -height/2,  0.0f);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f( width/2, -height/2,  0.0f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f( width/2,  height/2,  0.0f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(-width/2,  height/2,  0.0f);
    glEnd();
}

// render to buffer
// Do ping pong once: two passes, do convolution along X direction and Y direction
void rendertoBuffer(void)
{
    glUseProgramObjectARB(p1);
    
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    
    //glPushAttrib(GL_VIEWPORT_BIT);
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    gluOrtho2D(-width/2, width/2, -height/2, height/2);
    
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    glViewport(0, 0, width, height);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    
    // bind input texture  and draw
    glBindTexture(GL_TEXTURE_2D, init_tex);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
         GL_LUMINANCE, GL_UNSIGNED_BYTE, data);    
   
    // first draw
    shaderDraw();

    // now we have the render buffer textures
    for( int i = 0; i < iter; i++ )
    {
        // set the draw destination
        glDrawBuffer( att_point[out_tex] );

        // bind textureIN to smoo_text for shaders
        glActiveTexture(GL_TEXTURE0);
        int myTexture = glGetUniformLocationARB(p1, "smoo_text");
        glUniform1iARB(myTexture, 0);

        glBindTexture(GL_TEXTURE_2D, tex[in_tex]);
        int textID = glGetUniformLocationARB(p1, "tex_id");

        shaderDraw();

        // swap in/out index
        if( in_tex )
        {
            in_tex = 0;
            out_tex = 1;
            glUniform1iARB(textID, out_tex);
        }
        else
        {
            in_tex = 1;
            out_tex = 0;
            glUniform1iARB(textID, out_tex);
        }    
    }  

    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glDisable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    
    //cout<< __FILE__ << __LINE__ <<" IN RENDER TO BUFFER STAGE "<<endl;
    glUseProgramObjectARB(0);
}

void renderScene(void) 
{ 
   //rendertoBuffer();
    
    glUseProgramObjectARB(p2);
    glClearColor(0.0f, 0.0f,0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  
    //
    // bind textureIN to smoo_text for shaders
    glActiveTexture(GL_TEXTURE1);
    //glEnable(GL_TEXTURE_2D);
    int myTexture = glGetUniformLocationARB(p2, "imag_text");
   
    glBindTexture(GL_TEXTURE_2D, tex[out_tex]);
    glUniform1iARB( myTexture, 1);
    //
    // draw to screen
    shaderDraw();
    glDisable(GL_TEXTURE_2D);

    glutSwapBuffers();
    glUseProgramObjectARB(0);
    //cout<<__FILE__<<"   "<<__LINE__<<"  IN RENDER SCENE"<<endl;
}

void processNormalKeys(unsigned char key, int x, int y) {

    if (key == 27) 
        exit(0);
}

void updateInteration( int key, int x, int y)
{
    if( key == GLUT_KEY_PAGE_UP )
    {
    iter ++;

    }
    if( key == GLUT_KEY_PAGE_DOWN  && iter > 0)
    {
    iter --;
    }
    cout<< __FILE__<<" "<<__LINE__<<" current iteration "<< iter<<endl;
} 



int main(int argc, char **argv) 
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA | GLUT_MULTISAMPLE);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(320,320);
    glutCreateWindow("Lighthouse 3D - GLUT Tutorial");
    
     InitGLExtensions();
    InitFBO();
    initTextures();
    setShaders();
    rendertoBuffer();
    glutReshapeFunc(changeSize);
    
    glutDisplayFunc(renderScene);
    glutIdleFunc(renderScene);
  
    
    //adding here the setting of keyboard processing
    glutKeyboardFunc(processNormalKeys);
    glutSpecialFunc(updateInteration);
  
   
    glutMainLoop();
    return 0;
}

 [/b]
[/b][/QUOTE]

here is the error msg I got with Dark Photon’s suggestions:
"
error creating fbo, framebufferstatus is not complete:
error: GL_FRAMEBUFFER_UNSUPPORTED_EXT
"
with the borrowed function listed in above unit test ( replace the assertion part in my apps with checkFBOErrors() ).

?
tks

If I comment out the few lines to load the shaders, then compile and run it, I get:

> tst
GLEW IS INITIALIZED OK!!
FRAME BUFFER OBJECT IS INITIALIZED OK!!

Linux, GeForce 8800GTX, 169.09 drivers

Yes.
That is saying my unit test is OK on my computer.

my problem is: " If I try to use FBO with GL_TEXTURE_2D in my application( large scale code ) on the same computer, It will fail and give me the error msg."

tks

Looks like you need to master the art of debugging :slight_smile:

Start from your unit test and repeatedly add parts of your large scale code and check for errors. Takes a little effort but it always does the trick.

N.

http://www.opengl.org/discussion_boards/images/icons/default/tongue.gif

Tks, I will think about it. You know, the apps is really “large”, I even don’t know how to get started…