I'm trying to make an OpenGL program on Windows. Since the main exe file was getting bigger and bigger, I decided to split it into DLLs. And this is how my problem is started.
For ImGui functions, I created a class. Here is render() function of my class:
cout << "render" << endl;
imgui_newFrame();
{
ImGui::SetNextWindowSize(ImVec2(30, 30), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Test", &show_another_window);
ImGui::Button("Test Window");
ImGui::End();
}
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
ImGui::Render();
Before calling render() function in my class, I initiate ImGui in another function in my class with this:
if (!imgui_init(glfw_window)) {
return false;
}
And here is my main glfw loop:
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
glfwPollEvents();
MyMyGuiClass.render(); //here i ask my class to render imgui
glfwSwapBuffers(window);
}
With this code I am able to make ImGui clear window color (glClearColor function works and my console prints "render")
But it doesn't show anything else.
By the way, here is the command working perfectly when I run it.
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
glfwPollEvents();
imgui_newFrame();
{
ImGui::SetNextWindowSize(ImVec2(30, 30), ImGuiSetCond_FirstUseEver);
ImGui::Begin("", &show_another_window);
ImGui::Button("Test Window");
ImGui::End();
}
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
ImGui::Render();
glfwSwapBuffers(window);
}
I'm using VS2017 and my compiler doesn't show any warnings or errors when i compile this. Also I tried to make my class' functions static, and I got nothing.
So simply, is ImGui not able to render when called from inside a class?
The problem you're running into is that ImGui maintains a global state and that this state has to be kept somewhere. ImGui keeps it around in a module-local global symbol.
Note the "module-local" here! It means that every DLL (and the main EXE) gets its very own copy of that state. So doing things with ImGui in DLL "A" (or EXE "1" for that matter) will operate on its very own instance of ImGui state.
There is a solution to this, by making that pesky ImGui global state shared across DLLs. How to share data between DLLs is described in MSDN here https://msdn.microsoft.com/en-us/library/h90dkhs0(v=vs.90).aspx – as for the details in ImGui itself. It mostly boils down to the ImGuiContext that's being used. For now this is a module-local global variable, but the ImGui devs plan on making it explicit-per call and user managed eventually.
Comment from the ImGui code:
// Default context storage + current context pointer. Implicitely used by all
// ImGui functions. Always assumed to be != NULL. Change to a different context
// by calling ImGui::SetCurrentContext() ImGui is currently not thread-safe
// because of this variable. If you want thread-safety to allow N threads to
// access N different contexts, you might work around it by: - Having multiple
// instances of the ImGui code compiled inside different namespace
// (easiest/safest, if you have a finite number of contexts) - or: Changing
// this variable to be TLS. You may #define GImGui in imconfig.h for further
// custom hackery. Future development aim to make this context pointer explicit
// to all calls. Also read https://github.com/ocornut/imgui/issues/586
Related
I am trying to use QOpenGLWidget without subclassing.
When I try to make OpenGL calls outside of QOpenGLWidget's methods or signals, nothing seems to happen. For example, following code clears window black despite me setting glClearColor:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
auto glw = new QOpenGLWidget( this );
glw->makeCurrent();
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glw->doneCurrent();
connect( glw, &QOpenGLWidget::aboutToCompose, [=] {
glClear( GL_COLOR_BUFFER_BIT );
});
setCentralWidget( glw );
}
However, when I move glClearColor inside the lambda connected to the aboutToCompose signal, widget is cleared with white color.
As essentially explained in the comments section by Fabio and G.M., QOpenGLWidget::makeCurrent won't work if called before things are setup enough.
As of Qt 5.11 and probably other releases, QOpenGLWidget::makeCurrent works by calling the QOpenGLContext::makeCurrent method. That call only happens if the QOpenGLWidget is already in the initialized state however. Additionally, QOpenGLContext::makeCurrent can fail. The latter at least gives some indication of failure via its bool return parameter. Unfortunately, QOpenGLWidget::makeCurrent gives no indication at all. QOpenGLWidget::makeCurrent fails silently.
Besides knowing this & heeding the advice in the comments, one can use the QOpenGLWidget::context method to determine whether the QOpenGLWidget is in the initialized state. According to the linked documentation (and as seen in practice), the context method returns "0 if not yet initialized" or a non-null pointer otherwise. So it's a means to determine whether or not QOpenGLWidget::makeCurrent calls QOpenGLContext::makeCurrent and a means to partially work around QOpenGLWidget::makeCurrent returning void. That's probably not particularly useful in this case, but can be useful in other related contexts so I thought this worth mentioning.
So to get QOpenGLWidget::makeCurrent to actually succeed, QOpenGLWidget::makeCurrent has to be called after the QOpenGLWidget has been initialized in order for it to work.
Reading between the lines of this question, it sounds as if wondering about what was needed to be done in order for GL calls to work. And as the question's author recognizes, delaying the GL calls till the aboutToCompose signal has been fired, works for that (at least in the context of this user's code). Another way, is to make the QOpenGLWidget visible, then call the GL code.
Hope this answers your question completely if not at least helpfully.
You can call auto *ctx = QOpenGLContext::currentContext(); to check if makeCurrent succeeded.
I have a question about how to (correctly) use glewInit().
Assume I have an multiple-window application, should I call glewInit() exactly once at application (i.e., global) level? or call glewInit() for each window (i.e., each OpenGL rendering context)?
Depending on the GLEW build being used the watertight method is to call glewInit after each and every context change!
With X11/GLX functions pointers are invariant.
But in Windows OpenGL function pointers are specific to each context. Some builds of GLEW are multi context aware, while others are not. So to cover that case, technically you have to call it, everytime the context did change.
(EDIT: due to request for clarification)
for each window (i.e., each OpenGL rendering context)?
First things first: OpenGL contexts are not tied to windows. It is perfectly fine to have a single window but multiple rendering contexts. In Microsoft Windows what matters to OpenGL is the device context (DC) associated with a window. But it also works the other way round: You can have a single OpenGL context, but multiple windows using it (as long as the window's pixelformat is compatible with the OpenGL context).
So this is legitimate:
HWND wnd = create_a window()
HDC dc = GetDC(wnd)
PIXELFORMATDESCRIPTOR pf = select_pixelformat();
SetPixelFormat(dc, pf);
HGLRC rc0 = create_opengl_context(dc);
HGLRC rc1 = create_opengl_context(dc);
wglMakeCurrent(dc, rc0);
draw_stuff(); // uses rc0
wglMakeCurrent(dc, rc1);
draw_stuff(); // uses rc1
And so is this
HWND wnd0 = create_a window()
HDC dc0 = GetDC(wnd)
HWND wnd1 = create_a window()
HDC dc1 = GetDC(wnd)
PIXELFORMATDESCRIPTOR pf = select_pixelformat();
SetPixelFormat(dc0, pf);
SetPixelFormat(dc1, pf);
HGLRC rc = create_opengl_context(dc0); // works also with dc1
wglMakeCurrent(dc0, rc);
draw_stuff();
wglMakeCurrent(dc1, rc);
draw_stuff();
Here's where extensions enter the picture. A function like glActiveTexture is not part of the OpenGL specification that has been pinned down into the Windows Application Binary Interface (ABI). Hence you have to get a function pointer to it at runtime. That's what GLEW does. Internally it looks like this:
First it defines types for the function pointers, declares them as extern variables and uses a little bit of preprocessor magic to avoid namespace collisions.
typedef void (*PFNGLACTIVETEXTURE)(GLenum);
extern PFNGLACTIVETEXTURE glew_ActiveTexture;
#define glActiveTexture glew_ActiveTexture;
In glewInit the function pointer variables are set to the values obtained using wglGetProcAddress (for the sake of readability I omit the type castings).
int glewInit(void)
{
/* ... */
if( openglsupport >= gl1_2 ) {
/* ... */
glew_ActiveTexture = wglGetProcAddress("glActiveTexture");
/* ... */
}
/* ... */
}
Now the important part: wglGetProcAddress works with the OpenGL rendering context that is current at the time of calling. So whatever was to the very last wglMakeCurrent call made before it. As already explained, extension function pointers are tied to their OpenGL context and different OpenGL contexts may give different function pointers for the same function.
So if you do this
wglMakeCurrent(…, rc0);
glewInit();
wglMakeCurrent(…, rc1);
glActiveTexture(…);
it may fail. So in general, with GLEW, every call to wglMakeCurrent must immediately be followed by a glewInit. Some builds of GLEW are multi context aware and do this internally. Others are not. However it is perfectly safe to call glewInit multiple times, so the safe way is to call it, just to be sure.
It should not be necessary to get multiple function ptrs one-per-context according to this... https://github.com/nigels-com/glew/issues/38 in 2016 ....
nigels-com answers this question from kest-relm…
do you think it is correct to call glewInit() for every context change?
Is the above the valid way to go for handling multiple opengl contexts?
…with…
I don't think calling glewInit for each context change is desirable, or even necessary, depending on the circumstances.
Obviously this scheme would not be appropriate for multi-threading, anyway.
Kest-relm then says…
From my testing it seems like calling glewInit() repeatedly is not required; the code runs just fine with multiple contexts
It is documented here:
https://www.opengl.org/wiki/Load_OpenGL_Functions
where it states:
"In practice, if two contexts come from the same vendor and refer to the same GPU, then the function pointers pulled from one context will work in the other."
I assume this should be true for most mainstream Windows GL drivers?
I was working with a project that reads a data file, performs some calculations, and show results on standard output. Later i wanted to give a 3D graphical view to the results, so I made a new OpenGL project that shows data as 3D object.
Now the problem is, I can not figure out a way to integrate these two independent projects, because the main() in my OpenGL project goes in a non terminating glutMainLoop() loop, and I am unable to figure out where to put the loop in main() of my first project !
/**** Proj1 ****/
int main()
{
while(ESC key not pressed)
{
// read data file
// do some processing
// show results on standard output
}
}
/**** Proj2 ****/
int main()
{
glutInit(&argc, argv);
Init();
glutDisplayFunc(Display);
glutKeyboardFunc(Keyboard);
glutMouseFunc(Mouse);
glutIdleFunc(Idle);
glutMainLoop();
}
Least mixing of codes between Proj1 & Proj2 is requested.
Is it possible to do something like:
/**** Proj1 ****/
#include <filesFromProj2>
int main()
{
while(ESC key not pressed)
{
// read data file
// do some processing
proj2.showResult(result) // how to do this ?
}
}
The most simple solution would be to ditch GLUT and use a OpenGL windowing framework that lets you implement the event loop. GLFW would be the immediate choice. Then instead of having an opaque glutMainLoop that never returns you instead call glfwPollEvents beside your your stdio processing.
GLUT decouples your event handling code from your display code. It feels strange if you're used to the paradigm where you have full control over the loop, but it's not really hard to deal with. Basically, you need to maintain a state that your glutDisplayFunc will react to, and update that state in your glutKeyboardFunc. So in pseudocode (it seems like you have the C++ down):
displayFunc:
if state.showProj1
proj1.showResult
else if state.showProj2
proj2.showResult
keyboardFunc
if keyPressed(esc)
state.showProj1 = false
state.showProj2 = true
glutPostRedisplay()
Ok, so that is some pretty naive code there, but it should get the idea of how to make changes to your state in response to user input which in turn affects what you are rendering.
As mentioned in the previous answer, if you want explicit control of the program loop (as opposed to the event-based paradigm), you have some good options in GLFW and SDL, but of course there will be some ramp-up with those since GLUT does things in a pretty different way.
Found a solution so answering it myself for everyone's reference:
I desperately needed a workaround without having to change my existing glut base code into GLFW and SDF etc.
Digging more on internet I found that freeglut supports a function glutMainLoopEvent() that "causes freeglut to process one iteration’s worth of events in its event loop. This allows the application to control its own event loop and still use the freeglut windowing system."
Also, freeglut supported all the functions of glut (or atleast supported all the glut functions used in my prog). So,i didn't have to change my glut base code.
The pseudo-code for the workaround is as below. I welcome your comments.
#include <gl/freeglut.h>
#include <filesFromProj2>
int main()
{
glutInit(&argc, argv);
Init();
glutDisplayFunc(Display);
glutKeyboardFunc(Keyboard);
glutMouseFunc(Mouse);
glutIdleFunc(Idle);
// glutMainLoop(); // Do not use this
while(ESC key not pressed)
{
// read data file
// do some processing
proj2.showresults(results)
glutMainLoopEvent(); // One iteration only
Display(); // Call the func used with glutDisplayFunc()
}
glutLeaveMainLoop();
}
I also thought that multi-threading, may also solve this problem. One thread for glutMainLoop() and another for data processing !!
I'm writing a library that wraps around GLFW, among a few other libraries. I have a class that needs to be aware of user interface events, but GLFW uses a callback system where I have to specify a function that GLFW will automatically call when an event happens. This causes issues, because those functions that I have to supply GLFW have no way of being associated with an object of my class, so far as I can tell. For instance:
class MyClass {
MyClass() {
// Initialize GLFW
glfwSetKeyCallback(window, keyboardEventFunction);
}
// other content
}
void keyboardEventFunction(GLFWwindow *window, int b, int a, int m) {
// I want to notify the MyClass object, but it's out of scope
}
I am aware that GLFW has some non-callback functions to retrieve input data, but if I use those, there's no guarantee that I won't miss something simply because my program didn't happen to check at the exact moment a user provides input. I also lose the ability to check window focus and cursor enter-exit events. How can I get around this issue?
I have created two Ncurses windows: Window 1 and Window 2. I am able to write to Window 1 before Window 2 is called; however, after I call Window 2, I am unable to write to Window 1 using mvwprinw(window1, "Bla"). To illustrate:
...
initscr();
Window* window1 = newwin(10,10,0,0);
mvwprinw(window1, "i am writing to window"); // this works
wrefresh(window1);
Window* window2 = newwin(10,10, 12, 12);
mvwprintw(window2, "whee"); //works too
wrefresh(window2);
mvwprintw(window1, 0,0,"writing new sentence");
// this does not show on the screen
wrefresh(window1);
...
Why is that so?
SOLVED:
If anyone encounters a similar problem, be aware of coding windows within multiple C++ classes.
A listener class was built within one of the classes. However, it called an infinite loop (not an optimal way to design code, but sufficient for the program).
Hence, the code was stuck in the infinite loop, causing the next line of code to remain unexecuted.
SOLUTION: Use multithreading libs if necesary.