diff --git a/README.md b/README.md index 958f262..c624256 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,13 @@ to reproduce sharp corners almost perfectly by utilizing all three color channel The following comparison demonstrates the improvement in image quality. -![demo-msdf16](https://user-images.githubusercontent.com/18639794/86908136-5fdd4780-c116-11ea-96c5-4f58a42043a4.png) -![demo-sdf16](https://user-images.githubusercontent.com/18639794/86908146-6370ce80-c116-11ea-87ee-95bfb699665c.png) -![demo-sdf32](https://user-images.githubusercontent.com/18639794/86908155-65d32880-c116-11ea-9583-1b45f806bbd9.png) +![demo-msdf16](https://user-images.githubusercontent.com/18639794/106391899-e37ebe80-63ef-11eb-988b-4764004bb196.png) +![demo-sdf16](https://user-images.githubusercontent.com/18639794/106391905-e679af00-63ef-11eb-96c3-993176330911.png) +![demo-sdf32](https://user-images.githubusercontent.com/18639794/106391906-e7aadc00-63ef-11eb-8f84-d402d0dd9174.png) - To learn more about this method, you can read my [Master's thesis](https://github.com/Chlumsky/msdfgen/files/3050967/thesis.pdf). -- Check what's new in the [changelog](CHANGELOG.md). +- Check out my [MSDF-Atlas-Gen](https://github.com/Chlumsky/msdf-atlas-gen) if you want to generate entire glyph atlases for text rendering. +- See what's new in the [changelog](CHANGELOG.md). ## Getting started @@ -143,13 +144,12 @@ Using a multi-channel distance field generated by this program is similarly simp The only additional operation is computing the **median** of the three channels inside the fragment shader, right after sampling the distance field. This signed distance value can then be used the same way as usual. -The following is an example GLSL fragment shader including anti-aliasing: +The following is an example GLSL fragment shader with anti-aliasing: ```glsl -in vec2 pos; +in vec2 texCoord; out vec4 color; uniform sampler2D msdf; -uniform float pxRange; uniform vec4 bgColor; uniform vec4 fgColor; @@ -158,16 +158,35 @@ float median(float r, float g, float b) { } void main() { - vec2 msdfUnit = pxRange/vec2(textureSize(msdf, 0)); - vec3 sample = texture(msdf, pos).rgb; - float sigDist = median(sample.r, sample.g, sample.b) - 0.5; - sigDist *= dot(msdfUnit, 0.5/fwidth(pos)); - float opacity = clamp(sigDist + 0.5, 0.0, 1.0); + vec3 msd = texture(msdf, texCoord).rgb; + float sd = median(msd.r, msd.g, msd.b); + float screenPxDistance = screenPxRange()*(sd - 0.5); + float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); color = mix(bgColor, fgColor, opacity); } ``` -**Note:** This is an example shader only and probably is not optimal for your use case! Please do not blindly copy & paste. +Here, `screenPxRange()` represents the distance field range in output screen pixels. For example, if the pixel range was set to 2 +when generating a 32x32 distance field, and it is used to draw a quad that is 72x72 pixels on the screen, +it should return 4.5 (because 72/32 * 2 = 4.5). +**For 2D rendering, this can generally be replaced by a precomputed uniform value.** + +For rendering in a **3D perspective only**, where the texture scale varies across the screen, +you may want to implement this function with fragment derivatives in the following way. +I would suggest precomputing `unitRange` as a uniform variable instead of `pxRange` for better performance. + +```glsl +uniform float pxRange; // set to distance field's pixel range + +float screenPxRange() { + vec2 unitRange = vec2(pxRange)/vec2(textureSize(msdf, 0)); + vec2 screenTexSize = vec2(1.0)/fwidth(texCoord); + return max(0.5*dot(unitRange, screenTexSize), 1.0); +} +``` + +`screenPxRange()` must never be lower than 1. If it is lower than 2, there is a high probability that the anti-aliasing will fail +and you may want to re-generate your distance field with a wider range. ## Shape description syntax