Skip to content

Improving zoomed font quality a bit through shaders #858

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Flix01 opened this issue Oct 4, 2016 · 1 comment
Closed

Improving zoomed font quality a bit through shaders #858

Flix01 opened this issue Oct 4, 2016 · 1 comment

Comments

@Flix01
Copy link

Flix01 commented Oct 4, 2016

I think I've just found that by using the same kind of fragment shader that is commonly used to display signed distance fonts (SDF), we can achieve anti-aliasing in unmodified Dear ImGui (almost) for free (at least on my NVIDIA card...)!

The main drawback, aside from an expected performance drop, is that we lose all the intermediate values between 0 and 1 in the alpha component of the bound textures (e.g. of the main font texture used by ImGui internally and of all user textures that are passed to ImGui::Image(...) and ImGui::ImageButton(...)).

However I'm not sure if ImGui is using these intermediate values or not.

User textures that contain alpha values inside the range (0,1) are the main problem: thay can't be displayed correctly with the SDF shader.

Code:

In "imgui/examples/opengl3_example/imgui_impl_glfw_gl3.cpp"
replace the main function of the fragment shader with the following:

            "void main(void) {\n"
            "vec4 texColor = texture2D(Texture, Frag_UV.st);\n"
            "float width = fwidth(texColor.a);\n"
            "float alpha = smoothstep(0.5 - width, 0.5 + width, texColor.a);\n"
            "Out_Color = vec4(Frag_Color.rgb*texColor.rgb,Frag_Color.a*alpha);\n"
            "}\n";

            // Note that we could just comment out the 3rd line and calculate alpha trivially as:
            //"float alpha = smoothstep(0.0, 1.0, texColor.a);\n" // to speed up things a bit,
            // but fwidth computes the derivates [abs (dFdx (p)) + abs (dFdy (p));] 
            // and 'should' smooth things better, generating intermediate alpha values AFAIK. [We should test this]

It can easily be adapted for OpenGL version 2, OpenGLES, WebGL (and probably converted to Direct3D too).

P.S. Using the default, non-SDF shader together with a filter like GL_NEAREST we get a worse result (but without the texture alpha channel degradation problem).

These images have been taken using the embedded imgui font scaled at the maximum size allowed by: ImGui::GetIO().FontAllowUserScaling = true;

non-SDF shader + GL_NEAREST
gl_nearest-default_shader

SDF shader + GL_LINEAR
gl_linear-sdf_shader

People from this issue #618 might be interested in this topic too.

@Flix01
Copy link
Author

Flix01 commented Oct 4, 2016

On a second thought I'm not sure that this hack is really useful 😒.
In fact the default setting of the opengl3_example

non-SDF shader + GL_LINEAR
gl_linear-default
does not look much worse than my "upgraded version"!

I still have to understand why in my projects scaled text looks way blurrier than in this demo... and my hack seemed to work better... 👎

[Edit:]

IN SHORT

  • An SDF-shader makes sense only if we can generate a SDF Font texture for ImGui.
  • GL_NEAREST seems to be a good solution (maybe with oversampling of 1:1, or at least squared).
  • If we need a shader (with GL_LINEAR filtering) to improve scaled fonts, a simple and fast alpha-sharpening shader (without derivatives) is often enough:
            "void main(void) {\n"
            "vec4 texColor = texture2D(Texture, Frag_UV.st);\n"
            "float alpha =step(0.5,texColor.a);\n"
            "Out_Color = vec4(Frag_Color.rgb*texColor.rgb,Frag_Color.a*alpha);\n"
            "}\n";

gl_linear-alpha_in_0_1

            "void main(void) {\n"
            "vec4 texColor = texture2D(Texture, Frag_UV.st);\n"
            "float alpha =step(0.5,texColor.a*1.2);\n"
            "Out_Color = vec4(Frag_Color.rgb*texColor.rgb,Frag_Color.a*alpha);\n"
            "}\n";

gl_linear-alpha_in_0_1_ 2

  • However all the shaders that modify the texture alpha value, slightly modify the appearance of the unscaled text too, and of all the textures with (alpha!=0.0 && alpha!=1.0). So additional care must be taken into account.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants