关闭和打开多个 windows GLFW OpenGL C++
Closing and opening multiple windows GLFW OpenGL C++
我在 GLFW OpenGL
中遇到多个 windows
我有一个名为“Form”的 class,它指向 GLFWwindow 的一个实例。
我可以很好地呈现我的表格。
我可以同时渲染多个 Form 实例。
如果我通过调用 glfwDestroyWindow 关闭窗体的 GLFWwindow 并在我想再次显示窗体时尝试为窗体分配一个新的 GLFWwindow 实例,我的问题就开始了。
目前我可以使用它,但前提是我在创建新的 window 后重新生成所有着色器程序,否则新的 window 只会显示背景色。
如果我在使用 glCreateShader 创建新着色器之前通过调用 glDeleteShader 和 glDeleteProgram 来处理所有旧着色器,那么我只会以黑屏告终,我不明白为什么。但是如果我只是从原始的 const char* 指针重新创建新的着色器,它一切正常,只是我觉得它可能会导致内存泄漏或由于没有正确处理东西而导致的其他问题。
我确定这很简单,我只是没有掌握,我对 OpenGL 和 C++ 不太好,通常我在 Windows csharp 的 OnPaint 事件中编写程序,但我想我的程序 运行 在我的 ubuntu 计算机上,因此 System.Windows.Forms.Form 和 System.Drawing.Graphics class.
的基本实现
我不关心控件和小部件等,我可以在 OnPaint 事件中呈现所有内容。
下面是表格和图形的初始化方法 class,我认为它展示了我目前的处理方式。
如果有帮助,我可以添加更多内容,但如果我包括绘制线条、矩形、纹理、字体等的方法,整个 class 会相当大。
如有任何帮助,我们将不胜感激,请随时告诉我为什么我会做这个完全错误的事情,无论如何它主要只是一个学习曲线。
class Form
{
public: Form()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
//glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
}
public: void Show()
{
if (this->window != NULL)
{
glfwFocusWindow(this->window);
return;
}
this->window = glfwCreateWindow(this->width, this->height, this->title, nullptr, nullptr); // Windowed
//this->window = glfwCreateWindow(800, 600, "OpenGL", glfwGetPrimaryMonitor(), nullptr); // Fullscreen
this->graphics.window = this->window;
// store referance to this form in the new windows userPointer field, and set the windows size limits
glfwSetWindowUserPointer(this->window, &*this);
glfwSetWindowSizeLimits(this->window, this->minWidth, this->minHeight, this->maxWidth, this->maxHeight);
// attach calbacks to the window
glfwSetWindowSizeCallback(this->window, window_size_callback);
glfwSetFramebufferSizeCallback(this->window, framebuffer_size_callback);
glfwSetKeyCallback(this->window, key_callback);
glfwSetMouseButtonCallback(this->window, mouse_callback);
glfwSetWindowFocusCallback(this->window, window_focus_callback);
this->MakeCurrent();
// Now all that's left is calling glewInit() after the creation of your window and OpenGL context.
// The glewExperimental line is necessary to force GLEW to use a modern OpenGL method for checking if a function is available.
glewExperimental = GL_TRUE;
glewInit();
// if i initialize the graphics class here all works fine.
this->graphics.Initialize();
// if this is the first time the form is displayed then call the initialize method
if (this->initialized == false)
{
// if i initialize the graphics class here all the forms that were opend when the program initialy runs work fine.
// but any that open after only display the background color and the shaders dont work
//this->graphics.Initialize();
this->OnInitialize();
this->initialized = true;
}
// invalidate the form and call the resize method to draw the form as it show's
this->OnResize();
this->Invalidate();
}
public: void Close()
{
// here i feel i need to dispose of the shaders as the window is closing but if i do all the forms rendering disapears
//this->graphics.Dispose();
glfwDestroyWindow(this->window);
this->window = nullptr;
}
public: virtual void OnInitialize() { }
public: virtual void Dispose()
{
this->Close();
this->graphics.Dispose();
glfwTerminate();
}
}
class Graphics
{
public: Graphics()
{
}
public: void Initialize()
{
// Create and compile the vertex shader
const char* vertexSource1 = R"glsl(
#version 150 core
in vec2 position;
in vec2 texcoord;
out vec2 Texcoord;
void main()
{
Texcoord = texcoord;
gl_Position = vec4(position, 0.0, 1.0);
}
)glsl";
this->vertexShader1 = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(this->vertexShader1, 1, &vertexSource1, NULL);
glCompileShader(this->vertexShader1);
// Create and compile the fragment shader
const char* fragmentSource1 = R"glsl(
#version 150 core
in vec2 Texcoord;
uniform sampler2D tex;
void main()
{
gl_FragColor = texture(tex, Texcoord);
}
)glsl";
this->fragmentShader1 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(this->fragmentShader1, 1, &fragmentSource1, NULL);
glCompileShader(this->fragmentShader1);
// Create Vertex Array Object
glGenVertexArrays(1, &this->vertexArrayObj1);
glBindVertexArray(this->vertexArrayObj1);
// Create a Vertex Buffer Object
glGenBuffers(1, &this->vertexBufferObj1);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexBufferObj1);
// Create a Element Buffer Object
glGenBuffers(1, &this->elementBufferObj1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->elementBufferObj1);
// Create a Texture Object
glGenTextures(1, &this->tex1);
glBindTexture(GL_TEXTURE_2D, this->tex1);
// Link the vertex and fragment shader into a shader program
this->shaderProgram1 = glCreateProgram();
glAttachShader(this->shaderProgram1, this->vertexShader1);
glAttachShader(this->shaderProgram1, this->fragmentShader1);
//glBindFragDataLocation(this->shaderProgram1, 0, "outColor");
glLinkProgram(shaderProgram1);
//
//
// Create and compile the vertex shader
const char* vertexSource2 = R"glsl(
#version 150 core
in vec2 position;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
}
)glsl";
this->vertexShader2 = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(this->vertexShader2, 1, &vertexSource2, NULL);
glCompileShader(this->vertexShader2);
// Create and compile the fragment shader
const char* fragmentSource2 = R"glsl(
#version 150 core
uniform vec4 color;
void main()
{
gl_FragColor = color;
}
)glsl";
this->fragmentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(this->fragmentShader2, 1, &fragmentSource2, NULL);
glCompileShader(this->fragmentShader2);
// Create Vertex Array Object
glGenVertexArrays(1, &this->vertexArrayObj2);
glBindVertexArray(this->vertexArrayObj2);
// Create a Vertex Buffer Object
glGenBuffers(1, &this->vertexBufferObj2);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexBufferObj2);
// Create a Element Buffer Object
glGenBuffers(1, &this->elementBufferObj2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->elementBufferObj2);
// Link the vertex and fragment shader into a shader program
this->shaderProgram2 = glCreateProgram();
glAttachShader(this->shaderProgram2, this->vertexShader2);
glAttachShader(this->shaderProgram2, this->fragmentShader2);
//glBindFragDataLocation(this->shaderProgram2, 0, "outColor");
glLinkProgram(this->shaderProgram2);
glUseProgram(this->shaderProgram2);
//glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
//
//
// Create and compile the vertex shader
const char* vertexSource3 = R"glsl(
#version 150 core
in vec2 position;
in vec2 texcoord;
out vec2 Texcoord;
void main()
{
Texcoord = texcoord;
gl_Position = vec4(position, 0.0, 1.0);
}
)glsl";
this->vertexShader3 = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(this->vertexShader3, 1, &vertexSource3, NULL);
glCompileShader(this->vertexShader3);
// Create and compile the fragment shader
const char* fragmentSource3 = R"glsl(
#version 150 core
uniform vec4 color;
in vec2 Texcoord;
uniform sampler2D tex;
void main()
{
gl_FragColor = vec4(color.r, color.g, color.b, texture(tex, Texcoord).a);
}
)glsl";
this->fragmentShader3 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(this->fragmentShader3, 1, &fragmentSource3, NULL);
glCompileShader(this->fragmentShader3);
// Create Vertex Array Object
glGenVertexArrays(1, &this->vertexArrayObj3);
glBindVertexArray(this->vertexArrayObj3);
// Create a Vertex Buffer Object
glGenBuffers(1, &this->vertexBufferObj3);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexBufferObj3);
// Create a Element Buffer Object
glGenBuffers(1, &this->elementBufferObj1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->elementBufferObj1);
// Create a Texture Object
glGenTextures(1, &this->tex3);
glBindTexture(GL_TEXTURE_2D, this->tex3);
// Link the vertex and fragment shader into a shader program
this->shaderProgram3 = glCreateProgram();
glAttachShader(this->shaderProgram3, this->vertexShader3);
glAttachShader(this->shaderProgram3, this->fragmentShader3);
//glBindFragDataLocation(this->shaderProgram3, 0, "outColor");
glLinkProgram(shaderProgram3);
this->initialized = true;
}
public: void Dispose()
{
glDeleteProgram(this->shaderProgram1);
glDeleteShader(this->fragmentShader1);
glDeleteShader(this->vertexShader1);
glDeleteVertexArrays(1, &this->vertexArrayObj1);
glDeleteBuffers(1, &this->vertexBufferObj1);
glDeleteBuffers(1, &this->elementBufferObj1);
glDeleteBuffers(1, &this->tex1);
glDeleteProgram(this->shaderProgram2);
glDeleteShader(this->fragmentShader2);
glDeleteShader(this->vertexShader2);
glDeleteVertexArrays(1, &this->vertexArrayObj2);
glDeleteBuffers(1, &this->vertexBufferObj2);
glDeleteBuffers(1, &this->elementBufferObj2);
glDeleteProgram(this->shaderProgram3);
glDeleteShader(this->fragmentShader3);
glDeleteShader(this->vertexShader3);
glDeleteVertexArrays(1, &this->vertexArrayObj3);
glDeleteBuffers(1, &this->vertexBufferObj3);
glDeleteBuffers(1, &this->elementBufferObj3);
glDeleteBuffers(1, &this->tex3);
this->window = NULL;
this->initialized = false;
}
}
您要确保保留原始形式 window,这样它的 opengl 资源就不会被释放(这会导致您当前的问题)。
GLFWwindow * orig_window = glfwCreateWindow(800, 600, "The original window", NULL, NULL);
//init shaders etc. that you want to share between windows...
//for all windows created later, pass the original window as a shared context
GLFWwindow * shared_window = glfwCreateWindow(800, 600, "A shared window", NULL, orig_window);
有关详细信息,请在此处查看 GLFW 参考资料:https://www.glfw.org/docs/3.3/group__window.html#ga5c336fddf2cbb5b92f65f10fb6043344
我在 GLFW OpenGL
中遇到多个 windows我有一个名为“Form”的 class,它指向 GLFWwindow 的一个实例。 我可以很好地呈现我的表格。 我可以同时渲染多个 Form 实例。
如果我通过调用 glfwDestroyWindow 关闭窗体的 GLFWwindow 并在我想再次显示窗体时尝试为窗体分配一个新的 GLFWwindow 实例,我的问题就开始了。
目前我可以使用它,但前提是我在创建新的 window 后重新生成所有着色器程序,否则新的 window 只会显示背景色。
如果我在使用 glCreateShader 创建新着色器之前通过调用 glDeleteShader 和 glDeleteProgram 来处理所有旧着色器,那么我只会以黑屏告终,我不明白为什么。但是如果我只是从原始的 const char* 指针重新创建新的着色器,它一切正常,只是我觉得它可能会导致内存泄漏或由于没有正确处理东西而导致的其他问题。
我确定这很简单,我只是没有掌握,我对 OpenGL 和 C++ 不太好,通常我在 Windows csharp 的 OnPaint 事件中编写程序,但我想我的程序 运行 在我的 ubuntu 计算机上,因此 System.Windows.Forms.Form 和 System.Drawing.Graphics class.
的基本实现我不关心控件和小部件等,我可以在 OnPaint 事件中呈现所有内容。
下面是表格和图形的初始化方法 class,我认为它展示了我目前的处理方式。
如果有帮助,我可以添加更多内容,但如果我包括绘制线条、矩形、纹理、字体等的方法,整个 class 会相当大。
如有任何帮助,我们将不胜感激,请随时告诉我为什么我会做这个完全错误的事情,无论如何它主要只是一个学习曲线。
class Form
{
public: Form()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
//glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
}
public: void Show()
{
if (this->window != NULL)
{
glfwFocusWindow(this->window);
return;
}
this->window = glfwCreateWindow(this->width, this->height, this->title, nullptr, nullptr); // Windowed
//this->window = glfwCreateWindow(800, 600, "OpenGL", glfwGetPrimaryMonitor(), nullptr); // Fullscreen
this->graphics.window = this->window;
// store referance to this form in the new windows userPointer field, and set the windows size limits
glfwSetWindowUserPointer(this->window, &*this);
glfwSetWindowSizeLimits(this->window, this->minWidth, this->minHeight, this->maxWidth, this->maxHeight);
// attach calbacks to the window
glfwSetWindowSizeCallback(this->window, window_size_callback);
glfwSetFramebufferSizeCallback(this->window, framebuffer_size_callback);
glfwSetKeyCallback(this->window, key_callback);
glfwSetMouseButtonCallback(this->window, mouse_callback);
glfwSetWindowFocusCallback(this->window, window_focus_callback);
this->MakeCurrent();
// Now all that's left is calling glewInit() after the creation of your window and OpenGL context.
// The glewExperimental line is necessary to force GLEW to use a modern OpenGL method for checking if a function is available.
glewExperimental = GL_TRUE;
glewInit();
// if i initialize the graphics class here all works fine.
this->graphics.Initialize();
// if this is the first time the form is displayed then call the initialize method
if (this->initialized == false)
{
// if i initialize the graphics class here all the forms that were opend when the program initialy runs work fine.
// but any that open after only display the background color and the shaders dont work
//this->graphics.Initialize();
this->OnInitialize();
this->initialized = true;
}
// invalidate the form and call the resize method to draw the form as it show's
this->OnResize();
this->Invalidate();
}
public: void Close()
{
// here i feel i need to dispose of the shaders as the window is closing but if i do all the forms rendering disapears
//this->graphics.Dispose();
glfwDestroyWindow(this->window);
this->window = nullptr;
}
public: virtual void OnInitialize() { }
public: virtual void Dispose()
{
this->Close();
this->graphics.Dispose();
glfwTerminate();
}
}
class Graphics
{
public: Graphics()
{
}
public: void Initialize()
{
// Create and compile the vertex shader
const char* vertexSource1 = R"glsl(
#version 150 core
in vec2 position;
in vec2 texcoord;
out vec2 Texcoord;
void main()
{
Texcoord = texcoord;
gl_Position = vec4(position, 0.0, 1.0);
}
)glsl";
this->vertexShader1 = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(this->vertexShader1, 1, &vertexSource1, NULL);
glCompileShader(this->vertexShader1);
// Create and compile the fragment shader
const char* fragmentSource1 = R"glsl(
#version 150 core
in vec2 Texcoord;
uniform sampler2D tex;
void main()
{
gl_FragColor = texture(tex, Texcoord);
}
)glsl";
this->fragmentShader1 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(this->fragmentShader1, 1, &fragmentSource1, NULL);
glCompileShader(this->fragmentShader1);
// Create Vertex Array Object
glGenVertexArrays(1, &this->vertexArrayObj1);
glBindVertexArray(this->vertexArrayObj1);
// Create a Vertex Buffer Object
glGenBuffers(1, &this->vertexBufferObj1);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexBufferObj1);
// Create a Element Buffer Object
glGenBuffers(1, &this->elementBufferObj1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->elementBufferObj1);
// Create a Texture Object
glGenTextures(1, &this->tex1);
glBindTexture(GL_TEXTURE_2D, this->tex1);
// Link the vertex and fragment shader into a shader program
this->shaderProgram1 = glCreateProgram();
glAttachShader(this->shaderProgram1, this->vertexShader1);
glAttachShader(this->shaderProgram1, this->fragmentShader1);
//glBindFragDataLocation(this->shaderProgram1, 0, "outColor");
glLinkProgram(shaderProgram1);
//
//
// Create and compile the vertex shader
const char* vertexSource2 = R"glsl(
#version 150 core
in vec2 position;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
}
)glsl";
this->vertexShader2 = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(this->vertexShader2, 1, &vertexSource2, NULL);
glCompileShader(this->vertexShader2);
// Create and compile the fragment shader
const char* fragmentSource2 = R"glsl(
#version 150 core
uniform vec4 color;
void main()
{
gl_FragColor = color;
}
)glsl";
this->fragmentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(this->fragmentShader2, 1, &fragmentSource2, NULL);
glCompileShader(this->fragmentShader2);
// Create Vertex Array Object
glGenVertexArrays(1, &this->vertexArrayObj2);
glBindVertexArray(this->vertexArrayObj2);
// Create a Vertex Buffer Object
glGenBuffers(1, &this->vertexBufferObj2);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexBufferObj2);
// Create a Element Buffer Object
glGenBuffers(1, &this->elementBufferObj2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->elementBufferObj2);
// Link the vertex and fragment shader into a shader program
this->shaderProgram2 = glCreateProgram();
glAttachShader(this->shaderProgram2, this->vertexShader2);
glAttachShader(this->shaderProgram2, this->fragmentShader2);
//glBindFragDataLocation(this->shaderProgram2, 0, "outColor");
glLinkProgram(this->shaderProgram2);
glUseProgram(this->shaderProgram2);
//glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
//
//
// Create and compile the vertex shader
const char* vertexSource3 = R"glsl(
#version 150 core
in vec2 position;
in vec2 texcoord;
out vec2 Texcoord;
void main()
{
Texcoord = texcoord;
gl_Position = vec4(position, 0.0, 1.0);
}
)glsl";
this->vertexShader3 = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(this->vertexShader3, 1, &vertexSource3, NULL);
glCompileShader(this->vertexShader3);
// Create and compile the fragment shader
const char* fragmentSource3 = R"glsl(
#version 150 core
uniform vec4 color;
in vec2 Texcoord;
uniform sampler2D tex;
void main()
{
gl_FragColor = vec4(color.r, color.g, color.b, texture(tex, Texcoord).a);
}
)glsl";
this->fragmentShader3 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(this->fragmentShader3, 1, &fragmentSource3, NULL);
glCompileShader(this->fragmentShader3);
// Create Vertex Array Object
glGenVertexArrays(1, &this->vertexArrayObj3);
glBindVertexArray(this->vertexArrayObj3);
// Create a Vertex Buffer Object
glGenBuffers(1, &this->vertexBufferObj3);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexBufferObj3);
// Create a Element Buffer Object
glGenBuffers(1, &this->elementBufferObj1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->elementBufferObj1);
// Create a Texture Object
glGenTextures(1, &this->tex3);
glBindTexture(GL_TEXTURE_2D, this->tex3);
// Link the vertex and fragment shader into a shader program
this->shaderProgram3 = glCreateProgram();
glAttachShader(this->shaderProgram3, this->vertexShader3);
glAttachShader(this->shaderProgram3, this->fragmentShader3);
//glBindFragDataLocation(this->shaderProgram3, 0, "outColor");
glLinkProgram(shaderProgram3);
this->initialized = true;
}
public: void Dispose()
{
glDeleteProgram(this->shaderProgram1);
glDeleteShader(this->fragmentShader1);
glDeleteShader(this->vertexShader1);
glDeleteVertexArrays(1, &this->vertexArrayObj1);
glDeleteBuffers(1, &this->vertexBufferObj1);
glDeleteBuffers(1, &this->elementBufferObj1);
glDeleteBuffers(1, &this->tex1);
glDeleteProgram(this->shaderProgram2);
glDeleteShader(this->fragmentShader2);
glDeleteShader(this->vertexShader2);
glDeleteVertexArrays(1, &this->vertexArrayObj2);
glDeleteBuffers(1, &this->vertexBufferObj2);
glDeleteBuffers(1, &this->elementBufferObj2);
glDeleteProgram(this->shaderProgram3);
glDeleteShader(this->fragmentShader3);
glDeleteShader(this->vertexShader3);
glDeleteVertexArrays(1, &this->vertexArrayObj3);
glDeleteBuffers(1, &this->vertexBufferObj3);
glDeleteBuffers(1, &this->elementBufferObj3);
glDeleteBuffers(1, &this->tex3);
this->window = NULL;
this->initialized = false;
}
}
您要确保保留原始形式 window,这样它的 opengl 资源就不会被释放(这会导致您当前的问题)。
GLFWwindow * orig_window = glfwCreateWindow(800, 600, "The original window", NULL, NULL);
//init shaders etc. that you want to share between windows...
//for all windows created later, pass the original window as a shared context
GLFWwindow * shared_window = glfwCreateWindow(800, 600, "A shared window", NULL, orig_window);
有关详细信息,请在此处查看 GLFW 参考资料:https://www.glfw.org/docs/3.3/group__window.html#ga5c336fddf2cbb5b92f65f10fb6043344