我正在使用GLFW和ImGui用于一个涉及打开多个窗口的项目。到目前为止,我已经设置了它,以便每次必须打开一个新窗口时,我生成一个线程,它创建自己的GLFW窗口和OpenGL上下文。线程函数如下所示:
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
// Check for creation error...
glfwMakeContextCurrent(window);
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); // Is this supposed to be done per-thread?
// Calling specific impl-specific ImGui setup methods for GLFW & OpenGL3...
// Set up OpenGL stuff ...
while (!glfwWindowShouldClose(window))
{
// Some heavy-duty processing happens here...
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// ImGui code is here...
// Rendering some stuff in the window here...
// Render ImGui last...
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
}
// Calling impl-specific ImGui shutdown here...
glfwDestroyWindow(window);我知道GLFW要求您从主线程(称为glfwInit())中轮询事件,所以我的主线程上有一个循环,可以这样做:
while (!appMustExit)
{
glfwWaitEvents();
}
// appMustExit is set from another thread that waits for console input因此,我遇到的问题是,我的ImGui控件不会响应任何类型的输入,如果单击“关闭”按钮,glfwWindowShouldClose()永远不会返回true。似乎输入状态只在调用glfwPollEvents()的线程上可用,这使我相信,在仍然使用单独的线程进行呈现时,不能组合ImGui和GLFW!
如何修复它以允许ImGui &这些窗口响应GLFW事件?
我之前的尝试使用一个线程来遍历每个窗口并更新/呈现它,但是我希望使用线程来帮助应用程序在打开许多窗口的情况下更好地扩展。
更新:I想澄清的是,这个应用程序涉及实时处理复杂的机器视觉,并且ImGui代码部分与控制和响应这个机器视觉代码紧密结合。因此,我希望能够在与此处理相同的线程上调用ImGui函数,这也意味着该线程必须能够响应glfw输入。
发布于 2019-08-12 16:50:57
我找到了一种方法,可以将亲爱的ImGui更改为一个(希望是)线程安全库,并免费使用thead_local说明符。
在imconfig.h中,我必须创建一个新的线程本地ImGuiContext指针:
struct ImGuiContext;
extern thread_local ImGuiContext* threadCTX;
#define GImGui threadCTX在imgui_impl_glfw.cpp中,我必须将所有局部变量/静态变量更改为thread_local版本:
thread_local GLFWwindow* g_Window = NULL; // Per-Thread Main window
thread_local GlfwClientApi g_ClientApi = GlfwClientApi_Unknown;
thread_local double g_Time = 0.0;
thread_local bool g_MouseJustPressed[5] = { false, false, false, false, false };
thread_local GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 };
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
static thread_local GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL;
static thread_local GLFWscrollfun g_PrevUserCallbackScroll = NULL;
static thread_local GLFWkeyfun g_PrevUserCallbackKey = NULL;
static thread_local GLFWcharfun g_PrevUserCallbackChar = NULL;同样,在imgui_impl_opengl3.h中,我对OpenGL对象句柄也做了相同的操作:
static thread_local char g_GlslVersionString[32] = "";
static thread_local GLuint g_FontTexture = 0;
static thread_local GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
static thread_local int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location
static thread_local int g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location
static thread_local unsigned int g_VboHandle = 0, g_ElementsHandle = 0;通过这几个更改,我现在能够创建一个GLFW窗口& OpenGL上下文,初始化亲爱的ImGui,并在每个线程上调用glfwPollEvents,而不会相互影响。基本上,创建GLFW窗口的每个线程都可以像使用“主”线程一样使用。
这个解决方案可能有一些挫折,但对于我的用例来说,它似乎很好,每个窗口在自己的线程中运行自己的事件循环,有自己的OpenGL和ImGui上下文,并且窗口不相互交互或共享资源。
发布于 2019-08-02 20:07:03
为什么首先要创建多个线程?您可以完美地创建多个GLFW窗口和多个亲爱的ImGui上下文,并在同一个线程中管理所有内容。从不同的线程工作只会使所有事情更难处理。
在亲爱的ImGui的具体情况下,您可以使用“停靠”分支中的多视图特性,它本机支持在主视口之外提取任何亲爱的imgui窗口,并为您创建/管理GLFW窗口。所有这些都是由一个可爱的imgui上下文处理的,因此您可以从一个窗口拖放到另一个窗口。
https://stackoverflow.com/questions/57313660
复制相似问题