⚠️ This repo is still being developed, so you may not find some of the listed features.⚠️
awesome-msdf is a collection of various glsl shaders utilizing MSDF (multi-channel signed distance fields) to render text in high quality while being magnified, minified or rotated in 3D space. It shows the basic usage of MSDF in text rendering with some additional, more advanced text modifiers.
All assets and characters were generated by the msdfgen utility. Options to create the character assets were MTSDF (multi-channel true signed distance field) type with distance field pixel range of 6.
For 2D rendering, you are better off using a rasterizer since there are no constant text size or rotation modifications, unlike in 3D rendering.
Remember to generate a texture atlas with msdf-atlas-gen utility and not to generate every character texture separately, as shown in the examples. The utility can also output an arfont file containing all character atlas positions, kerning info, spaces between characters and more.
Read through the README in the shaders folder for more detailed shader explanations and a few tips.
To see how the shaders work in real-time, you can download the SHADERed desktop application, open the '.sprj' file from the repo with the SHADERed app and see the output on the canvas. Learn more about SHADERed on their official Tutorial website or by watching Youtube tutorials.
The following snippet shows the basic usage of an MSDF texture (distance field pixel range 6) to render text while preserving the highest quality. For more info, check out this explanation from the msdfgen creator.
uniform sampler2D tex;
in vec2 uvCoord;
out vec4 outColor;
float median(float r, float g, float b) {
return max(min(r, g), min(max(r, g), b));
}
float screenPxRange() {
vec2 unitRange = vec2(6.0)/vec2(textureSize(tex, 0));
vec2 screenTexSize = vec2(1.0)/fwidth(uvCoord);
return max(0.5*dot(unitRange, screenTexSize), 1.0);
}
void main() {
vec4 texel = texture(tex, uvCoord);
float dist = median(texel.r, texel.g, texel.b);
float pxDist = screenPxRange() * (dist - 0.5);
float opacity = clamp(pxDist + 0.5, 0.0, 1.0);
outColor = vec4(0.5, 0.5, 0.5, opacity);
}
Below, you can find links to all the sources that helped me learn about MSDF and create this repo.
- What is state-of-the-art for text rendering in OpenGL as of version 4.1? - Stack Overflow - A discussion about today's popular text rendering methods, including SDFs.
- Text Rendering For Games - The presentation covers three different ways to render text for games (one being SDFs).
- The Valve paper - This short pdf by Valve originally proposed using distance fields to render text.
- Glyphs, shapes, fonts, signed distance fields - YouTube - Short video explaining how to generate and use SDFs to render text or other 2D shapes.
- Drawing Text with Signed Distance Fields in Mapbox GL - This short article covers how SDFs work and the basic usage of SDFs for text rendering.
- Cinder-SdfText: Initial Release (WIP) - Cinder - Interesting discussion about an SDF text renderer and improving the shader code to preserve the quality of minified SDF texts.
- Signed-distance-field fonts look crappy at small pt sizes - JVM Gaming - Another interesting discussion where preserving the quality of scaled SDF texts is the main topic.
- Antialiasing with a signed distance field - Musing Mortoray - This article explains how to set up the shader code for true anti-aliasing correctly.
- Antialiasing For SDF Textures - An article which shows different ways of setting up the shader code for better anti-aliasing. Some parts are based on the explanations of the article above.
- Rendering Signed Distance Fields, Part 1 « Essential Math Weblog - Part 1 of the blog explains the math behind the anti-aliasing of SDF text.
- Rendering Signed Distance Fields, Part 2 « Essential Math Weblog - Part 2 of the blog goes more in in-depth.
- Rendering Signed Distance Fields, Part 3 « Essential Math Weblog - Part 3 of the blog presents the final shader product for anti-aliasing.
- Partial Derivatives (fwidth) | Ronja's tutorials - Explains what and how the partial derivate functions fwidth(), ddx() and ddy() work (dFdx() and dFdy() in glsl).
- Chlumsky/msdfgen: Multi-channel signed distance field generator - Utility for generating SDF and M(T)SDF from vector shapes and fonts. Use msdf-atlas-gen to generate font atlases for rendering. If this project didn't exist, this repo wouldn't exist either.
- Implementing SDF/MSDF Font In OpenGL - An article covering how MSDFs are generated, how they work and the basic usage of MSDFs for text rendering.
- MSDF text rendering performance demonstration - YouTube - Short video presenting the performance of using MSDFs when rendering a lot of text. Note that minified text looks much worse than the rest, but I am convinced that methods used in the examples avoid that efficiently.
- leochocolat/three-msdf-text-utils,
- suikki/sdf_text_sample,
- Evolut-Group-Pty-Ltd/Lavo-2.0,
- wassy310/MJ_Simulator,
- maltaisn/msdf-gdx,
- MSDF Preview,
- Cierpliwy/sdf-test,
- jinleili/sdf-text-view - wgsl shaders,
- TinySDF demo,
- ShoYamanishi/SDFont
- MaxVell89/particles-animation
There are two reasons why I wanted to make this repo. The first reason is that I am very interested in distance fields and their usage in rendering. Therefore, this repo helps me to understand and learn more. The second reason is the rare findings on this topic over the internet. While searching for code examples and usage information regarding the subject, I could only find a few articles. Also, searching on GitHub, I often found the same basic code snippet repeating itself in almost every repo. I want to fill this repo with as much information and code examples (basic to advanced) as possible, so other people don't have to search aimlessly.
All contributions, such as fixing grammar, adding new sources and improving shader code, are welcome.
If you have questions about the topic feel free to post them in the discussions section.