How to draw ugly lines fast
cohost.org
cohost.org
This needs to be correct, and very fast -- sometimes the computational burden can limit your machine's top speed before the mechanical limitations are reached.
https://en.wikipedia.org/wiki/Apple_II_graphics#High-Resolut...
> The Apple II's Hi-Res mode was peculiar even by the standards of the day. [...] Each row of 280 pixels was broken up into 40 blocks of seven pixels each, represented in a single byte. Each pair of adjacent pixels generated a single color pixel via artifact color, resulting in an effective resolution of 140×192. The lower seven bits of each byte represented the pixels, while the most significant bit controlled the phase offset for that block of pixels, altering the color that was displayed.
> The other thing I need to do is subpixel-correct lines, because they're so much more nicer in motion than non-subpixel-correct lines. Don't confuse this with AA lines - you can have chunky non-AA single-colour pixel lines that are ALSO subpixel-correct.
> Why this is important is hard to convey in a static picture, but in motion the quality difference is very obvious. And it turns out the speed difference is not actually significant, so why not go for the extra quality?
This claim is made almost immediately in the article, but then provides no poof in picture OR video!
The breakdown of the algorithm and general writing is great though.
It's essentially pointing out the biggest issue with the article and then shrugging it off, while obviously putting a lot of effort into the writing.
Or you could post GIFs yourself. Maybe that seems like too much work?
Asking whether I'm willing to provide my own gif isn't quite a fair measure. The author has the code running and he himself commented on the need for moving pictures. I have partial code and no personal investment in this.
I have however written a few articles about stuff I've done for my own work and wherever it seemed relevant I've taken the time to produce and include video. That's been a lot less effort than writing the text, even when it's required a number of changes in the scenes and code.
(By sub-pixel they mean more finely determining the endpoints of the lines on an arbitrary grid finer than the output pixels — NOT physical display sub-pixels.)
I feel like I've gotten a better understanding of things I thought I knew already. The only question left in my mind is "why does he always need to write new subpixel-accurate line drawers?!"
Tom Forsyth
GPU designer and gfx coder
Gfx coder and chip designer. Worked at Oculus, Valve, RAD, Muckyfoot, 3Dlabs, now back at Intel. Blade2, Larrabee, TF2, VR and many other atrocities.For example, the standard algorithm would always generate lines that are symmetrical:
####
####
But the modified version lets you position the endpoints different, so that you'd get: ###
#####
or ##
######
etcWith subpixel precision (e.g. you do all the math at a higher precision than the framebuffer resolution, and preserve the fractional part of pixel coordinates in all computations until you actually write to the framebuffer), the outlines remain stable even for small movements. IIRC Quake (with the software renderer) was one of the first games which paid proper attention to subpixel accuracy, and they showed this off with a very slight camera movement at the result screen after a multiplayer match. Triangle edges were properly 'crawling' instead of being all jittery.
0 #
#######
##
######
###
#####
3 ####
####
#####
###
######
##
6 #######
#In the right circumstances this might all be fine and work well enough if you have enough precision for the fractional part, but this is no algorithm that I would recommend to anyone.
You can start reading from example Alvy Ray Smith's "A pixel is not a little square" http://alvyray.com/Memos/CG/Microsoft/6_pixel.pdf
But in the end, the sampling kernel you choose to sample your line, and, what sort of geometric primitive your line is in the first place, defaults back to matters of taste so there is a very good theoretical basis for discussing all of this, but, there is no ultimate absolutely correct answer that it will provide.
I'd say the sampling kernels aren't fully matters of taste, but matters of the display or sampling technology instead. Pixels on CRTs are indeed not little squares, but pixels on anything else pretty much are -- though they can be non-contiguous squares, with different patterns for different colors, even, which eliminates any simplicity that the little-square picture intuitively captures.
Fortunately, all this starts to matter less and less as pixel size and spacing gets smaller and smaller.
Sibling comment mentions the famous paper “A Pixel is Not a Little Square”. The implication being that using squares when computing analytic coverage for antialiasing is not “perfect”. The problem is we don’t have a single definition of perfect, because it depends on what display device you’re using. CRTs and LCDs and printers all have completely different ‘pixels’, so no single solution exists that works for all of them. Combine that with the fact that getting close to perfect for any given device is very computationally expensive, and you can see why we don’t usually even shoot for perfect.
> "But in practice you can do significantly better, especially for lines that are nearly horziontal..."
I must say though, "horziontal" does sound fancy!
I signed up to make a comment about it in the article but it "takes a day or two" for the account to be allowed to comment :shrug:
Go to page 15 of the results (the last page) and it says
> Page 15 of about 142 results
If I "include omitted results" it claims 331 results, but these include pages with the "horizontal" spelling only...
It's true when first and last points are within or not too far from the screen/clip, but if wanting to draw a long line (if coords are 32 bits ints) that's mostly out of it and don't want clipping to introduce half a pixel size errors/inconsistencies, unless running Bresenham for a long time out of the clip, floating points are a more accurate tool to do the clipping and the drawing.
See for example: https://github.com/jeffhain/jolikit/blob/master/src/main/jav...
[edit: it might actually be possible to jump to the clipped area while staying in integers and not loose accuracy, but I don't recall why I didn't try that]
I know compute shaders exist, but I have found that with huge datasets and a wide variety of end-user hardware, it tends to end up with many lines of code and brittleness. So I’m curious about high performance CPU-only implementations.