Home

Awesome

<h1 align="center"><i>awesome</i> <b>msdf</b></h1> <p align="center"><img src="assets/showcase/showcase.gif" alt="Logo"></p>

⚠️ This repo is still in development, 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.

Shaders, tips and real-time output

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.

Basic MSDF usage

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);
}

Sources, links, articles, discussions, more info

Below are links to all the sources that helped me learn about MSDF and create this repo.

Introductory sources

About SDFs (Signed distance fields)

Antialiasing SDF text

MSDFs (Multi-channel signed distance field)

Helpful code snippets

The repo motive

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.

Contributing and questions

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.