dfrg / swash

Font introspection, complex text shaping and glyph rendering.
Apache License 2.0
584 stars 34 forks source link

Subpixel Format Rendering? #18

Closed wooosh closed 2 years ago

wooosh commented 2 years ago

The subpixel format is described as "32-bit RGBA subpixel mask with 1/3 pixel offsets for the red and blue channels."

Could you elaborate on what 1/3 pixel offset means in this case? I'm not quite sure how to actually apply the subpixel mask to render text in a given color from looking at the docs (though I may have missed something obvious).

dfrg commented 2 years ago

For subpixel rendering, you essentially end up with three rasterized copies of the outline with one in each of the RGB channels. The green channel contains the original outline while the red and blue channels are shifted 1/3 pixel left and right, respectively. BGR pixel layouts are also common. In this case, the red and blue channels are swapped. The goal is to use the physical layout of the pixels of the monitor to get a 3x increase in horizontal resolution and thus crisper text.

Actually rendering these subpixel masks is a bit involved as it requires some extra setup in your rendering pipeline and can be done in several different ways. This webrender document covers the idea and possible implementations. The swash_demo repo implements subpixel rendering so there is some reference code in there. In particular, you can find the GLSL fragment shader here: https://github.com/dfrg/swash_demo/blob/master/src/comp/shaders.rs#L57 This makes use of dual source blending, so requires OpenGL 4.1 (or the relevant extensions). Vulkan and Metal support it out of the box.

wooosh commented 2 years ago

Thanks for the help!