Disclaimer: this article is meant to describe the precision that the DS uses for interpolation as well as how interpolation works. It is not meant to deride DeSmuME (which uses lower precision on default settings), nor proclaim that CorgiDS is better (it isn’t). This is wholly a technical article, not a contest. I apologize if the tone of the article indicates otherwise.
CorgiDS now supports color interpolation! Observe these shiny screenshots:
Astute observers may notice that the output here differs from something like DeSmuME. This is because, along with melonDS, CorgiDS uses the same color precision that the DS uses! StapleButter, the developer of melonDS, has helped immensely in getting interpolation working, as well as giving me information about the quirks of the DS GPU.
For comparison, here’s the output from DeSmuME using default settings on my Mac:
How does interpolation work? If you’re unfamiliar with the term, interpolation simply means finding any number of values within the boundaries of two known values. Consider the following: say you have a function f(x). You are given the values for, say, f(0) and f(10). Interpolation would be finding the values between f(0) and f(10), such as f(1), f(2), and so on.
The DS uses interpolation for both vertex colors (shown in the screenshots) and textures, the latter of which I’ve yet to implement. Both methods use the following formula:
((p – a)u1w2 + a(u2w1)) / ((p – a)w2 + aw1)
This formula outputs the interpolated attribute of pixel a. There’s a lot of stuff here, but the formula is simpler than it seems:
- a is the pixel number of the line on which interpolation is to take place, ranging from 0 to p.
- p is the total number of pixels on the line.
- u1 and u2 are the attributes of the boundaries of the line. With color interpolation, these are the colors, and with texture interpolation, these are the texture coordinates.
- w1 and w2 are the w-values of the boundaries. If you don’t recall, the DS uses four-dimensional matrices to clip polygons from a 3D representation to a 2D image. Vertices keep this fourth dimension, known as the w-axis. They are included in the formula to perform perspective correction.
Using this formula, color interpolation is deceptively simple. The left and right edges of a polygon are interpolated, and then the DS uses the result of the interpolation to interpolate the interior of the polygon. That’s all it takes!
…Well, no. In reality, as it tends to be with the DS GPU, things are more complicated. I mentioned earlier how CorgiDS and melonDS have more color precision than the other emulators. Vertex colors are 15-bit, meaning that each RGB value ranges from 0 to 0x1F (31), a measly amount considering that modern displays use at least 24-bit color. StapleButter discovered that the DS gets around this limitation by extending color precision to 27 bits during interpolation as to allow for a wider range of values and then reducing it to 18 bits for the display.
Furthermore, the above formula isn’t entirely correct. While it is what a modern GPU would use, the DS GPU is a lazy bastard and takes shortcuts. The GPU sets u1 and u2 to 0 and 1 respectively, giving the actual formula:
(p – a)w2 / ((p – a)w2 + aw1)
This formula gives a “perspective correction factor” that the DS uses to linearly interpolate colors and textures, which as you might guess, loses precision unnecessarily.
Another weird quirk: w-values are normalized to 16-bit precision using shift increments of 4. If a w-value is 12-bits long, for instance, the DS will extend this to 16-bits. However, if the w-value is 20-bits long, it is reduced down to 16-bits, greatly reducing precision. Why it couldn’t have done things like normal GPUs is beyond us emudevs… Nevertheless, documenting these quirks (and the many others) is necessary for pixel-perfect accuracy. Admittedly, I’m not aiming for 100% accuracy, but I’d still like to have some standards for accuracy myself.
If you haven’t guessed by now, next up is textures! Color interpolation is nice and all, but commercial games don’t run on vertex colors. With my newfound knowledge of interpolation, textures shouldn’t be a hard task at all.
Many thanks to StapleButter, who helped me understand many of the technical aspects of 3D graphics.