tsoding / ded

Dramatic EDitor
MIT License
579 stars 76 forks source link

Distance field font rendering #60

Closed mate-h closed 1 year ago

mate-h commented 1 year ago

Using freetype's built in signed distance field flags to render text with anti aliasing. Note that in this case sub-pixel antialiasing is still not implemented which results in subtle visual errors when the text is scrolling at smaller scales.

screenshot-2 screenshot-1

rexim commented 1 year ago

@mate-h looks very promising! I'll take a look into that a bit later today. Thanks!

rexim commented 1 year ago

@mate-h looks good to me! :+1: Thank you for your contribution! I'll fix the CI later. Kappa

bovacu commented 1 year ago

Just a quick question, SDF is well known to be really good at upscaling the fonts, but not downscaling and if you create a smaller font (as I could see on main.c, the font size is 64) such as 12 or 15, usually it looks really bad. Haven't tried it on ded, but just a heads up on this common problem, do you have an idea in mind on how to fix this problem?

Edit: So I compiled it and test it with a smaller font and this is how it looks, and if the camera zooms a bit out, it also gets really pixelated, cannot read anything:

image

mate-h commented 1 year ago

Thanks for bringing this up. I think implementing sub-pixel antialiasing and oversampling could solve this issue potentially. I should submit a separate PR for that.

Oversampling involves adding a for loop the text shader that determines the average pixel alpha based on more than 1 sample around the current pixel being shaded.

Sub pixel antialiasing involves using the R,G,B channels of a pixel to toggle on only 1/3 of a physical pixel.

https://en.m.wikipedia.org/wiki/Subpixel_rendering

bovacu commented 1 year ago

Wow thanks for the answer! Thanks for the link too, if you create that PR and you remember to link it here it would be nice! To follow the progress of the feature.

mate-h commented 1 year ago

Got the subpixel rendering working, looks pretty good from a distance. This is what it looks like up close: Screen Shot 2023-02-15 at 4 03 44 PM

From a distance: Screen Shot 2023-02-15 at 3 56 43 PM

bovacu commented 1 year ago

So you substituted SDF rendering for subpixel rendering or are you making it switch to use one or the other depending on the situation? In this case the situation is the font size

mate-h commented 1 year ago

The shader program is still using the SDF to determine the exact area being occupied by the character. This method is using both approaches with additional implementation in the fragment shader. The coordinate system for each glyph needs to be shuffled around such that we know the exact size of the glyph being rendered in the fragment shader. Additional uniforms needed:

uniform vec2 atlas_resolution;

Attributes changed:

out vec2 out_uv;
out vec4 out_atlas;

The out_uv attribute now reflects the normalized coordinate space of the fragment. The out_atlas attribute represents the position and scale of the glyph with respect to the atlas. Together with the atlas_resolution uniform the exact pixel size of the glyph can be determined in the fragment shader.

Also, something to consider here is HDPI displays, in which case it only works if the SDL_WINDOW_ALLOW_HIGHDPI is enabled. https://wiki.libsdl.org/SDL2/SDL_WindowFlags

mate-h commented 1 year ago

Screen Shot 2023-02-16 at 10 37 20 AM

Example implementation:

https://github.com/mate-h/ded/pull/1

Based on this shadertoy:

https://www.shadertoy.com/view/4dsSzs

bovacu commented 1 year ago

Wow this is amazing! Really nice job! I'm not that good with shaders and I'd like to ask if you have any resources to learn more about them (beyond checking shadertoy and play with the shaders, something more theorical maybe).

mate-h commented 1 year ago

Appreciate the positive feedback. Learning openGL and shaders is very long and painful process (end results are always worth it). I am a year and a half in and still not quite done with learning it. This book is a good start: https://thebookofshaders.com/

mate-h commented 1 year ago

Just a quick question, SDF is well known to be really good at upscaling the fonts, but not downscaling and if you create a smaller font (as I could see on main.c, the font size is 64) such as 12 or 15, usually it looks really bad. Haven't tried it on ded, but just a heads up on this common problem, do you have an idea in mind on how to fix this problem?

Edit: So I compiled it and test it with a smaller font and this is how it looks, and if the camera zooms a bit out, it also gets really pixelated, cannot read anything:

image

Also one more thing to try is to increase the resolution of the atlas to improve the quality of the rendered glyphs.