I’m trying to implement anti-aliased pixel rendering. My basic idea is to render 4 pixels instead of 1, and give each “real” pixel a weight based on its distance to the “virtual” pixel:
void put_aa_pixel(double x, double y)
{
int x0 = int(x);
int x1 = x0 + 1;
int y0 = int(y);
int y1 = y0 + 1;
double weight_x1 = x - x0;
double weight_x0 = 1 - weight_x1;
double weight_y1 = y - y0;
double weight_y0 = 1 - weight_x1;
put_pixel(x0, y0, int((weight_x0 * weight_y0) * 255));
put_pixel(x1, y0, int((weight_x1 * weight_y0) * 255));
put_pixel(x0, y1, int((weight_x0 * weight_y1) * 255));
put_pixel(x1, y1, int((weight_x1 * weight_y1) * 255));
}
Multiplying the x and y weights gives me the overlapping area of the virtual pixel inside each real pixel. I naively assumed this would give me a perfect anti-aliasing effect, but the moving pixels inside my test program just display an aweful flicker. It looks much worse then simple pixels without any anti-aliasing.
However, when I switch from multiplication to addition, it looks much better:
put_pixel(x0, y0, int((weight_x0 + weight_y0) * 127.5));
put_pixel(x1, y0, int((weight_x1 + weight_y0) * 127.5));
put_pixel(x0, y1, int((weight_x0 + weight_y1) * 127.5));
put_pixel(x1, y1, int((weight_x1 + weight_y1) * 127.5));
Adding the weights doesn’t seem to have any geometric significance. So why does this work better? What’s wrong with the first version? And is there an even better approach?
There was a bug lurking in my code for half a year:
Can you see the bug? Yes, it’s a classic copy and paste error:
After fixing the bug, the original multiplication approach looks very nice.