如何在窗口构造函数中正确管理渲染器初始化?

问题描述 投票:0回答:1

作为练习,我正在用 C++ 围绕 GLFW 和 OpenGL 编写一个简单的包装器。我有两个类:

Window
Renderer
,其中
Window
拥有
Renderer
的实例。

Window
类在其构造函数中设置GLFW上下文,运行主循环,并使用其
Renderer
成员来处理绘图。
Renderer
类在其构造函数中设置缓冲区并处理 OpenGL 函数调用。

我面临的问题是 OpenGL 需要任何函数调用的有效上下文。如果我在调用

Renderer
构造函数之前初始化
Window
,则
Renderer
构造函数将在创建 GLFW 上下文之前运行。

为了避免这种情况,我将

unique_ptr
存储到
Renderer
类中的
Window
,并在
std::make_unique<Renderer>
构造函数中使用
Window
实例化它。然后,在
Window
析构函数中,我在销毁 GLFW 上下文之前调用
std::unique_ptr::reset()
,以确保在上下文有效时仍然可以进行 OpenGL 调用来释放资源。

class Window
{
   public:
       Window()
       {
           // Initializing GLFW and creating an OpenGL context
           // ...
           m_renderer = std::make_unique<Renderer>();
       }
       ~Window()
       {
           m_renderer.reset();
           glfwTerminate();
       }
       int run()
       {
           while(...)
           {
               m_renderer->draw();
               // ...
           }
           return 0;
       }
   private:
       std::unique_ptr<Renderer> m_renderer; 
       // ...
}

class Renderer
{
    public:
        Renderer() { /* Set buffers */ }
        ~Renderer() { /* Free buffers */ }
        draw() { glDrawElements(...); /* ... */ }
    private:
        // ...
}

int main()
{
     Window window();
     return window->run();
}
        

我理解,在调用

Renderer
构造函数时,
Window
对象应该已经初始化,但这里的情况并非如此。我觉得我可能颠倒了
Renderer
Window
之间的依赖关系,或者我的整体架构可能是错误的。我宁愿依赖根据范围在正确的时刻调用构造函数和析构函数,而不是手动触发它。

更好的解决方案是什么?

c++ opengl glfw abstraction glew
1个回答
2
投票

我建议您创建一个单独的类,将其命名为

GLFWInit
,它执行 GLFW 初始化并在其析构函数中调用
glfwTerminate()
。那么你有两个选择:

  1. GLFWInit
    类型的对象嵌入到您的
    Window
    类中。尽早放置该成员,但至少在
    m_renderer
    成员之前。

  2. Window
    派生您的
    GLFWInit
    类。

这两种方法都确保 GLFW 在

m_renderer
之前初始化并在其之后拆除。然后,您甚至不必将渲染器设置为指针,并且可以直接嵌入成员(如果可行)。

© www.soinside.com 2019 - 2024. All rights reserved.