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;
}
However, do I set AntiAlias to 9 or higher, I get this result:
(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:
- 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). - 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:So you can see there is not much happening. Nothing to switch on or off the Multisampling. However the text is clear.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();
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:
These commands are set inside the setRenderStates2DMode() function when the flag Transformation3DChanged is set.Code: Select all
glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.375, 0.375, 0);
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:
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) :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).Code: Select all
glMatrixMode(GL_PROJECTION); glTranslatef(0.375, 0.375, 0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.375, 0.375, 0);
- 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).
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?