我正在尝试在Windows上制作OpenGL程序。由于主exe文件越来越大,我决定将其拆分为DLL。这就是我的问题的开始。
对于ImGui函数,我创建了一个类。这是我的类的render()函数:
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();
在我的类中调用render()函数之前,我在我的类中使用另一个函数启动ImGui:
if (!imgui_init(glfw_window)) {
return false;
}
这是我的主要glfw循环:
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
glfwPollEvents();
MyMyGuiClass.render(); //here i ask my class to render imgui
glfwSwapBuffers(window);
}
使用此代码,我可以使ImGui清除窗口颜色(glClearColor函数工作,我的控制台打印“渲染”)
但它没有显示任何其他内容。
顺便说一句,这个命令在我运行时运行得很好。
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);
}
我正在使用VS2017,编译时我的编译器没有显示任何警告或错误。我也尝试让我的班级功能保持静止,但我什么都没有。
那么简单,ImGui是否无法在从类内部调用时进行渲染?
答案 0 :(得分:1)
你遇到的问题是ImGui维持一个全局状态,并且这个状态必须保存在某个地方。 ImGui将其保存在 module-local 全局符号中。
注意这里的“模块本地”!这意味着每个DLL(和主EXE)都获得它自己的状态副本。因此,在DLL“A”(或EXE“1”)中使用ImGui进行操作将在其自己的ImGui状态实例上运行。
通过在DLL之间共享令人讨厌的ImGui全局状态,有一个解决方案。 如何在DLL之间共享数据在MSDN中描述https://msdn.microsoft.com/en-us/library/h90dkhs0(v=vs.90).aspx - 关于ImGui本身的详细信息。它主要归结为正在使用的ImGuiContext。目前这是一个模块本地的全局变量,但是ImGui开发人员计划最终调用它并最终用户管理。
来自ImGui代码的评论:
// 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