PDA

View Full Version : nothing wrote to FBO attachment



kewuwsi
03-26-2008, 10:02 AM
Hi, there.
attached is my code for FBO.
[CODE]
// declare fbo
static GLuint PP_FBO = 0;
static GLuint PP_PING_TEX = 0;

static int currentShaderProgram = 0;


// init fbo
if( 0 == PP_PING_TEX)
{
glGenTextures(1, & PP_PING_TEX);
glBindTexture(GL_TEXTURE_2D, PP_PING_TEX);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 256, 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
}

if( 0 == PP_FBO)
{
glGenFramebuffersEXT(1, & PP_FBO);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, PP_FBO);

// Attach Texture to Framebuffer Color Buffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT , GL_TEXTURE_2D, PP_PING_TEX, 0);

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
assert(status == GL_FRAMEBUFFER_COMPLETE_EXT);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}


//use fbo
glUseProgramObjectARB(0);

// render to buffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, PP_FBO);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, PP_PING_TEX, 0);

glDrawBuffer( GL_COLOR_ATTACHMENT0_EXT);
// save current attribute
glPushAttrib(GL_VIEWPORT_BIT);

// set for fbo rendering
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0.0, 256.0, 0.0, 256.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glViewport(0, 0, 256, 256 );


glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, myTextureName);


// first pass
//glClearColor(1.0,0.0,0.0,0.0);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex2f( 0.0, 0.0);
glTexCoord2f(1.0f, 0.0f); glVertex2f( 256.0, 0.0);
glTexCoord2f(1.0f, 1.0f); glVertex2f( 256.0 , 256.0);
glTexCoord2f(0.0f, 1.0f); glVertex2f( 0.0, 256.0);
glEnd();

unsigned char result[256*256];
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadPixels(0, 0, 256,256,GL_LUMINANCE,GL_UNSIGNED_BYTE,result);
for( int i = 0; i < 256; i++)
{
for( int j = 0; j < 256; j++)
{
int value = (int) result[i*256+j];
if( value )
{
cout<< (int) result[i*256+j]<<"|";
}
}
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);

glPopAttrib();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);


[/B][/QUOTE]

Please take a look. The problem is, seems nothing is wrote to attachment( nothing printed out). And if I enable the two line after "//first pass", I got all 255s.

really out of my mind. can you please give a clue?


tks

Relic
03-26-2008, 01:35 PM
Check if there had been an error during the rendering. Add a glGetError after the glClear and after the glEnd.
I would expect that this setup won't work because GL_LUMINANCE is a 1-component format and FBOs have only been specified for rendering to 3- and 4-component formats (RGB and RGBA).
1- and 2-component formats are a special case and if it's supported then on NVIDIA as described in one of the early FBO presentations and the formats are R and RG, not luminance.

You could render to an RGB texture and read out luminance but that glReadPixels would need to calculate the luminance values on the fly.

kewuwsi
03-26-2008, 02:29 PM
as far as my understanding, FBO is not supporting 1 component internal format. The one component input format is OK.
I did succeed with this type of setting.( have working code ).

I am just expecting glReadPixels(...GL_LUMINANCE....) give me some none zero value.

adding

GLenum err=glGetError();
if (err!=0)
{
printf( "GLERR: %s", gluErrorString(err));
}

[/B]
after glEnd(); and glClear(). never give me msg.

the thing made me headache is: similar FBO in another class works OK( in same application )......... I ma out of mind!

Relic
03-26-2008, 03:58 PM
Oops, my bad, I misread the
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 256, 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);

So it's actually an RGB8 texture and the glReadPixels should convert it to luminance and that works somehow with the clear color.

You don't have a depth buffer attached to the FBO. The clear GL_DEPTH_BUFFER_BIT is useless.

Be aware that the glTexEnv is per texture unit not per texture object so the glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); affects the glBindTexture(GL_TEXTURE_2D, myTextureName);, but that's probably what you wanted anyway.

Does it work if you render the quad untextured with a constant color different than the clear color, like (0.5,0,0)?
If yes it's the texture setup.
How did you setup the myTextureName texture object?

Check other state, blending, current color etc.

If none of the above helps and things are working in other places of your code, one way would be to do an OpenGL command trace and see what exactly is different there.

kewuwsi
03-27-2008, 06:28 AM
I used the following code:


glColor3f(1.0, 1.0, 0.0);
glBegin(GL_TRIANGLES);
glVertex2f(0.0, 0.0);
glVertex2f( 256.0, 0.0);
glVertex2f( 256.0 , 256.0);
glEnd();

[/B]
instead of quad drawing part, still nothing is printed out.
really weird..

-NiCo-
03-27-2008, 06:32 AM
You should also add

glDisable(GL_TEXTURE_2D);

before the code you posted otherwise the test is rather pointless.

kewuwsi
03-27-2008, 07:21 AM
OK, now the code: still nothing out.
[CODE]
//use fbo
glUseProgramObjectARB(0);
// render to buffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, PP_FBO);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, PP_PING_TEX, 0);
glDrawBuffer( GL_COLOR_ATTACHMENT0_EXT);
// save current attribute
glPushAttrib(GL_VIEWPORT_BIT);
// set for fbo rendering
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0.0, 256.0, 0.0, 256.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glViewport(0, 0, 256, 256 );
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, myTextureName);
// first pass
//glClearColor(1.0,0.0,0.0,0.0);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);

glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 0.0);
glLineWidth(5.0);
glBegin(GL_TRIANGLES);
glVertex2f(0.0, 0.0);
glVertex2f( 256.0, 0.0);
glVertex2f( 256.0, 256.0);
glEnd();
GLenum err = glGetError();
if (err!=0) {
printf("GLERR: %s", gluErrorString(err));
}
//drawQuad();
unsigned char result[256*256];
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadPixels(0, 0, 256,256,GL_LUMINANCE,GL_UNSIGNED_BYTE,result);
for( int i = 0; i < 256; i++)
{
for( int j = 0; j < 256; j++)
{
int value = (int) result[i*256+j];
if( value )
{
cout<< (int) result[i*256+j]<<"|";
}
}
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopAttrib();

[/B][/QUOTE]

-NiCo-
03-27-2008, 08:02 AM
Well, my guess is that you forgot to reset some state during another part of your program. Here's the code I tried:



int sizex = 8;
int sizey = 8;

GLuint PP_FBO = 0;
GLuint PP_PING_TEX = 0;

if ( 0 == PP_PING_TEX)
{
glGenTextures(1, & PP_PING_TEX);
glBindTexture(GL_TEXTURE_2D, PP_PING_TEX);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, sizex, sizey, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
}
if ( 0 == PP_FBO)
{
glGenFramebuffersEXT(1, & PP_FBO);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, PP_FBO);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT , GL_TEXTURE_2D, PP_PING_TEX, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
glUseProgramObjectARB(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, PP_FBO);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, PP_PING_TEX, 0);
glDrawBuffer( GL_COLOR_ATTACHMENT0_EXT);

glPushAttrib(GL_VIEWPORT_BIT);

glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0.0, sizex, 0.0, sizey);

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

glViewport(0, 0, sizex, sizey );

glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);

glColor3f(0.5, 0.0, 0.0);

glDisable(GL_TEXTURE_2D);

glBegin(GL_TRIANGLES);
glVertex2f(0.0, 0.0);
glVertex2f( sizex, 0.0);
glVertex2f( sizex, sizey);
glEnd();

unsigned char result[sizex*sizey];
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadPixels(0, 0, sizex,sizey,GL_LUMINANCE,GL_UNSIGNED_BYTE,result);

fprintf(stderr,"\n");

for ( int i = 0; i < sizey; i++)
{
for ( int j = 0; j < sizex; j++)
{
fprintf(stderr,"%03d|",(int) result[i*sizex+j]);
}
fprintf(stderr,"\n");
}

glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopAttrib();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);


This is the output:



127|127|127|127|127|127|127|127|
000|127|127|127|127|127|127|127|
000|000|127|127|127|127|127|127|
000|000|000|127|127|127|127|127|
000|000|000|000|127|127|127|127|
000|000|000|000|000|127|127|127|
000|000|000|000|000|000|127|127|
000|000|000|000|000|000|000|127|


which is correct.

kewuwsi
03-27-2008, 08:06 AM
yeah, I think so.
it works in one of my another class( in the same application).

but what is the "state" will effect this part?

-NiCo-
03-27-2008, 08:14 AM
Well, there's a bunch of reasons why this doesn't work. That's the hard part about debugging. Some reasons are obvious and some are not.

For example, if you bound an object to the pixel pack buffer and forgot to unbind it when performing glReadPixels(...,result) , then it will treat result as an offset to the pixel pack buffer and it will not read to your system memory at address 'result'.

or you enabled cullface somewhere and the triangle is being clipped because of the wrong winding rule. Or you have blending still enabled. Or you have lighting enabled and the object is not facing the light. There's too much to sum up.

I usually bypass all other parts of my code and than iteratively enable parts of it and see if I still get the expected result. The moment this changes, it means that the problem lies in the last part you enabled. It's trial and error, takes some time but always works.

kewuwsi
03-27-2008, 08:45 AM
well, somehow I made it give me some reasonable output.
before using FBO, my apps calls another render(), the code of this render is like this.

[CODE]
glActiveTexture(GL_TEXTURE1);

glBindTexture(GL_TEXTURE_2D, myTexture1);

glEnable(GL_TEXTURE_2D);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE2);

glBindTexture(GL_TEXTURE_2D, myTexture2);


glEnable(GL_TEXTURE_2D);


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE3);

glBindTexture(GL_TEXTURE_2D, myTexture3);


glEnable(GL_TEXTURE_2D);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glActiveTexture(GL_TEXTURE0);

[/B][/QUOTE]
if I remove this render() call, I can got "000|128|" as you did...
I think the problem is: for this three glEnable(TEXTURE_2D); I have to disable them one by one......... remember had this problem before, but did not figure out the underlay theory....


tks

kewuwsi
03-27-2008, 09:13 AM
yeah!
It is this part effect my FBOs.
But I do need these three textures too in shaders. So just disable them is not the solution.

can anybody point me a right direction?


tks

Relic
03-27-2008, 09:57 AM
Hmm, read more docs. ;)
Shaders don't care at all about the fixed function glEnable texture state. They use texture image units and the shader uniforms you setup imply which texture image unit is used to fetch texture data.

-NiCo-
03-27-2008, 10:29 AM
Indeed, if you're using shaders you don't need to enable the texture stages. One of the things I like about shaders actually :)
But since the OP is using glUseProgramObjectARB(0) he's back to fixed functionality for that part.

kewuwsi
03-27-2008, 11:26 AM
tks!
finally I will use my shaders instead of glUseProgramObjectARB(0).
I went back to the fixed functionality just want to see whether the FBO is working properly.



The part puzzles me is," why the glEnable(GL_TEXTURE_2D) effects my FBOs?" I mean, no matter I use fixed functionality or use my shaders, if I keep the "glEnable(GL_TEXTURE_2D)" there. I can't get anything. If I remove it, it just works!

-NiCo-
03-27-2008, 01:21 PM
The glEnable(GL_TEXTURE_2D) does not affect your FBO, it affects your drawing routine. If you enabled multiple texture stages with glActiveTexture, they remain active. You wanted to draw the texture bound to glActiveTexture(GL_TEXTURE0) but GL_TEXTURE1, GL_TEXTURE2,etc. were still active which means that they will also be applied (modulated/replaced/...) to the object you are drawing.

kewuwsi
03-27-2008, 02:02 PM
thanks for explanation.
Then why the try just draw a triangle without any texture( glDisable(GL_TEXTURE_2D) ) rendered nothing to FBO attachment?

kewuwsi
03-27-2008, 02:08 PM
you are saying that the (modulated/replaced/...) is applied to the triangle drawing?

-NiCo-
03-27-2008, 02:27 PM
Yes. You said yourself that it works if you disable the texture units that you activated in an earlier pass. Because you did not deactivate them they will be applied to the triangle.

-NiCo-
03-27-2008, 02:28 PM
thanks for explanation.
Then why the try just draw a triangle without any texture( glDisable(GL_TEXTURE_2D) ) rendered nothing to FBO attachment?

Because the glEnable(GL_TEXTURE_2D) and glDisable(GL_TEXTURE_2D) only apply to the texture unit you activated last using glActiveTexture()

V-man
03-28-2008, 06:57 AM
I know it is too late but for future reference
http://www.opengl.org/wiki/index.php/GLSL_:_common_mistakes

Also, it will render your triangle whether you enable or disable those texture units when you are in fixed pipeline mode. Clear your background to some other color to be sure.