The other day, I asked myself quite a few questions about the whether or not it is possibility to create 22-bit color output, when you only have 16-bit dithered input. The cause for this question was a column written by 3dfx's Gary Tarolli. At first, it sounds like a hoax, or at least like a lame excuse for their lack of support for true 24-bit color. But, as I will show in this article, it is indeed possible to approach 22-bit color output using just 16-bit dithered input. However, this technique has a couple of nasty side effects. Whether they are acceptable or not, is up to you. I will first try to explain a basic way to increasing the color depth, starting from a dithered input. Note that this is not necessarily the way 3dfx is doing it, but I assume that their technique is similar. After the more general part, I will refer to a possible implementation used by 3dfx.

So first of all how does it work, well let’s explain it by using a pipelined diagram.

Internally, the 3dfx processor is working with 24 or even 32 bits of color information. This data cannot be stored in the 16-bit frame buffer, so the color information has to be reduced to 16 bits. This is achieved by down sampling while dithering. Dithering is a process whereby colors are approximated by intermixing pixels of two or more colors on the screen. "Intermixing", in this context, is the placing of pixels, of different colors, next to each other. When looking from a distance, your eye will perceive a different color, a blend. For example, if you use a checkerboard of red and white pixels, your eye will "see" a shade of pink. This is how dithering is able to simulate millions of colors. However, the images produced by this process reveals a grainy or patterned texture, which is usually undesirable. To reduce the impact of the patterns, you can perform a form of up sampling back to 24-bit color. One way to do this is to use a filter. This filter will determine a new 24-bit color by using the color information from several 16-bit pixels surrounding the actual screen pixel. So instead of just using the color at position (x, y), you also use the color information from the pixels at the surrounding positions, like (x+1, y), etc. The result of this filter is passed to the RAMDAC, which translates the digital color information into an analog signal for the monitor.

For more information about how dithering is implemented check this article.

The only thing that is new and special thing is the up sampling to 24 bits via a filter. So I will now discuss this a bit more in detail. A filter can be seen as a black box with several inputs and one output. In this case, the inputs are several 16-bit dithered color values. Inside the black box is a mathematical function that translates this input into a single output value. We would like to have a 24-bit output value that is close to the 24-bit value that the 3D core produced before the dithering and down sampling was applied. Now the question is, what is inside this black box? 3dfx hasn't revealed the contents of their black box, but we can make some guesses. First though, I will describe some general methods.

One way of doing it would be like this: We take four 16 bit color values. The color of the actual pixel and the ones to right, below it and below right. And now we simply combine these 4 color values by mixing them together (just like our eye would do). So if we write it like a formula:

Color 24 bits = (Color 16 bits A + Color 16 bits B + Color 16 bits C + Color 16 bits D) /4

This is a simple average calculated with 24-bit accuracy with 16-bit input. This is fairly simple to implement in hardware (getting the inputs without destroying your bandwidth is another matter. More on that later on in the article).

Now for better results we can use different and more complex filters. We could, for example, average a 3 by 3 zone. So we'd read the 8 pixels surrounding the actual screen pixel and blend them together. We can also give a higher importance to the central pixel by multiplying it with 2. All kinds of filters are possible and 3dfx probably spent quite a bit of time trying to find a good filter.

So how does it look, is it really better? Well I created some test images that more or less show you what happens.