PDA

View Full Version : Problems with fbo's and blending



Memoid
02-26-2009, 07:56 PM
I'm having problems with semi-transparent stuff draw in FBO's getting lighter when drawn to the screen.

My code is simply this:


void ofEnableAlphaBlending(){
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void drawFG() {
glColor4f(1, 1, 1, fadeAmount);
ofRect(100, 100, 200, 200);

glColor4f(0, 0, 1, fadeAmount);
ofRect(120, 120, 200, 200);
}


void draw() {
ofEnableAlphaBlending();

glColor4f(1, 0, 0, 1);
ofRect(150, 150, 200, 200); // red rect bg

if(useFBO == false) {
drawFG();
} else {
fboNew.begin();
{
fboNew.clear();
drawFG();
}
fboNew.end();

glColor3f(1, 1, 1);
fboNew.draw(0, 0, fboNew.getWidth(), fboNew.getHeight());
}
}


If I use the FBO, the white rect is clearly a lot more see through. If fadeAmount ==1 then they are both white. But if fadeAmount is 0.5, drawing without FBO gives me 127/255 in photoshop but drawing with FBO gives 31/255!!

So I thought maybe its because the alpha is being applied twice. Its drawn into the FBO with alpha, and then drawn again to the screen with alpha. I would have thought if that is the case the final alpha should be 0.25 =>64/255, but the result i get is 31/255!

So I thought I'd try disabling blend when drawing the FBO to the screen:



ofDisableAlphaBlending();
fboNew.draw(0, 0, fboNew.getWidth(), fboNew.getHeight());


Then the FG is identical whether using FBO or not, but of course this time I don't see the background, because the transparent parts of the FBO don't show through.

So I thought i'd disable blending when drawing into the FBO but enable when drawing to the screen:


if(useFBO == false) {
drawFG();
} else {
fboNew.begin();
{
fboNew.clear();
ofDisableAlphaBlending();
drawFG();
}
fboNew.end();

glColor3f(1, 1, 1);
ofEnableAlphaBlending();
fboNew.draw(0, 0, fboNew.getWidth(), fboNew.getHeight());
}


Now the FG has the correct alphas, white has the correct color on black and on the red, and the blue has the correct color on black and on the red. But since blending was disabled when writing into the FBO the white and blue aren't blended, the blue overwrote the white so where they overlap you don't see the white.

This is driving me crazy and I can't find a solution, I actually have quite a few more FBOs and my elements aren't just 2 rects but hundreds of sprites. Does anyone know how to solve this problem?

my fbo creation code:


glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

glGenTextures(1, &textureName);
glBindTexture(GL_TEXTURE_2D, textureName);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureName, 0);

glEnable(GL_TEXTURE_2D);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glGenerateMipmapEXT(GL_TEXTURE_2D);

if(useDepthBuffer){
glGenRenderbuffersEXT(1, &depthBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer);
}

checkStatus();

clear();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDisable(GL_TEXTURE_2D);

Komat
02-27-2009, 12:55 AM
You can set the texture function to ignore the alpha from the texture and use only alpha from the vertex color when you are drawing the FBO to the screen. You can do that using the GL_COMBINE texture environment or shaders.

Memoid
02-27-2009, 04:17 PM
Hi, I didn't know about that. I looked in the documentation and tried various combinations but still couldn't get it behave how I'd expect it. Could you possibly be a bit more specific please?

Abdallah DIB
02-27-2009, 04:54 PM
glTexEnv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REP LACE)
but the internal format of ur texture should be RGB and not RGBA, otherwise the alpha of the texture will be assigned to the vertex .
if u want to use the GL_COMBINE ( i will choose this one , u can always find a better way ):
glTexEnv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COM BINE);

glTexEnv(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE );
glTexEnv(GL_TEXTURE_ENV,GL_COMBINE_ALPHA,GL_REPLAC E);

glTexEnv(GL_TEXTURE_ENV,GL_SRC0_RGB,GL_PRIMARY);
glTexEnv(GL_TEXTURE_ENV,GL_SRC1_RGB,GL_TEXURE );

glTexEnv(GL_TEXTURE_ENV,GL_SRC0_ALPHA,GL_PRIMARY);

glTexEnv(GL_TEXTURE_ENV,GL_OPERAND0_ALPHA,GL_SRC_A LPHA);


with shaders it is more easy :P