Problem with glBlendFunc and FBO

Started by
5 comments, last by nemebean 16 years, 11 months ago
I'm trying to render my trees to an FBO to use as an impostor. I've got it working pretty well now, except that my leaves are ending up with nasty semi-transparent borders around them similar to what I saw rendering them directly to the screen before I found the right blending options. Here are comparison screenshots: Bad Good The bad one is when I render to FBO, the good one is direct to the screen. As you can see instead of being completely opaque or completely transparent, the bad one has translucent parts that would need to be blended (which would be a nightmare). I'm using these calls to set up the alpha testing:
glAlphaFunc(GL_GREATER, 0.5);
glEnable(GL_ALPHA_TEST);
glBlendFunc(GL_ONE, GL_ZERO);
Since it works when I render without the FBO, is there something else I need to be doing when I'm setting up the FBO? Currently it looks like this:
glGenFramebuffersEXT(1, &impostorfbo);
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, impostorfbo);
   
   glGenRenderbuffersEXT(1, &depthbuffer);
   glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);
   glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 512, 512);
   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthbuffer);
   
   glGenTextures(1, &imptex);
   glBindTexture(GL_TEXTURE_2D, imptex);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
   
   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, imptex, 0);
   if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
      cout << "Failed to create framebuffer in WorldObjects.\n" << glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) << endl;
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
and then simply binding it with glBindFramebufferEXT before rendering. Am I missing something here? Is it possibly just a driver bug? I'm stumped and this is sort of a major problem since it's bad to have a largely opaque group of leaves go partially transparent when it switches to the impostor. TIA for any help.
Advertisement
it doesnt look like a driver bug, i dont know if u can use GL_DEPTH_COMPONENT without specifying a size.
is depthtest/writes enabled

also glBlendFunc(GL_ONE, GL_ZERO); is the same as no blend (so dont use it)

also use multisample sample_to_coverage to make your leaves look a lot better (dont use alphatest), though i dont know what the status with this + FBOs are

Quote:Original post by zedz
it doesnt look like a driver bug, i dont know if u can use GL_DEPTH_COMPONENT without specifying a size.
is depthtest/writes enabled

Depthtesting is enabled and working correctly. I'm not sure what you mean about GL_DEPTH_COMPONENT and specifying a size since I'm passing 512x512 as the size to that function.

Quote:also glBlendFunc(GL_ONE, GL_ZERO); is the same as no blend (so dont use it)

This is intentional. I don't want any translucent pixels or I end up with halos around the edges of the leaves. The alpha test takes care of removing the transparent parts of the texture and anything left should be fully opaque.

Quote:also use multisample sample_to_coverage to make your leaves look a lot better (dont use alphatest), though i dont know what the status with this + FBOs are

I'll look into that, but for the moment I'm perfectly happy with the way my leaves look (or at least I have a lot more pressing concerns) so I'd really like to just leave it as is. Also, from a quick Google you seem to be referring to CSAA which is only available on 8-series cards. Since I'm still on a 7600 GT I can't use that anyway.
A/ i mean
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, 512, 512);

B/
try disabling blend, ie glDisable( GL_BLEND );

C/ its not CSAA it works on a lot of cards inc ati + nvidia gffx >
see Alpha to coverage here
http://www.humus.ca/index.php?page=3D&&start=8
itll make your leaves look much better
Changing it to GL_DEPTH_COMPONENT24 didn't seem to have any effect. Disabling GL_BLEND gave me black boxes around all of my leaf textures, but toying with that did lead to a solution to my problem. It turns out that I wasn't enabling alpha testing for the billboarded polygon and once I did that everything rendered as I wanted. So although it still seems to be ignoring my blending when I write to the FBO, at least I can do the alpha test at a later point and it works. The only problem would be if I need to have alpha tested and translucent polys in the same billboard, but I guess I just won't be doing that.:-)

I will take a look at that alpha to coverage technique (which gave me much better Google results than sample to coverage;-). It was something that I wanted to implement eventually, but now I have an actual method to use. Thanks for the tip.
I was just about to post exactly the same topic. Here's my tree: http://img183.imageshack.us/img183/7235/treemeshimpostoran0.png

As you can see, the leaves does not render correctly and the orientation is wrong. I'm setting up the FBO:

  glGenFramebuffersEXT(1, &_fbo);  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);  glGenRenderbuffersEXT(1, &_depth_buffer);  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, _depth_buffer);  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, _width, _height);  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, _depth_buffer);    glGenTextures(1, &_texture);  glBindTexture(GL_TEXTURE_2D, _texture);  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,  _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  glTexParameterf(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);  glBindTexture(GL_TEXTURE_2D,0);  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, _texture, 0);  check_status();  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);


And rendering into the FBO:

  int size = 512;  AABB bb(_tree->bounding_box());  Framebuffer_object fbo(size, size);  glPushAttrib(GL_VIEWPORT_BIT|GL_COLOR_BUFFER_BIT);  glViewport(0, 0, size, size);      glMatrixMode(GL_PROJECTION);  glPushMatrix();  glLoadIdentity();      glOrtho(bb.min[0], bb.max[0], bb.min[1], bb.max[1], bb.min[2], bb.max[2]);  math::Vec3_t eye = bb.center();  eye.y = bb.min[1];  math::Vec3_t center = eye+math::Vec3_t(0,0,-1);      glMatrixMode(GL_MODELVIEW);  glPushMatrix();  glLoadIdentity();  gluLookAt(eye.x, eye.y, eye.z,	    center.x, center.y, center.z,	    0, 1, 0);  fbo.begin();  {    glClearColor( 0,0,0,0 );    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    _tree->draw(camera);  }  fbo.end();      glPopMatrix();    glMatrixMode(GL_PROJECTION);  glPopMatrix();  glMatrixMode(GL_MODELVIEW);    glPopAttrib();


Rendering the actual impostor quad:

  glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT);  glEnable(GL_TEXTURE_2D);  glEnable(GL_ALPHA_TEST);  glAlphaFunc(GL_GREATER, 0.9f);  glDisable(GL_LIGHTING);  glDisable(GL_LIGHT0);  glDisable(GL_FOG);      glPushMatrix();    {      float m[16];      glGetFloatv(GL_MODELVIEW_MATRIX, m);          // reset right and up vectors, effectively creates a cylindrical billboard       m[0]=1; m[8]=0;      m[1]=0; m[9]=0;      m[2]=0; m[10]=1;      glLoadMatrixf(m);      glActiveTexture(GL_TEXTURE0);      glBindTexture(GL_TEXTURE_2D, _impostor_texture);      AABB bb(_tree->bounding_box());      glBegin(GL_QUADS);      glTexCoord2f(0,0);  glVertex2f(bb.min[0],bb.min[1]);      glTexCoord2f(0,1);  glVertex2f(bb.min[0],bb.max[1]);      glTexCoord2f(1,1);  glVertex2f(bb.max[0],bb.max[1]);      glTexCoord2f(1,0);  glVertex2f(bb.max[0],bb.min[1]);      glEnd();     }    glPopMatrix();  glPopAttrib();    


Any idea what might be causing this? I even tried rendering a 4096^2 texture and it looks the same.
My best guess would be that glAlphaFunc(GL_GREATER, 0.9f) is too high a threshold. Try a lower value (I use .5) and see if more of your leaves come back. I know at least in my case if I use a threshold of .9 I lose a lot of my leaves in a similar fashion.

This topic is closed to new replies.

Advertisement