这是我的第一个大型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);
}
1条答案
按热度按时间hrysbysz1#
经过一些研究,我会说这要视情况而定,因此最好是先看看基础,然后再形成看法。
OpenGL wiki提供了一些有用的信息。
加载OpenGL函数是创建OpenGL上下文后初始化OpenGL的重要任务。强烈建议您使用OpenGL加载库,而不是手动流程。然而,如果您想知道它是如何手动工作的,请继续阅读。
Windows
此函数仅在存在有效的OpenGL上下文时才起作用。事实上,它返回的函数指针本身是特定于上下文的。此函数的Windows文档指出,返回的函数可能适用于另一个上下文,具体取决于该上下文的供应商和该上下文的像素格式。
在实践中,如果两个上下文来自相同的供应商并引用相同的GPU,则从一个上下文提取的函数指针将在另一个上下文中工作。
Linux和X-Windows
这个函数可以在没有OpenGL上下文的情况下运行,但它返回的函数显然不能。这意味着函数与上下文没有任何关联。
如果查看
glew
(./src/glew.c
)的源代码,您会发现lib只是调用底层系统的加载过程,并将这些调用的结果赋给全局函数指针。换句话说,多次调用
glewInit
除了OpenGL wiki中解释的副作用外,没有其他副作用。另一个问题是:您真的需要为该任务使用多个窗口吗?仅使用一个上下文和多个帧缓冲区对象就可以实现不同的方法。
多个上下文(它们之间共享资源)和事件处理(只能从‘main’线程调用)需要正确的同步和多个上下文切换。