[GUI] Blurry text in OpenGL with high AntiAlias values.

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
GrafZahl
Posts: 37
Joined: Mon Oct 20, 2014 6:24 pm

[GUI] Blurry text in OpenGL with high AntiAlias values.

Post by GrafZahl »

Hi,

I'm currently implementing a renderer for IMGUI ( https://github.com/ocornut/imgui ), based on Irrlicht function to render the GUI elements. However the issue I have is also there with the build-in Irrlicht GUI.
I created a short test to reproduce it. Basically it is the Hello-World example with enabled OpenGL and high AntiAlias value (32).

Code: Select all

 
#include <Irrlicht/irrlicht.h>
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
int main()
{
  SIrrlichtCreationParameters Parameters;
  Parameters.DriverType = video::EDT_OPENGL;
  //Parameters.DriverType = video::EDT_DIRECT3D9;
  Parameters.WindowSize = core::dimension2d<u32>(1024, 800);
  //Parameters.AntiAlias = 8;  // not blurry
  Parameters.AntiAlias = 32; // blurry
 
  IrrlichtDevice *device = createDeviceEx(Parameters);
 
  if (!device)
      return 1;
 
  device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");
 
  IVideoDriver* driver = device->getVideoDriver();
  ISceneManager* smgr = device->getSceneManager();
  IGUIEnvironment* guienv = device->getGUIEnvironment();
 
  guienv->addStaticText(L"Hello World! This is the Irrlicht Software renderer!",
      rect<s32>(10,10,260,22), true);
 
  smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));
 
  while(device->run())
  {
    driver->beginScene(true, true, SColor(255,100,101,140));
 
    smgr->drawAll();
    guienv->drawAll();
 
    driver->endScene();
  }
 
  device->drop();
 
  return 0;
}
 
 
When I set AntiAlias to 8 I get this result:
Image

However, do I set AntiAlias to 9 or higher, I get this result:
Image

(sorry for the small text, but the default font is very small and I want to keep the example simple)

The same happens also with text, rendered by IMGUI, where I noticed this effect the first time.
If I use DirectX9 instead the text is clear, as intended.

I did some things to investigate further at this:
  1. I searched in the Irrlicht library code for the AntiAlias value and found some parts in COpenGLDriver, where some OpenGL settings are applied depending on this value.
    I commented out all settings that are AntiAlias depending except the WGL_SAMPLES_ARB attribute. And the issue is still there, this means even when GL_MULTISAMPLE_ARB is not enabled anywhere in the code, there is some kind of AntiAliasing visible (not only for text, also for meshes). However this is only the case for AntiAlias values greater then 8, if it is 8 or less all AntiAlias effects are gone (whith GL_MULTISAMPLE_ARB disabled all the time).
  2. There is an IMGUI example, that uses pure OpenGL commands to render everything. First I implemented this OpenGL specific rendering before I adapted everything to Irrlicht privimive drawing functions. In this pure OpenGL implementation the text is never blurry, completely independent of the AntiAlias value.
    The rendering is quite simply:

    Code: Select all

     
     
        // We are using the OpenGL fixed pipeline to make the example code simpler to read!
        // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
        GLint last_texture;
        glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
        glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glDisable(GL_CULL_FACE);
        glDisable(GL_DEPTH_TEST);
        glEnable(GL_SCISSOR_TEST);
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnable(GL_TEXTURE_2D);
        //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context
     
        // Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
        ImGuiIO& io = ImGui::GetIO();
        float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y;
        draw_data->ScaleClipRects(io.DisplayFramebufferScale);
     
        // Setup orthographic projection matrix
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
     
        // Render command lists
        // ... here happens the privimitve rendering with glDrawElements() and so on, I did not copy it to this code, since I think it is not related to the issue. 
     
        // Restore modified state
        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);
        glBindTexture(GL_TEXTURE_2D, last_texture);
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glPopAttrib();
     
     
    So you can see there is not much happening. Nothing to switch on or off the Multisampling. However the text is clear.
    I compared with an OpenGL debugger all the commands that are performed on OpenGL level between the Irrlicht primitive draw implementation and the OpenGL implementation.
    Of course Irrlicht does a lot of more things but in the end I found out that the issue is related to these commands:

    Code: Select all

     
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glTranslatef(0.375, 0.375, 0);
     
    These commands are set inside the setRenderStates2DMode() function when the flag Transformation3DChanged is set.
    If I add them to the pure OpenGL implementation, I also get blurry text when AntiAlias is greater than 8.

    I had a look at the IMGUI description and saw the following comment there:
    Q: I integrated ImGui in my engine and the text or lines are blurry..
    A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
    Then I added this code to the pure OpenGL implementation and the blurred text was gone again, even when the text is not completely clear (it seems that it is shifted by 1/4 or 1/2 pixels) :

    Code: Select all

     
      glMatrixMode(GL_PROJECTION);
      glTranslatef(0.375, 0.375, 0);  
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glTranslatef(0.375, 0.375, 0);
     
  3. The next thing I tried was to comment out this line "glTranslatef(0.375, 0.375, 0);" in the setRenderStates2DMode() function of the OpenGL driver (is around line 3234) and the issue was solved for the Irrlicht IMGUI renderer. Also the native Irrlicht GUI Text is clear again (the example above does not show this error anymore).
So I'm not an expert for 3D rendering, but the issue seems to be somehow related to the Matrix setup.
Could anyone explain to me why the "glTranslatef(0.375, 0.375, 0);" is done in setRenderStates2DMode() and why my issue is solved as soon as I comment out this line? Does it have side effects to other render operations?
Any further ideas about this topic?
Irrlicht related projects:
Looking for a cool and easy to use GUI? Try the IrrIMGUI bindings for IMGUI: https://github.com/ZahlGraf/IrrIMGUI
Try out my Irrlicht CMake build system: https://github.com/ZahlGraf/IrrlichtCMake
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: [GUI] Blurry text in OpenGL with high AntiAlias values.

Post by CuteAlien »

Seems it was done in version 850. And still had a comment back then which got removed at some point (don't ask me why, I have no clue). The comment linked to the explanation: https://www.opengl.org/archives/resourc ... m#tran0030

I can reproduce the problem, but don't know more about it yet.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
GrafZahl
Posts: 37
Joined: Mon Oct 20, 2014 6:24 pm

Re: [GUI] Blurry text in OpenGL with high AntiAlias values.

Post by GrafZahl »

Hi

Your link helped me a lot to understand the issue.
I found several interesting discussions when searching for "opengl translation 0.375 FSAA".

So far as I understood, OpenGL interprets the coordinates different on the type of primitive that should be rendered.
When a pixel or line should be rendered, the pixel is only used by a line, when it is near to the pixel center (search to diamond exit rule for more information). But the pixel center for OpenGL has an 0.5 offset.
That's why a rectangle (from lines) from 0,0 to 10,10 needs actually the coordinates of 0.5,0.5 to 10.5,10.5 to be precise. Then the chance is very high, that the right pixel is found as pixel to use for that line. However, even then it is hardware dependent, since NVidia and ATI seems to have different algorithms for rounding the numbers.

Other primitives like triangles (that are the primitives I use here) will just fill every pixel that is "touched" by the primitive, even when it is not at the center of the pixel. That's why you can build a perfect filled rectangle by using the coordinates of 0,0 to 10,10.

To be able to draw all types of primitives and handle different kind of rounding algorithms, the magic number 0.375 for translating all coordinates was introduced by the most applications. This will help the diamond rule to find the correct pixel for lines and single pixel drawings and it will not influence the triangle drawing too much.

At least this is the description I found. The issue is now, that advanced Anti-Aliasing algorithms like FSAA will do strange things with triangle primitives that has such an offset. FSAA is often not enabled at low Anti-Aliasing values, but there is an hardware dependent threshold, when it is switched on in addition to MSAA. That's why I don't see this effect at AA levels 0-8. But it could differ from graphic card to graphic card.

Is there a possibility to switch on to different glTranslate values for the Modelview Matrix depending on which primitive should be rendered next? If so, this might be a proper solution. However this would introduce new overhead, maybe such a switch should only be applied on high AA levels...

Best regards,
GrafZahl
Irrlicht related projects:
Looking for a cool and easy to use GUI? Try the IrrIMGUI bindings for IMGUI: https://github.com/ZahlGraf/IrrIMGUI
Try out my Irrlicht CMake build system: https://github.com/ZahlGraf/IrrlichtCMake
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: [GUI] Blurry text in OpenGL with high AntiAlias values.

Post by CuteAlien »

I wonder if AA ever makes sense for GUI. Maybe for the lines... but I doubt it's ever good for fonts. I think it should be disabled completely for font-drawing. As workaround you could probably disable it before the guienv->drawAll(); call.

Edit: Hm, or is AA used always for the whole frame in some way? I've never digged into that stuff ...
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
GrafZahl
Posts: 37
Joined: Mon Oct 20, 2014 6:24 pm

Re: [GUI] Blurry text in OpenGL with high AntiAlias values.

Post by GrafZahl »

Yes you are right, AA does not make much sense for the GUI.
However I was not able to find a way to disable it just for a certain render step.

I tried to disable it with the Material Flag (and I guess this is the way the Irrlicht build in GUI uses it), but it had no effect.
I also tried to disable it via OpenGL commands directly (as I wrote above) "glDisable( GL_MULTISAMPLE_ARB)" but even this did not work, since this will only affect MSAA.

Edit:
Edit: Hm, or is AA used always for the whole frame in some way? I've never digged into that stuff ...
Yes it seems so, at least some parts of the AA.
Irrlicht related projects:
Looking for a cool and easy to use GUI? Try the IrrIMGUI bindings for IMGUI: https://github.com/ZahlGraf/IrrIMGUI
Try out my Irrlicht CMake build system: https://github.com/ZahlGraf/IrrlichtCMake
GrafZahl
Posts: 37
Joined: Mon Oct 20, 2014 6:24 pm

Re: [GUI] Blurry text in OpenGL with high AntiAlias values.

Post by GrafZahl »

One update from my side here:
In the current version of my IMGUI renderer I just subtract from every vertex -0.375 from X and Y. With this I get a clear and non-blurry text and GUI output, even when Anti-Aliasing is enabled with very high values.

So it seems to be a workaround to compensate the +0.375 offset that is introduced by Irrlicht.
However it is just a workaround and furthermore the Irrlicht GUI has exactly the same issue.
Thus I think Irrlicht needs a real solution for that.

I'm not an expert for OpenGL, so I don't know what is possible and what not but I have two suggestions:

1.) The 0.375 offset is just a trade-off to draw line and pixel primitives (that needs an 0.5 offset) correctly, without harming triangle primitives (that does not need any offset) too much. It was a standard solution in the past when low-tech Anti-Aliasing was the standard for most systems.
However now with more advances Anti-Aliasing techniques like FSAA, this offset leads to blurry textures for triangles. And furthermore, it is not possible to disable those techniques just for a certain render step.

Here I think the best solution would be to apply the 0.375 offset to the modelview-matrix only in case line- and pixel primitives are drawn and to reset the modelview-matrix for other primitives. Is this possible?

2.) If this is not possible with reasonable performance, then we need a workaround at least for the Irrlicht GUI. Here I would suggest to add an negative offset of -0.375 to all vertices of the Irrlicht GUI to compensate this effect.

What do you think Alien?

Best regards
Graf Zahl
Irrlicht related projects:
Looking for a cool and easy to use GUI? Try the IrrIMGUI bindings for IMGUI: https://github.com/ZahlGraf/IrrIMGUI
Try out my Irrlicht CMake build system: https://github.com/ZahlGraf/IrrlichtCMake
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: [GUI] Blurry text in OpenGL with high AntiAlias values.

Post by CuteAlien »

I also think we need a solution for that and appreciate all feedback. Problem right now is that I'm not familiar with that stuff so I have to find some free time to read myself into this stuff first ...
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
GrafZahl
Posts: 37
Joined: Mon Oct 20, 2014 6:24 pm

Re: [GUI] Blurry text in OpenGL with high AntiAlias values.

Post by GrafZahl »

I understand this... From my point of view the code change it not very simple, since it might be done at several functions inside the OpenGL driver. Furthermore I don't even know if this is possible or if it will have major drawbacks.
So it is clear, that this might be a risky change, that needs to be tested carefully.

Unfortunately I also do not have enough experience with OpenGL in general or with the OpenGL driver to support you here :( I'm very sorry.

However the workaround with subtract 0.375 from X and Y directly when you create the GUI elements, could be a temporary solution for the build in Irrlicht GUI. I think this is something that could be done quite fast.
But be careful: This offset should only be applied in OpenGL mode, in DirectX mode it must not be applied (I've tested it).

Best regards,
Graf Zahl
Irrlicht related projects:
Looking for a cool and easy to use GUI? Try the IrrIMGUI bindings for IMGUI: https://github.com/ZahlGraf/IrrIMGUI
Try out my Irrlicht CMake build system: https://github.com/ZahlGraf/IrrlichtCMake
jazztickets
Posts: 1
Joined: Tue Feb 19, 2019 5:30 pm

Re: [GUI] Blurry text in OpenGL with high AntiAlias values.

Post by jazztickets »

Just so y'all know, setting glTranslatef(0.375, 0.375, 0) globally is very, very bad. Read up on the diamond exit rule: https://stackoverflow.com/a/10341863

When drawing NON-FILLED rectangles, that's when you apply a 0.5 (not 0.375) shift in the coordinates. When drawing FILLED quads, no shifting should occur. Otherwise you'll end up with blurry images!

0.375 is an artifact from a time when drivers were crap and didn't behave consistently. I've achieved pixel perfect filled/nonfiled rectangle drawing in my opengl engine using the aforementioned techniques across all drivers (amd, nvidia, intel): https://imgur.com/d8e5Uor
Post Reply