2D antialiased graphics using OpenGL
Keith Packard
keithp@keithp.com
Thu, 11 Dec 2003 10:55:18 -0800
Around 12 o'clock on Dec 11, "Martijn Sipkema" wrote:
> I've taken a quick look at cairo at if I understand correctly it draws
> back-to-front
cairo is an immediate mode library, so it draws in whatever order the
application requests it to. It exposes the GL_SRC_ALPHA_SATURATE operator
so that applications may use it if they so choose. Note that cairo
doesn't dictate what destination format is used, so applications would
have to find something suitable before using this operator. The Render
extension can use external alpha buffers so that a 16 bit screen can still
use destination alpha operators.
> Handling gamma correction in the framebuffer is a pain. Can't we just
> assume that the framebuffer is gamma corrected?
Heh. Linear frame buffers need to be 10 to 12 bits per component to avoid
visible banding in continuous tone images. Turns out that the weird
exponential behaviour of the classic CRT matches the intensity response
curve of the eye well enough that 8 bits per component is usable in that
space. A happy coincedence, but it does mean significantly more
computation to take advantage of it.
As usual, Jim Blinn has a pretty good exposition of this behaviour in an
article called 'Dirty Pixels', published in a book of the same name.
> Sure, but relatively simple antiasliased graphics shouldn't require
> programmability.
Render provides for arbitrary filters when sampling data. I'm hoping to
take advantage of programmable pixel and fragment shaders to do
convolution in the hardware so that I can have hardware accelerated
correct gaussian blurred shadows under my windows. The software
implementation is "usable", but far from ideal.
> One way to draw antialiased fonts is to have the font coverage as an alpha
> channel for a texture. This will produce high quality and fast font
> rendering I think, but it doesn't take into account the location of the
> pixel components on an TFT screen.
Render exposes glyphs with precomputed opacity values for all three
components of the screen. As glyph hinting (at least today) requires that
glyphs be pixel aligned, we can easily precompute the three locations of
the glyph corresponding to the three visible components and select the
appropriate one on the fly. I've experimented with shifting glyphs by a
sub pixel and the results are quite encouraging:
http://keithp.com/~keithp/subpixel/
This was just a hack job (I rotated the PNM files by one byte), but it
looks worth implementing for cairo to improve text spacing. Moving from
100dpi to 300dpi will really help match the screen with printed output.
Of course, performance will suffer as few of the pixels are opaque or
transparent. But, I think I've demonstrated that really bad text
performance doesn't really seem to bother people (current per-component
text is drawn in software at around 50000 glyphs/sec)
> Using a high resolution bitmap alpha channel texture for the font and using
> multisample rendering for antialiasing might work also, but I doubt this
> would be of the same quality as having the font rasterizer do this.
That depends to a great extent on the desired output. For displaying
static text on the screen, you want to use the full hinting available in
the font and align stems to the sub-pixel grid. However, when animating
text, it's important to *avoid* sub-pixel grid alignment as you get
horrible motion artifacts. The multi-sample technique is probably close
to what you want, especially if you can use a gaussian filter rather than
a box.
-keith