5

This is a question about Processing.org.

I am fading out previously drawn objects by drawing a semi-transparent white rectangle over the view for every frame.

However, it appears that they never fade to completely white. The fading has a fixed point at some noticeably non-white shade of grey. Same thing happens when trying to fade to black.

Is this a standard feature of how alpha-blending works in processing? Is there a relatively easy way around it, to achieve a completely white background (given enough steps)?

I imagined the resulting colour would be a linear combination of the colours that are blended, which means the limit should be white. Perhaps the non-white fixed point is an artefact of rounding?

Sample code illustrating the issue:

void setup() {
  size(300,300);
  background(0);
  noStroke();
  frameRate(15);
}

void draw() {
  fill(255,10);
  rect(0,0,width,height);
  fill(255);
  rect(0,0,50,50); // for comparison to white
}

edit: added java tag in hope of more attention

Szabolcs
  • 24,728
  • 9
  • 85
  • 174
  • Have you found a solution to this problem yet? – LaserJesus May 17 '13 at 05:28
  • @LaserJesus Not really, I've stopped playing with it. The reason why it doesn't fade to complete white is that colours are encoded as integers (i.e. no fractional values are allowed). – Szabolcs May 17 '13 at 14:19

3 Answers3

0

I did a lot of digging and now I am rather confident to say, that complete fading with the alpha channel is not possible. There is however a thing called brightness, so let's use it.

void setup() {
  size(300,300);
  background(0);
  noStroke();
  frameRate(15);

  // White rectangle for fading comparison.
  fill(255);
  rect(0, 0, 50, 50);
}

void draw() {
  fade(10);
}

void fade(final int fadeSpeed) {
  loadPixels();
  for (int row = 0; row < height; row++) {
    for (int col = 0; col < width; col++) {
      final int pixelIndex = row * width + col;
      int pixel = pixels[pixelIndex];
      int red   = ((pixel >>> 16) & 0xFF) + fadeSpeed;
      int green = ((pixel >>>  8) & 0xFF) + fadeSpeed;
      int blue  =  (pixel         & 0xFF) + fadeSpeed;
      if (red   > 255) { red   = 255; }
      if (green > 255) { green = 255; }
      if (blue  > 255) { blue  = 255; }

      // Shift bits back into propper position and 
      red   <<= 16;
      green <<=  8;
      pixel &= 0xFF000000;  // Keep alpha bits.
      pixel |= red |= green |= blue;

      pixels[pixelIndex] = color(pixel);
    }
  }
  updatePixels();
}

By incrementing all three color channels (red, green, blue) at the same time we don't change color but brightness.

Senkaku
  • 197
  • 2
  • 10
0

I discovered that, while the rounding error (if that's what it is) applies to pretty much everything you can try, using blendMode(SUBTRACT), followed by a fill with a very small greyscale color (like fill(2)) achieves a gradual fade over many draw() cycles without the "ghost" image that all the other approaches seem to have, while keeping the frame rate up (which is often critical in real-time drawing situations).

 // The only reasonable way to actually "fade" out the pixels.
blendMode(SUBTRACT);
fill(2);
rect(0, 0, width, height);
blendMode(NORMAL);
Tom Auger
  • 19,421
  • 22
  • 81
  • 104
0

I am not sure whats going on, it seems like you should be right and that if the number of rectangles drawn * the alpha value of those rectangles is greater than 255 it should be completely white. Anyways why not just redraw every frame (like i do by moving the background(0) line into the draw loop) and then just increase your alpha value. I think this path will give you more control in your animations in the future.

int a;

void setup() {
  size(300,300);
  noStroke();
  frameRate(15);
  a = 0;
}

void draw() {
  background(0);
  a += 1;
  if(a<=255){
    fill(255,a);
  }
  rect(0,0,width,height);
  fill(255);
  rect(0,0,50,50); // for comparison to white
}
Robin
  • 686
  • 1
  • 9
  • 18
  • My point was not to just fade out a rectangle, but to gradually fade out *everything* that was drawn on the screen so far, all of this while still drawing new things. Imagine moving a "ball" through the screen, and not deleting the ball drawn in the previous frame, but instead just "fading it out" a bit. The end result will be that the ball will leave a fading trail. This can make a nice effect for more complex animations. The approach you outlined can only produce a fading rectangle, not this effect. – Szabolcs Oct 27 '11 at 16:18