We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › problem/limitation/question about alpha blending
Page Index Toggle Pages: 1
problem/limitation/question about alpha blending (Read 1439 times)
problem/limitation/question about alpha blending
Feb 6th, 2007, 5:57pm
 
I am trying to use "alpha" blending
to gradually paint semi-transparent layers of colour.

The problem I am encountering is that when I use
very small alpha values (e.g., 2 to 20 out of 255)
the resulting colours I get are heavily quantized,
meaning that a smooth gradient appears as a staircase in brightness.

I have included a very small Processing Sketch
that illustrates the phenomenon.
You have to let it run for at least 20 seconds
to see the staircase effect emerge.

I am wondering whether this effect is an inherent consequence
of the alpha blending being done using integer calculations,
or whether there might be some kind of workaround.

-- djones

Quote:


// demo_alpha_bug

float x = 0;

void setup() {
 size(512,256);
 background(0);
 frameRate(240);
 strokeWeight(1);
}

void draw() {
 float g, a, y, step;

 y = 0;
 step = height / 8;
 for (int i = 1 ; i <= 8 ; ++i) {
   a = i * 2;
   g = 256.0*x/width;
   stroke(g, a);
   line(x,y, x,y+step-1);
   y += step;
 }
 if (++x > width) {
   x = 0;
 }
}

Re: problem/limitation/question about alpha blendi
Reply #1 - Feb 6th, 2007, 8:26pm
 
Hi djones-

What you're seeing is an effect of the discrete "steps" in the code... there are 8 "levels" to it because there are 8 steps defined by these two lines:

Quote:
 step = height / 8;
 for (int i = 1 ; i <= 8 ; ++i) {


I was able to reduce the effect by increasing the number of steps:

Quote:
 step = height / 128;
 for (int i = 1 ; i <= 128 ; ++i) {


This doesn't eliminate the problem entirely, though.  The eye is naturally very good at finding "edges," which usually appear as this kind of discontinuous change in color.  You can do better by introducing randomness into the number of steps.  The gets rid of the original staircase effect, but introduces a new streaking effect which may or may not be desireable:

Quote:

// demo_alpha_bug

float x = 0;

void setup() {
 size(512,256);
 background(0);
 frameRate(240);
 strokeWeight(1);
}

void draw() {
 float g, a, y, step;

 y = 0;
 float numSteps = random(8,128);
 step = height / numSteps;
 for (int i = 1 ; i <= numSteps ; ++i) {
   a = i * 2.0;
   g = 256.0*x/width;
   stroke(g, a);
   line(x,y, x,y+step-1);
   y += step;
 }
 if (++x > width) {
   x = 0;
 }
}


In a sense, this is a result of integer calculations, but perhaps not in the way you meant.  The available range of alpha levels is being artificially compressed to the number of steps specified.  By increasing the number of steps, we got rid of some of that discretization but because the eye is so sensitive to edges, we needed to put some "fuzz" in to destroy the edge.

You could probably eliminate the streaks we introduced with the randomization by limiting the extent to which numSteps can vary from iteration to iteration, which should have a "smoothing" effect.
Re: problem/limitation/question about alpha blendi
Reply #2 - Feb 6th, 2007, 11:59pm
 
Hi,

I am including a simpler example that demonstrates
the difficulty I am trying to eliminate.

In the code below, the grey-level "g" varies smoothly from 0 to 255
as the vertical lines are drawn from left to right.

The alpha blending value "a" is 12 (out of 255).

The program repeatedly draws the vertical lines with
the continuous ramp of grey-levels, ... but the image
that accumulates over time has a very small number
of discrete grey levels.

Basically, if the alpha-blending was being done using floating point,
the continuous ramp of grey would slowly emerge, but I think the
staircase is a consequence of pixels being rounded to the nearest integer
on each iteration.

This problem is a simplified version of what I am really trying
to do in a larger sketch.  I want to draw many layers of colour
with very small alpha blending values to create transluscent layers
... without these annoying discrete steps.

-- djones


Quote:


// demo_alpha_bug_2

float x = 0;  

void setup() {  
 size(512,256);  
 background(0);  
 frameRate(240);  
 strokeWeight(1);  
}  

void draw() {  
 float g, a;  

 a = 12;  
 g = 256.0*x/width;
 stroke(g, a);  
 line(x,0, x,height);  

 if (++x > width) {  
   x = 0;  
 }  
}  

Re: problem/limitation/question about alpha blendi
Reply #3 - Feb 7th, 2007, 12:30am
 
each renderer will treat this differently. OPENGL, for instance, gives decent results; P3D gives ok results, though it leaves some black lines because of its lack of numerical accuracy; JAVA2D (the default) gives the stair stepping. you'll also see differences with different platforms or versions of java.

this is mostly a numerical fact of life--256 values will give you terrible accuracy, no matter what. if you want things to be smoother, calculate and store smooth values yourself and convert them before rendering.
Re: problem/limitation/question about alpha blendi
Reply #4 - Feb 7th, 2007, 6:34pm
 
Ah... now I understand what you were saying!

What Ben said.  :-)

I have another workaround you can try, too.  I agree that this looks like a form of rounding error.  This technique of gradually "building opacity" layer upon layer compounds the errors.  To work around that limitation, you could redraw the original background and build opacity by increasing the alpha level on each pass.  My changes are highlighted in bold below:

Quote:
// demo_alpha_bug_3

float a, x = 0;

void setup() {
 size(512,256);
 background(0);
 frameRate(240);
 strokeWeight(1);
 a = 12;
}

void draw() {
 float g;
 
 g = 256.0*x/width;
 stroke(0);
 line(x,0, x,height);

 stroke(g, a);
 line(x,0, x,height);
 
 if (++x > width) {
   x = 0;
   a += (a >= 255) ? 0 : 8;
 }
}


The tricky part here, of course, is that the background of your real sketch is probably more complex than a black rectangle so redrawing the appropriate slice of that image under these lines of increasing opacity might be a little challenging.  Perhaps someone who has more experience with off-screen drawing buffers could help out with that part?
Re: problem/limitation/question about alpha blendi
Reply #5 - Feb 8th, 2007, 1:07am
 
Thanks so much Ben.  I hadn't even thought about the difference the renderer would make.  The OPENGL does indeed handled the alpha blending much better, plus it is significantly faster (at least on my Mac G5).

cheers!
 David Jones

fry wrote on Feb 7th, 2007, 12:30am:
each renderer will treat this differently. OPENGL, for instance, gives decent results; P3D gives ok results, though it leaves some black lines because of its lack of numerical accuracy; JAVA2D (the default) gives the stair stepping. you'll also see differences with different platforms or versions of java.

this is mostly a numerical fact of life--256 values will give you terrible accuracy, no matter what. if you want things to be smoother, calculate and store smooth values yourself and convert them before rendering.

Page Index Toggle Pages: 1