c++ GLFW类多窗口

stszievb  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(270)

我是OpenGL的新手,目前我正在为OpenGL学习做我的测试OpenGL项目。而这个项目的一个组件是WindowManager。我已经尝试添加多个窗口创建支持,但它不工作的方式,我想要的。
当我启动我的应用程序时,两个窗口(让我们称之为A-FIRST_WINDOW,B-SECOND_WINDOW)同时被创建,但当我关闭B窗口时,我的应用程序仍然工作,这很好,因为A窗口仍然可用,我可以使用它,当我关闭A窗口时,我的应用程序被关闭。但是如果我先关闭A窗口,我的B窗口也会关闭,应用程序也会完成。
注:A窗口-第一个创建B窗口-第二个创建
密码...
WindowManager.hpp

  1. #include <GLFW/glfw3.h>
  2. #define DEFAULT_WIDTH 800
  3. #define DEFAULT_HEIGHT 600
  4. #define DEFAULT_TITLE "Soul Byte Engine Window"
  5. namespace SoulByteEngineCore
  6. {
  7. namespace WindowManager
  8. {
  9. class Window
  10. {
  11. public:
  12. Window(unsigned int width=DEFAULT_WIDTH, unsigned int height=DEFAULT_HEIGHT, const char *title = DEFAULT_TITLE);
  13. public:
  14. void Clear(float x_pos, float y_pos, float z_pos);
  15. public:
  16. unsigned int GetWidth();
  17. unsigned int GetHeight();
  18. public:
  19. static bool Init();
  20. public:
  21. void ShowWindowData();
  22. public:
  23. const char* GetTitle();
  24. public:
  25. bool SetLogging();
  26. public:
  27. void onUpdate();
  28. public:
  29. bool ShouldClose();
  30. public:
  31. void Destroy();
  32. private:
  33. bool CreateWindow();
  34. private:
  35. void Update();
  36. private:
  37. unsigned int m_windowWidth = DEFAULT_WIDTH;
  38. unsigned int m_windowHeight = DEFAULT_HEIGHT;
  39. private:
  40. const char* m_windowTitle = DEFAULT_TITLE;
  41. private:
  42. unsigned int OpenGLMajorVersion = 3;
  43. unsigned int OpenGLMinorVersion = 3;
  44. private:
  45. GLFWwindow* m_window_handle = NULL;
  46. };
  47. }
  48. }
  1. #include <glad/gl.h>
  2. #include <WindowManager/WindowManager.hpp>
  3. #include <utility>
  4. #include <iostream>
  5. namespace SoulByteEngineCore
  6. {
  7. namespace WindowManager
  8. {
  9. Window::Window(unsigned int width, unsigned int height, const char *title)
  10. :m_windowWidth{std :: move(width)}
  11. ,m_windowHeight{std :: move(height)}
  12. ,m_windowTitle{std :: move(title)}
  13. {
  14. CreateWindow();
  15. }
  16. void Window::Update()
  17. {
  18. glfwSwapBuffers(this->m_window_handle);
  19. glfwPollEvents();
  20. }
  21. void Window::onUpdate()
  22. {
  23. Update();
  24. }
  25. void Window::Destroy()
  26. {
  27. glfwDestroyWindow(this->m_window_handle);
  28. }
  29. bool Window::ShouldClose()
  30. {
  31. return glfwWindowShouldClose(this->m_window_handle);
  32. }
  33. bool Window::Init()
  34. {
  35. if (!glfwInit())
  36. {
  37. std::cout << "SoulByteEngine :: CORE :: WINDOW_MANAGER :: ERROR :: CRITICAL :: GLFW CANNOT BE INITIALIZED! " << std::endl;
  38. return false;
  39. }
  40. }
  41. bool Window::CreateWindow()
  42. {
  43. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  44. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  45. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  46. m_window_handle = glfwCreateWindow(m_windowWidth, m_windowHeight, m_windowTitle, NULL, NULL);
  47. if (!m_window_handle)
  48. {
  49. std::cout << "SoulByteEngine :: CORE :: WindowManagerModule :: ERROR :: COULD'T CREATE WINDOW" << std::endl;
  50. return false;
  51. }
  52. glfwMakeContextCurrent(this->m_window_handle);
  53. if (!gladLoadGL(glfwGetProcAddress))
  54. {
  55. std::cout << "SoulByteEngine :: CORE :: WINDOW_MANAGER :: ERROR :: CRITICAL :: WINDOW HAS BEEN CREATED, BUT GLAD COULD NOT BE INITIALIZED! " << std::endl;
  56. return false;
  57. }
  58. return true;
  59. }
  60. bool Window::SetLogging()
  61. {
  62. return false;
  63. }
  64. unsigned int Window::GetWidth()
  65. {
  66. return this->m_windowWidth;
  67. }
  68. unsigned int Window::GetHeight()
  69. {
  70. return this->m_windowHeight;
  71. }
  72. const char* Window::GetTitle()
  73. {
  74. return this->m_windowTitle;
  75. }
  76. void Window::ShowWindowData()
  77. {
  78. std::cout << "Window Data:" << std::endl;
  79. std::cout << "Title: " << this->GetTitle() << std::endl;
  80. std::cout << "Width: " << this->GetWidth() << std::endl;
  81. std::cout << "Height: " << this->GetHeight() << std::endl;
  82. }
  83. void Window::Clear(float x_pos, float y_pos, float z_pos)
  84. {
  85. glClearColor(x_pos, y_pos, z_pos, 1.0f);
  86. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  87. }
  88. }
  89. }

Application.cpp

  1. #include <WindowManager/WindowManager.hpp>
  2. int main()
  3. {
  4. if (SoulByteEngineCore::WindowManager::Window::Init())
  5. {
  6. SoulByteEngineCore::WindowManager::Window first_window(DEFAULT_WIDTH, DEFAULT_HEIGHT, "First Fuckin SoulByteEngine Window");
  7. SoulByteEngineCore::WindowManager::Window second_window(DEFAULT_WIDTH, DEFAULT_HEIGHT, "Second Fuckin SoulByteEngine Window");
  8. while (!first_window.ShouldClose() || !second_window.ShouldClose())
  9. {
  10. if (first_window.ShouldClose() == true)
  11. {
  12. first_window.Destroy();
  13. }
  14. else
  15. {
  16. //first_window.Clear(0.0f, 1.0f, 0.0f);
  17. first_window.onUpdate();
  18. }
  19. if (second_window.ShouldClose() == true)
  20. {
  21. second_window.Destroy();
  22. }
  23. else
  24. {
  25. //second_window.Clear(0.0f, 1.0f, 0.0f);
  26. second_window.onUpdate();
  27. }
  28. }
  29. }
  30. }
yzuktlbb

yzuktlbb1#

此答案基于用户@BDL的评论(架构问题)。
由于不能从回调调用glfwDestroyWindow(只能从主线程调用),所以必须采取不同的方法。
为此,我们需要两个列表(向量),一个是打开的(活动)窗口,另一个是关闭的(应该关闭标志集)窗口,例如:

  1. std::vector<GLFWwindow*> opened_windows;
  2. std::vector<GLFWwindow*> closing_windows;

两者最初都是空的,并且如果窗口被成功创建或被标记为被销毁,则被填充。
打开时(每当创建窗口时):

  1. GLFWwindow *win = createWindow();
  2. if (win) {
  3. opened_windows.push_back(win);
  4. }

对于关闭案例,我们必须建立一个关闭处理程序:

  1. void window_close_callback(GLFWwindow* win)
  2. {
  3. //remove window from the opened list
  4. opened_windows.erase(std::find(..., win));
  5. //add to garbage list
  6. closing_windows.push_back(win);
  7. }

然后在你的主循环中:

  1. while (!opened_windows.empty()) {
  2. //1. do your stuff
  3. //2. process events (which might catch a close event)
  4. //3. destroy all windows in the garbage
  5. if (!closing_windows.empty()) {
  6. //foreach element in list, invoke glfwDestroyWindow
  7. closing_windows.clear();
  8. }
  9. }
展开查看全部
um6iljoc

um6iljoc2#

感谢所有回答我问题的人!特别感谢@BDL!我知道我的架构真的很糟糕,因为我没有检查我的窗口是否关闭,我的Destroy()方法正在关闭窗口,不管我的窗口是否已经关闭,因为你知道没有任何操作可以对已经关闭的窗口执行,并且对已经关闭的窗口采取的任何操作都会导致glfw崩溃。
所以,我已经修正了:
WindowManager.hpp:

  1. #include <GLFW/glfw3.h>
  2. #define DEFAULT_WIDTH 800
  3. #define DEFAULT_HEIGHT 600
  4. #define DEFAULT_TITLE "Soul Byte Engine Window"
  5. namespace SoulByteEngineCore
  6. {
  7. namespace WindowManager
  8. {
  9. class Window
  10. {
  11. public:
  12. Window(unsigned int width=DEFAULT_WIDTH, unsigned int height=DEFAULT_HEIGHT, const char *title = DEFAULT_TITLE);
  13. public:
  14. void Clear(float x_pos, float y_pos, float z_pos);
  15. public:
  16. unsigned int GetWidth();
  17. unsigned int GetHeight();
  18. public:
  19. bool IsClosed();
  20. public:
  21. static bool Init();
  22. public:
  23. void ShowWindowData();
  24. public:
  25. const char* GetTitle();
  26. public:
  27. bool SetLogging();
  28. public:
  29. void onUpdate();
  30. public:
  31. bool ShouldClose();
  32. public:
  33. void Destroy();
  34. private:
  35. bool CreateWindow();
  36. private:
  37. void Update();
  38. private:
  39. unsigned int m_windowWidth = DEFAULT_WIDTH;
  40. unsigned int m_windowHeight = DEFAULT_HEIGHT;
  41. private:
  42. const char* m_windowTitle = DEFAULT_TITLE;
  43. private:
  44. bool m_isClosed = false;
  45. private:
  46. unsigned int OpenGLMajorVersion = 3;
  47. unsigned int OpenGLMinorVersion = 3;
  48. private:
  49. GLFWwindow* m_window_handle = NULL;
  50. };
  51. }
  52. }

WindowManager.cpp:

  1. #include <glad/gl.h>
  2. #include <WindowManager/WindowManager.hpp>
  3. #include <utility>
  4. #include <iostream>
  5. namespace SoulByteEngineCore
  6. {
  7. namespace WindowManager
  8. {
  9. Window::Window(unsigned int width, unsigned int height, const char *title)
  10. :m_windowWidth{std :: move(width)}
  11. ,m_windowHeight{std :: move(height)}
  12. ,m_windowTitle{std :: move(title)}
  13. {
  14. CreateWindow();
  15. }
  16. void Window::Update()
  17. {
  18. glfwSwapBuffers(this->m_window_handle);
  19. glfwPollEvents();
  20. }
  21. void Window::onUpdate()
  22. {
  23. Update();
  24. }
  25. void Window::Destroy()
  26. {
  27. if (!m_isClosed)
  28. {
  29. m_isClosed = true;
  30. glfwDestroyWindow(this->m_window_handle);
  31. }
  32. }
  33. bool Window::ShouldClose()
  34. {
  35. return glfwWindowShouldClose(this->m_window_handle);
  36. }
  37. bool Window::Init()
  38. {
  39. if (!glfwInit())
  40. {
  41. std::cout << "SoulByteEngine :: CORE :: WINDOW_MANAGER :: ERROR :: CRITICAL :: GLFW CANNOT BE INITIALIZED! " << std::endl;
  42. return false;
  43. }
  44. }
  45. bool Window::CreateWindow()
  46. {
  47. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  48. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  49. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  50. m_window_handle = glfwCreateWindow(m_windowWidth, m_windowHeight, m_windowTitle, NULL, NULL);
  51. if (!m_window_handle)
  52. {
  53. std::cout << "SoulByteEngine :: CORE :: WindowManagerModule :: ERROR :: COULD'T CREATE WINDOW" << std::endl;
  54. return false;
  55. }
  56. glfwMakeContextCurrent(this->m_window_handle);
  57. if (!gladLoadGL(glfwGetProcAddress))
  58. {
  59. std::cout << "SoulByteEngine :: CORE :: WINDOW_MANAGER :: ERROR :: CRITICAL :: WINDOW HAS BEEN CREATED, BUT GLAD COULD NOT BE INITIALIZED! " << std::endl;
  60. return false;
  61. }
  62. return true;
  63. }
  64. bool Window::SetLogging()
  65. {
  66. return false;
  67. }
  68. bool Window :: IsClosed()
  69. {
  70. return this->m_isClosed;
  71. }
  72. unsigned int Window::GetWidth()
  73. {
  74. return this->m_windowWidth;
  75. }
  76. unsigned int Window::GetHeight()
  77. {
  78. return this->m_windowHeight;
  79. }
  80. const char* Window::GetTitle()
  81. {
  82. return this->m_windowTitle;
  83. }
  84. void Window::ShowWindowData()
  85. {
  86. std::cout << "Window Data:" << std::endl;
  87. std::cout << "Title: " << this->GetTitle() << std::endl;
  88. std::cout << "Width: " << this->GetWidth() << std::endl;
  89. std::cout << "Height: " << this->GetHeight() << std::endl;
  90. }
  91. void Window::Clear(float x_pos, float y_pos, float z_pos)
  92. {
  93. glClearColor(x_pos, y_pos, z_pos, 1.0f);
  94. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  95. }
  96. }
  97. }

Application.cpp:

  1. #include <WindowManager/WindowManager.hpp>
  2. int main()
  3. {
  4. if (SoulByteEngineCore::WindowManager::Window::Init())
  5. {
  6. SoulByteEngineCore::WindowManager::Window first_window(DEFAULT_WIDTH, DEFAULT_HEIGHT, "First Fuckin SoulByteEngine Window");
  7. SoulByteEngineCore::WindowManager::Window second_window(DEFAULT_WIDTH, DEFAULT_HEIGHT, "Second Fuckin SoulByteEngine Window");
  8. while (!first_window.IsClosed() || !second_window.IsClosed())
  9. {
  10. if (first_window.ShouldClose())
  11. {
  12. first_window.Destroy();
  13. }
  14. else
  15. {
  16. first_window.onUpdate();
  17. }
  18. if (second_window.ShouldClose())
  19. {
  20. second_window.Destroy();
  21. }
  22. else
  23. {
  24. second_window.onUpdate();
  25. }
  26. }
  27. }
  28. }
展开查看全部

相关问题