我是OpenGL的新手,目前我正在为OpenGL学习做我的测试OpenGL项目。而这个项目的一个组件是WindowManager。我已经尝试添加多个窗口创建支持,但它不工作的方式,我想要的。
当我启动我的应用程序时,两个窗口(让我们称之为A-FIRST_WINDOW,B-SECOND_WINDOW)同时被创建,但当我关闭B窗口时,我的应用程序仍然工作,这很好,因为A窗口仍然可用,我可以使用它,当我关闭A窗口时,我的应用程序被关闭。但是如果我先关闭A窗口,我的B窗口也会关闭,应用程序也会完成。
注:A窗口-第一个创建B窗口-第二个创建
密码...
WindowManager.hpp
#include <GLFW/glfw3.h>
#define DEFAULT_WIDTH 800
#define DEFAULT_HEIGHT 600
#define DEFAULT_TITLE "Soul Byte Engine Window"
namespace SoulByteEngineCore
{
namespace WindowManager
{
class Window
{
public:
Window(unsigned int width=DEFAULT_WIDTH, unsigned int height=DEFAULT_HEIGHT, const char *title = DEFAULT_TITLE);
public:
void Clear(float x_pos, float y_pos, float z_pos);
public:
unsigned int GetWidth();
unsigned int GetHeight();
public:
static bool Init();
public:
void ShowWindowData();
public:
const char* GetTitle();
public:
bool SetLogging();
public:
void onUpdate();
public:
bool ShouldClose();
public:
void Destroy();
private:
bool CreateWindow();
private:
void Update();
private:
unsigned int m_windowWidth = DEFAULT_WIDTH;
unsigned int m_windowHeight = DEFAULT_HEIGHT;
private:
const char* m_windowTitle = DEFAULT_TITLE;
private:
unsigned int OpenGLMajorVersion = 3;
unsigned int OpenGLMinorVersion = 3;
private:
GLFWwindow* m_window_handle = NULL;
};
}
}
#include <glad/gl.h>
#include <WindowManager/WindowManager.hpp>
#include <utility>
#include <iostream>
namespace SoulByteEngineCore
{
namespace WindowManager
{
Window::Window(unsigned int width, unsigned int height, const char *title)
:m_windowWidth{std :: move(width)}
,m_windowHeight{std :: move(height)}
,m_windowTitle{std :: move(title)}
{
CreateWindow();
}
void Window::Update()
{
glfwSwapBuffers(this->m_window_handle);
glfwPollEvents();
}
void Window::onUpdate()
{
Update();
}
void Window::Destroy()
{
glfwDestroyWindow(this->m_window_handle);
}
bool Window::ShouldClose()
{
return glfwWindowShouldClose(this->m_window_handle);
}
bool Window::Init()
{
if (!glfwInit())
{
std::cout << "SoulByteEngine :: CORE :: WINDOW_MANAGER :: ERROR :: CRITICAL :: GLFW CANNOT BE INITIALIZED! " << std::endl;
return false;
}
}
bool Window::CreateWindow()
{
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
m_window_handle = glfwCreateWindow(m_windowWidth, m_windowHeight, m_windowTitle, NULL, NULL);
if (!m_window_handle)
{
std::cout << "SoulByteEngine :: CORE :: WindowManagerModule :: ERROR :: COULD'T CREATE WINDOW" << std::endl;
return false;
}
glfwMakeContextCurrent(this->m_window_handle);
if (!gladLoadGL(glfwGetProcAddress))
{
std::cout << "SoulByteEngine :: CORE :: WINDOW_MANAGER :: ERROR :: CRITICAL :: WINDOW HAS BEEN CREATED, BUT GLAD COULD NOT BE INITIALIZED! " << std::endl;
return false;
}
return true;
}
bool Window::SetLogging()
{
return false;
}
unsigned int Window::GetWidth()
{
return this->m_windowWidth;
}
unsigned int Window::GetHeight()
{
return this->m_windowHeight;
}
const char* Window::GetTitle()
{
return this->m_windowTitle;
}
void Window::ShowWindowData()
{
std::cout << "Window Data:" << std::endl;
std::cout << "Title: " << this->GetTitle() << std::endl;
std::cout << "Width: " << this->GetWidth() << std::endl;
std::cout << "Height: " << this->GetHeight() << std::endl;
}
void Window::Clear(float x_pos, float y_pos, float z_pos)
{
glClearColor(x_pos, y_pos, z_pos, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
}
}
Application.cpp
#include <WindowManager/WindowManager.hpp>
int main()
{
if (SoulByteEngineCore::WindowManager::Window::Init())
{
SoulByteEngineCore::WindowManager::Window first_window(DEFAULT_WIDTH, DEFAULT_HEIGHT, "First Fuckin SoulByteEngine Window");
SoulByteEngineCore::WindowManager::Window second_window(DEFAULT_WIDTH, DEFAULT_HEIGHT, "Second Fuckin SoulByteEngine Window");
while (!first_window.ShouldClose() || !second_window.ShouldClose())
{
if (first_window.ShouldClose() == true)
{
first_window.Destroy();
}
else
{
//first_window.Clear(0.0f, 1.0f, 0.0f);
first_window.onUpdate();
}
if (second_window.ShouldClose() == true)
{
second_window.Destroy();
}
else
{
//second_window.Clear(0.0f, 1.0f, 0.0f);
second_window.onUpdate();
}
}
}
}
2条答案
按热度按时间yzuktlbb1#
此答案基于用户@BDL的评论(架构问题)。
由于不能从回调调用
glfwDestroyWindow
(只能从主线程调用),所以必须采取不同的方法。为此,我们需要两个列表(向量),一个是打开的(活动)窗口,另一个是关闭的(应该关闭标志集)窗口,例如:
两者最初都是空的,并且如果窗口被成功创建或被标记为被销毁,则被填充。
打开时(每当创建窗口时):
对于关闭案例,我们必须建立一个关闭处理程序:
然后在你的主循环中:
um6iljoc2#
感谢所有回答我问题的人!特别感谢@BDL!我知道我的架构真的很糟糕,因为我没有检查我的窗口是否关闭,我的Destroy()方法正在关闭窗口,不管我的窗口是否已经关闭,因为你知道没有任何操作可以对已经关闭的窗口执行,并且对已经关闭的窗口采取的任何操作都会导致glfw崩溃。
所以,我已经修正了:
WindowManager.hpp:
WindowManager.cpp:
Application.cpp: