Faster than Bresenham's Algorithm? (2009)
hbfs.wordpress.com
hbfs.wordpress.com
The thing is that Bresenham is resolution-independent. If the registers used have enough width to represent the coordinates of the entire display, then the line will be drawn correctly. The error term that is propagated through the loop is always precisely correct. There is no cumulative error from using approximations.
You can think of Bresenham's as being like fixed point, but with a variable denominator for the error term which depends on the specific delta. For instance if we are drawing 600 across (x) and 450 up (y), then the error term is basically an accumulator to which we add 450. Whenever it goes over 600, we subtract 600, and increment y. (Okay, so it is not like fixed point but in fact exact rational math. The error term accumulates numerators, which are compared to the denominator.)
We could represent the same approximately with a fixed point number, but that pins us to a denominator. If we have, say, 8 bits of fractional precision, then we work in multiples of 1/256. Now 450/600 is precisely 3/4, and so we are lucky in this case: 3/4 is a multiple of 1/256: the denominator is a power of two, and so we can step the x coordinate by 1, and the y coordinate by 3/4. The "staircase" will be the same as under Bresenham's.
Suppose delta is <453,599>. Bresenham's still deals with this precisely. 453 is added to the error term, and 599 subtracted when it blows past 599. Yet, 599 is a prime, and 453/599 has no exact representation in fixed point. The best we can do is add more bits of precision to minimize the cumulative error. If the display is on the order of 1000x1000 and we go down to 1/65535 sub-pixel precision in our fixed-point coordinates, maybe there is no noticeable artifact.
I ended up with an unrolled loop for 8 horizontal pixels and self-modifying code which jumped into this loop similar to a Duff's Device, and at each increment in y a pixel-mask byte was xor'ed into video memory, and a new jump-position into the pixel-loop was computed for the next 8-pixel-mask.
This was even fast enough for rendering a (distorted) 3D wireframe cube: https://www.youtube.com/watch?v=W8kxJLUParo
The line rendering code is here (I'm sure there's even more optimized 8-bit code out there): https://github.com/floooh/kc85sdk/blob/master/test/line.s
But the most important thing I learned in his class was that having a well-sorted-out compiler is more important than the choice of language. Most of the class used Borland Turbo Pascal for their projects (it was up to version 5 by that point, I think). I wanted to learn C, and with his approval I used their new version 1.0 Turbo C compiler. What I found was that the Pascal code, with no heroic coding efforts, ran 3-4 times faster than the supposedly "closer to the metal" C.
We might say that Bresenham's Algorithm is not really about drawing lines; it's about doing a best-possible discrete approximation to linear interpolation, using integer arithmetic.
And since we can easily[1] change that line to any conic section we want, we should be able to use a variation on B's Alg. to do a perspective-correct interpolation, right?
Sounds good to me. However, as perhaps you were, I'm too lazy[2] right now to work out the details. :-)
--------
[1] For certain values of "easy".
[2] Or perhaps "too busy". That sounds a bit better, doesn't it?
I guessed that the downfall of the approach would be the iterations spent on the same pixel value in a texture, when, so to speak, Bresenham is "going vertical": marching through Y values while treading on the same X. If X is the texture space, it's wasteful. While rasterizing, it really behooves us to just map backwards from screen pixels, get the color value and move on. On the other hand, the approach could do anti-aliasing: average those values being tread over. That is usually solved with mipmapping, though: pre-filtered textures at multiple resolutions. Again: no iterative work per display pixel.
Basic, aliased line drawing still has value on low resolution embedded devices that don't need 21st century display capabilities.