0

I'm looking for some input on a general approach to implement temporal dithering in processing.

Currently I have a processing sketch which generates a hex file that can be sent to an APA102 LED strip over SPI. The framerate which I would be able to achieve should be sufficient that I can implement temporal dithering to increase the dynamic range of the LEDs, mainly with lower brightness. I looked into FastLed and Fadecandy to try and understand how it is done, but I can't really figure it out. Using these libraries is not an option as the animation should be 'hardcoded' in the hex file.

Who could point me in the right direction?

edit: I currently implemented the following: First, I calculate the achievable framerate on the LEDs which gives me the number of dither-frames I can insert, based on the number of LEDs in my string and the SPI clockspeed. The LEDstrip can update at 420fps, so I have 7 'virtual' frames per frame to still be able to have 60fps base refresh rate. I then calculate a lookup table of 7x7 which looks like this:

0 0 0 0 0 0 0 
0 0 0 1 0 0 0
0 0 1 0 0 1 0
0 1 0 1 0 1 0
0 1 0 1 1 0 1
1 1 0 1 1 1 0
0 1 1 1 1 1 1

I do all the gamma- color correction calculations with floats, and every line in the lookup table corresponds a step of 1/7 between two values. These are then added to the floored RGB values to achieve the dithering. However, all this does not really change much visually. Compared to the animation without dithering I don't see a difference. I was hoping to see something like https://www.youtube.com/watch?v=1-_JtRl2ks0

Joel Spolsky
  • 33,372
  • 17
  • 89
  • 105
Sharky
  • 31
  • 5

1 Answers1

0

You can read the code that FastLED uses for dithering in master/controller.h -- search for init_binary_dithering. From reading this, I gather that they just check how much time has elapsed since the last update to estimate how many "bits" of virtual dithering they can get.

Since you didn't provide working code, I'm not sure why you're not seeing a difference. But, I can work through an example to understand what temporal dithering is supposed to be doing.

Suppose your global brightness is set to 32. That means all RGB values are divided by 8 (256/32) before being displayed. For example 255,255,255 will actually display as 31,31,31.

(For now I'll just ignore "G" and "B" - let's pretend it's just "R".)

  • How is 32 displayed? It's displayed as 1.
  • How is 0 displayed? It's displayed at 0.

Now

  • How is 16 displayed? It was going to be displayed as 0. But this is where temporal dithering can be useful. What we really want to do is display it as 0 half the time and 1 half the time.

  • How is 24 displayed? It would also be displayed as 0, but with temporal dithering, we should display it as 0 one quarter of the time and 1 the other three quarters of the time.

Again from your description I'm not certain why you're not seeing the desired effect.

Joel Spolsky
  • 33,372
  • 17
  • 89
  • 105