这是我的第一个大型OpenGL项目,我对想要实现的一个新功能感到困惑。
我正在开发一个游戏引擎。在我的引擎中,我有两个类:Renderer
和CustomWindow
。GLFW需要初始化,然后需要创建OpenGL上下文,然后可以初始化glew。这是没有问题的,直到我决定支持同时创建多个窗口。以下是我感到困惑的事情:
- 是否需要为创建的每个窗口初始化GLEW?如果没有,我是否仍然可以在每次创建窗口时调用
glewInit()
,并且一切正常 - 如果我创建了一个窗口,然后将其销毁,我是否必须再次调用
glewInit()
?我是否必须重新调用这些函数?:
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numberOfTexturesSupported);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_MULTISAMPLE);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_PROGRAM_POINT_SIZE);
如果有任何偏离主题的评论会有所帮助,我们非常欢迎。
更新1:更多上下文
作为参考,我想这样做的原因是实现共享同一OpenGL上下文的多窗口渲染。请注意,每个窗口都使用自己的顶点阵列对象(VAO(。这是供参考的代码:
// CustomWindow.cpp
CustomWindow::CustomWindow() {
window = nullptr;
title = defaultTitle;
shouldClose = false;
error = false;
vertexArrayObjectID = 0;
frameRate = defaultFrameRate;
window = glfwCreateWindow(defaultWidth, defaultHeight, title.c_str(), nullptr, nullptr);
if (!window) {
error = true;
return;
}
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) {
error = true;
return;
}
glGenVertexArrays(1, &vertexArrayObjectID);
glBindVertexArray(vertexArrayObjectID);
allWindows.push_back(this);
}
CustomWindow::CustomWindow(int width, int height, const std::string& title, GLFWmonitor* monitor, GLFWwindow* share) {
window = nullptr;
this->title = title;
shouldClose = false;
error = false;
vertexArrayObjectID = 0;
frameRate = defaultFrameRate;
window = glfwCreateWindow(width, height, title.c_str(), monitor, share);
if (!window) {
error = true;
return;
}
glfwMakeContextCurrent(window);
glGenVertexArrays(1, &vertexArrayObjectID);
allWindows.push_back(this);
}
CustomWindow::~CustomWindow() {
if (window != nullptr || error)
glfwDestroyWindow(window);
unsigned int position = 0;
for (unsigned int i = 0; i < allWindows.size(); i++)
if (allWindows[i] == this) {
position = i;
break;
}
allWindows.erase(allWindows.begin() + position);
if (mainWindow == this)
mainWindow = nullptr;
}
// Rendere.cpp
Renderer::Renderer() {
error = false;
numberOfTexturesSupported = 0;
if (singleton != nullptr) {
error = true;
return;
}
singleton = this;
// Init GLFW
if (!glfwInit()) {
error = true;
return;
}
// Set window hints
glfwWindowHint(GLFW_MAXIMIZED, true);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
glfwWindowHint(GLFW_SAMPLES, 4);
// Init GLEW
if (glewInit() != GLEW_OK) {
error = true;
return;
}
// Set graphics message reporting
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(openglDebugCallback, nullptr);
// Set up OpenGL
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numberOfTexturesSupported);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_MULTISAMPLE);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_PROGRAM_POINT_SIZE);
}
经过一些研究,我想说这取决于情况,因此最好看看基础来形成意见。
OpenGL wiki提供了一些有用的信息。
加载OpenGL函数是在创建OpenGL上下文后初始化OpenGL的一项重要任务。强烈建议您使用OpenGL加载库,而不是手动过程。然而,如果你想知道它是如何手动工作的,请继续阅读
Windows
此函数仅在存在有效OpenGL上下文的情况下工作。事实上,它返回的函数指针本身就是特定于上下文的。该函数的Windows文档指出,返回的函数可以与另一个上下文一起使用,具体取决于该上下文的供应商和该上下文的像素格式。
在实践中,如果两个上下文来自同一供应商并引用同一GPU,那么从一个上下文提取的函数指针将在另一个上下文中工作。
Linux和X-Windows
这个函数可以在没有OpenGL上下文的情况下运行,尽管它返回的函数显然不能。这意味着函数不会以任何方式与上下文相关联。
如果您查看glew
(./src/glew.c
(的源代码,您会发现lib只是调用底层系统的加载过程,并将这些调用的结果分配给全局函数指针。
换句话说,多次调用glewInit
除了OpenGL wiki中解释的副作用之外,没有其他副作用。
另一个问题是:你真的需要多个窗口来完成这个任务吗?只使用一个上下文和多个帧缓冲区对象可以实现不同的方法。
多个上下文(在它们之间共享资源(和事件处理(只能从"主"线程调用(需要适当的同步和多个上下文切换。