[solved] ofSetColor(r, g, b, a) unexpected behavior when alpha == 1

I couldn’t find this bug posted on the forum. When the renderer has its alpha set to a value of 1, the hue of the color used for drawing changes.

For example, if you draw 25 transparent, orange circles on top of one another using an alpha of 1, the result is red. If the alpha is greater than 1, the result is orange. Code snippet below:

void testApp::draw(){
    ofBackground(0);

    for (int i=0; i<25; i++) {
        // This should be a shade of orange but it's red
        ofSetColor(255, 132, 0, 1);
        ofCircle(ofGetWidth()/3.0, ofGetHeight()/2.0, ofGetWidth()/6.0);

        // This should be a shade orange and it is.
        ofSetColor(255, 132, 0, 2);
        ofCircle(ofGetWidth()*2.0/3.0, ofGetHeight()/2.0, ofGetWidth()/6.0);
    }
}

I’m running Windows 7 (64x) running 0.8.0 under Code::Blocks 12.11.

Any thoughts on what’s happening? I’m just starting to dig around in renderer code, but since I haven’t spent much time with it, it could take me a while to find out what’s going on.

1 Like

i guess it’s just that each circle is blending against the black background, if you try with a white background i guess the result will be the same

1 Like

@arturo Thanks!

So then, the source color (255, 132, 0) is being blended into the destination color (0, 0, 0, 255) using GL_FUNC_ADD​ where alpha acts as the weighting. So O = sS + dD where s = sourceAlpha / 255 and d = destAlpha / 255. When the source color’s alpha is 1, we end up with an output of (1, 0.52, 0). By default, it looks like openFrameworks sets the color precision of openGL to 8 bits per channel. So that would make (1, 0.52, 0) truncate to (1, 0, 0). When the source color alpha is 2, we end up with an output (2, 1.04, 0) which is truncated to (2, 1, 0).

That makes sense to me. I’m not very familiar with openGL - have a misinterpreted anything?

So then, if every blend operation is a function of two colors with a truncation to 8 bit precision per channel, it doesn’t matter how many circles I stack on top of one another if the color is (255, 132, 0, 1). The truncation prevents the green channel from changing to a non-zero value.

I tried temporarily upping the color precision in ofAppGLFWWindow to see if that would “solve” the truncation issue. That didn’t work.

Hey @mikewesthad, try rendering to an ofFBO, using an internal color format of GL_RGBA32F - this way, you will have 32bit float precision per colour channel.

To do this,
0) in ofApp::setup(), initialise an ofFBO ‘myFbo’ with the setting internalformat == GL_RGBA32F

  1. in ofApp::draw, encapsulate your original draw code within an myFbo.begin() / myFbo.end() pair
  2. then, in ofApp::draw(), draw your fbo using myFbo.draw()

For more infos & an example how to use float32 fbos, have a look at the fboTrailsExample in gl/examples/fboTrailsExample

Cheers

T

1 Like

@tgfrerer thanks for the suggestion!

Using an fbo with 32 bit precision worked like a charm. I just had to remember to ofDisableAlphaBlending() before drawing the fbo to the screen. Otherwise, the fbo would get alpha blended with the background.

This definitely satisfies my curiosity around the original “unexpected” behavior I was seeing. It’s not a bug - sorry for jumping the gun and classifying it as such. It’s just a numerical precision issue resulting from the 8 bit per channel setting of the default openGL renderer.

(Reclassifying as advanced and adding solved to the title)

1 Like