Grayscale dithering + lower FPS = higher resolution!


In a previous topic I talked about using a monochrome display to display colors; and that it’s best to have this color assignment done on the OS level.
Kind of creating a ‘library’ as were, so that on the programming level, one of 3 modes can be chosen:
- fully monochrome,
- 3 colors (B, W, Grey), or
- 4 colors (B, W, Light Grey, Dark Grey)
Can be programmed for each artifact (background/sprite/object) on the screen.
And have the OS take care of correctly dithering the screen.

These 3-4 colors on a monochrome display essentially half to 1/3rd the screen frequency.

On the other hand you can use the same principle to create a higher perceivable resolution.

EG: Imagine in a pixel row on a 4 color setting:
0 = dark ,
1= dark grey,
2= light grey,
3= white.

And for a 3 color setting, I’ll write:
0 = dark
X = grey
3 = white.

Using these colors, to increase perceivable resolution in the following way:

Monochrome setting:
Our current system, moving a monochrome pixel is:
Frame 1: 0300
Frame 2: 0030
The pixel has moved 1 column to the right in 1 frame.
This is great for sharp, fast moving objects, that require little precision.

One can half the framerate, and make the transition from one pixel to another more smooth as such:
F1: 0300
F2: 0330
F3: 0030
This improves the perceived resolution by 2x, however, it halfs the framerate, and stretches the pixel in the transition!
This is good for medium fast movement, of up to 30 pixels per second movement, I would think.


3 Color:
More precision can be gotten in a 3 color setting:
F1: 0300 (60FPS)
F2: 0XX0 (30FPS)
F4: 0030 (60FPS)
However, doing it this way, Frame 2 will take 2 frames to draw, one frame longer than in the above setting; and the FPS in this setting drops from 30FPS to 20FPS.
Color accuracy is increased, as the pixel now looks different stretched over 2 pixels in grey format, rather than doubling the black pixel, like in example above.

Doing the same for a grey pixel in 3 color mode, will essentially stretch the pixel, as dithering is no longer possible (anything between black and grey or white and grey is not available in 3 color mode), and drop the FPS to 10FPS, as each color frame takes 2FPS to draw, and essentially they’re each rendered at 30FPS).
So the entire move of 1 grey pixel takes 6 frames, or 10FPS:

F1: 0X00 (30FPS)
F3: 0XX0
F5: 00X0

Generally good for backgrounds, and slow moving images, moving no faster than what I’d say 10 pixels per second.
Still, stretching and tearing occurs due to F3 doubling the pixels.

You can use this example to move a pixel down, up, left or right from it’s previous spot, doubling the perceivable screen resolution.


4 color settting:
With 4 colors it gets more difficult, as each additional color slows down FPS even more.
For one black or white pixel to move 1 pixel to any direction, it’ll take 8 frames on a 4 color setting, however, it essentially tripling the perceived resolution:

F1: 0300 (60FPS)
F2: 0210 (20FPS)
F5: 0120 (20FPS)
F8: 0030 (60FPS)

This is great for backgrounds that aren’t moving very fast, like less than 8 pixels per second.
A 4 color pixel move using 2 grayscales increases color and position accuracy over 3 color, but drops the pixel framerate considerably, to 8FPS; which would make it quite hard to apply this in fast or medium speed screen objects.
Perhaps rounding off the real life FPS at which the Arduboy refreshes the screen, it’ll be at 9FPS, but still perceivable fps drop to the eye…
It’s probably good for where accuracy and visual aesthetics is required over fluid framerates, and perhaps very slow moving images, like backgrounds moving slower than 8 pixels per second.


This transition pixelation works most fluid on BLACK and WHITE pixels, or MONOCHROME settings, however grey scales increase perceivable resolution accuracy.

In case of a light or dark grey pixel, you’re running 4 colors (black, dark, light, white); which means you’d be running at ~9-20FPS or 1/8th to 1/3rd of the original system FPS.
(I say 20FPS, using 60FPS as a frame of reference. I know the system actually does 67-69 or so FPS, so the real world FPS numbers are somewhat higher).

Possible to do on an arduino, you think?

There’s been extensive discussion about this, actually. :smiley:

1 Like

Yes, more shades of grey, yes.
But increasing perceivable resolution using these same forms of dithering?

I guess I would need to see a proof of concept to understand how that would work.

While i can explain it, unfortunately, I can’t program it :smirk:

However, as proof of concept, if you can program a pixel on the screen, and can program a grayscale pixel, you should be able to program the pixel moving over the screen with increased smoothness, using the principle of dithering…

Then build on that. Perhaps by using sprites, or… I don’t know…
The car game showing the grayscale colors might give some clues how to do it.

I know what you mean :smiley: I guess we’re talking about subpixel positioning. Let me try to make a gif (you don’t need to program it BTW, GIMP is all you need).



1 Like

Made a little dithering demo… Here I used an integer variable as a counter, which moves the dither filter to produce a “third color”. I placed the dither filter behind the picture. So if FPS is high enough, the dithering may blend.
P.S.: How do you like the pixel art I did here? Will be used in a game…
Scarlet Tower (Arduboy) - Water Stage Clear Intermission
FootDipDitherDemo.hex (29.0 KB)
Recording from the camera (my phone):
Scarlet Tower (Arduboy) - Water Stage Clear Intermission (Recording from camera)

1 Like

Regarding pure monochrome…

I’m sure it looks different, but I can’t imagine how it’s going to be any smoother or “perceived” as 2x the resolution. Your not taking into account persistence of vision - which really throws a wrench in things. I’d almost suggest it actually doubles the resolution (bigger pixels) since when the object is constantly moving now the smallest pixel size is actually 2x1.

To prove this take a simple object like a solid square and move it from left to right… with monochrome there is only moving it a single pixel at a time… So whatever the frames per second there are only 128 positions for the object to exist at, period. So at 128 FPS an object would move across the screen in 1 second - 1 pixel per frame.

Now if once you start talking about greyscale what you’re saying makes a little more sense since you can simulate “sub pixels” with varying brightness levels… so now you can imagine the square not moving 1 pixel at a time but 0.5, sometimes with a trailing “grey” pixel… giving the appearance of 256 “positions”… ie, smoother movement. Again, see all the other threads exploring that - and the samples above even.

But again none of that is true for purely monochrome. It’s very possible you’re confusing greyscale and monochrome since when you do weird things quickly with black and white what you end up with is actually greyscale…

For many games you’d benefit most (if you determined it was beneficial) from this type of “motion blur” for the sprites though, and you could accomplish that without a display driver managing the whole screen buffer.

I think what you’re describing is:

O = fully lit, o = partially lit

What would normally be two frames:



With grey scale you can add a "middle frame":


But now the pixels need to be grey (since the line is now half way between pixels)… so while again this is all black and white the timing has to be adjusted… because the O pixels have to be lit twice as long as the o pixels…

I went with the dither filter in the background…
Also, who are you replying to?

Hello there, folks! I am back!