🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Font smoothing

Started by
4 comments, last by matt77hias 3 years, 11 months ago

Given full pixel AA (http://rastertragedy.com/RTRCh2.htm#Sec1)%E2%80%8B)​ (coverage in alpha, no sub-pixel rendering) using a pre-generated glyph cache (no additional data structures, no (M)SDF, etc.), is it possible to avoid (e.g., in the final shader) that a white text on a black background looks fatter than a black text on a white background?

Browsers tend to solve this problem through different font smoothing settings (https://www.zachleat.com/web/font-smooth/​),​ but I have no idea about the internals of those (and how much is done on the CPU vs GPU).

🧙

Advertisement

This looks like a gamma-correction issue. Perform blending in linear color space, then convert to sRGB on display, and the difference between the two should go away.

Assuming the “glyph cache” contains an alpha channel that your shader uses to interpolate between the foreground and background colours, you could introduce a nonlinear transformation with one or more parameters that you can adjust to your taste to make text thinner or fatter.

For example (assuming alpha values between 0 for background and 1 for glyph interior) effective coverage can be the glyph cache coverage raised to a certain power: for a power between 0 and 1 the glyph becomes fatter, for a power above 1 the glyph becomes thinner.

Omae Wa Mou Shindeiru

a light breeze said:

This looks like a gamma-correction issue. Perform blending in linear color space, then convert to sRGB on display, and the difference between the two should go away.

The glyph cache texture has a `R8G8B8A8 sRGB` format. In this example, the texels have either { 0,0,0 } or { 1,1,1 } RGB components. The A component is the only one that really matters as that contains the coverage. After sampling from the glyph texture, the RGB components are pre-multiplied by the A. (Note that the sRGB format is not really necessary here, as the hardware filtering will still result in the same linear color without, since the A component is linear.)

The pre-multiplied color will be combined with a vertex color (in this example, either { 0,0,0,1 } or { 1,1,1,1 }).

The final color is written to a render target with a `R8G8B8A8 sRGB` format. So all color arithmetic (including the blending) happens in linear space, while all colors are stored as sRGB.

http://rastertragedy.com/RTRCh5.htm#Sec3​ mentions that the gamma exponent can be tweaked to adjust the perceived boldness for the black and white case. I currently, just rely on the implicit hardware conversions from and to sRGB.

🧙

LorenzoGatti said:

Assuming the “glyph cache” contains an alpha channel that your shader uses to interpolate between the foreground and background colours, you could introduce a nonlinear transformation with one or more parameters that you can adjust to your taste to make text thinner or fatter.

For example (assuming alpha values between 0 for background and 1 for glyph interior) effective coverage can be the glyph cache coverage raised to a certain power: for a power between 0 and 1 the glyph becomes fatter, for a power above 1 the glyph becomes thinner.

That could indeed be a solution as it seems more a perceptual issue than a rendering issue. Unfortunately, this seems to depend on the background color, requiring custom blending in the pixel shader, as I do not see how this can be achieved in the output merger.

🧙

This topic is closed to new replies.

Advertisement