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);