是否需要为我创建的每个GLFW窗口调用glewInit()?

oogrdqng  于 2022-09-26  发布在  其他
关注(0)|答案(1)|浏览(152)

这是我的第一个大型OpenGL项目,我对我想要实现的一个新功能感到困惑。

我正在研发一款游戏引擎。在我的引擎中有两个类:RendererCustomWindow。需要初始化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);
}
hrysbysz

hrysbysz1#

经过一些研究,我会说这要视情况而定,因此最好是先看看基础,然后再形成看法。

OpenGL wiki提供了一些有用的信息。
加载OpenGL函数是创建OpenGL上下文后初始化OpenGL的重要任务。强烈建议您使用OpenGL加载库,而不是手动流程。然而,如果您想知道它是如何手动工作的,请继续阅读。

Windows

此函数仅在存在有效的OpenGL上下文时才起作用。事实上,它返回的函数指针本身是特定于上下文的。此函数的Windows文档指出,返回的函数可能适用于另一个上下文,具体取决于该上下文的供应商和该上下文的像素格式。

在实践中,如果两个上下文来自相同的供应商并引用相同的GPU,则从一个上下文提取的函数指针将在另一个上下文中工作。

Linux和X-Windows

这个函数可以在没有OpenGL上下文的情况下运行,但它返回的函数显然不能。这意味着函数与上下文没有任何关联。

如果查看glew(./src/glew.c)的源代码,您会发现lib只是调用底层系统的加载过程,并将这些调用的结果赋给全局函数指针。

换句话说,多次调用glewInit除了OpenGL wiki中解释的副作用外,没有其他副作用。

另一个问题是:您真的需要为该任务使用多个窗口吗?仅使用一个上下文和多个帧缓冲区对象就可以实现不同的方法。

多个上下文(它们之间共享资源)和事件处理(只能从‘main’线程调用)需要正确的同步和多个上下文切换。

相关问题