如何解决这个设计缺陷?
How to resolve this design flaw?
开发 teris 游戏 我得出的结论是,使用通常的 MVC 模式可能会使我的代码混乱,而且由于 OpenGL 在 GLEW 下的工作方式,使得构建代码变得更加困难。相反,我想出了这个巧妙的修改,也依赖于观察者模式,这会更有意义,至少在短期内(图像不反映完整的 class 树):
解释一下:
- 每个盒子都是一个 class,Engine
包含 Entities
的实例,Game
包含 Figure
的实例。
-Figure
继承Entity
。
-Engine
观察 Game
,并且 Game
被观察者与 Figures
.
耦合
它应该如何工作:
理想情况下,我应该实例化 Engine
,它将设置 GLEW 和 GLFW 以及构成 window 的所有其他内容,然后创建一个 Game
对象,该对象将在新线程中创建一个figure,并通知引擎开始绘图循环,当该 figure 被设置时,通过 Observer 将其与指向 Engine
的对象指针一起传递。
这会很好地工作,我可以通过继承 Entity
添加各种图形,图形不会从屏幕上掉下来,因为每个坐标更新都会经过 Game
,而且我可能可以, 如果有必要,给每个图形一个独特的着色器。
它的实际工作原理:
Engine初始化,Game初始化,Figure在另一个线程中调用,抛出
atioglxx.dll: 0xC0000005: Access violation reading location 0x00000728.
当被要求访问任何 OpenGL 功能时。
我怀疑发生这种情况是因为 Figure
不知道所有支持功能都在 Engine
中启动。而且我不能在 Figure
中再做一次。我可以将与视图有关的所有内容移动到 Engine
,但那样我就无法设置单独的着色器,而且我必须为 Engine
中的每个图形构建 VAO(顶点数组对象) ].
那么,如何在引入尽可能少的更改的同时消除错误?
简短的回答是,对给定上下文的所有 OpenGL 调用都需要在同一个线程上。更长的答案正在路上...
首先,Entities
需要能够使用 GL 调用绘制自己。您不能将来自一个线程的绘图代码与另一个线程混合,OpenGL 客户端状态将不正确。 (将 OpenGL 视为 'C' 状态机)。
其次,您需要按帧缓冲实体状态。当您在 Game
线程中开始下一帧时,Engine
可能会或可能不会完成提交绘图调用。所以你需要一些同步的方式来提交一个框架的所有 Entity
状态。这有点棘手,因为您想避免同步原语(例如互斥锁),这可能会使您的管道停滞或导致阻塞。
您可以阅读 Doom III source code,它使用双缓冲管道将绘图调用提交到 Engine
后端。诀窍在于 Doom 在主线程上完成大部分工作,然后在后端 (Engine
) 线程上执行 Draw Call,并在 [=] 上为下一帧提交绘制状态 (Entities
) 12=] 主线程。然后它等待 Engine
线程完成并交换缓冲区。
阅读 Metal 和 Vulkan 多线程。这些很相似。
需要在 Engine
上加载资源并返回句柄供您的实体引用(着色器、纹理、静态几何等。)
开发 teris 游戏 我得出的结论是,使用通常的 MVC 模式可能会使我的代码混乱,而且由于 OpenGL 在 GLEW 下的工作方式,使得构建代码变得更加困难。相反,我想出了这个巧妙的修改,也依赖于观察者模式,这会更有意义,至少在短期内(图像不反映完整的 class 树):
解释一下:
- 每个盒子都是一个 class,Engine
包含 Entities
的实例,Game
包含 Figure
的实例。
-Figure
继承Entity
。
-Engine
观察 Game
,并且 Game
被观察者与 Figures
.
耦合
它应该如何工作:
理想情况下,我应该实例化 Engine
,它将设置 GLEW 和 GLFW 以及构成 window 的所有其他内容,然后创建一个 Game
对象,该对象将在新线程中创建一个figure,并通知引擎开始绘图循环,当该 figure 被设置时,通过 Observer 将其与指向 Engine
的对象指针一起传递。
这会很好地工作,我可以通过继承 Entity
添加各种图形,图形不会从屏幕上掉下来,因为每个坐标更新都会经过 Game
,而且我可能可以, 如果有必要,给每个图形一个独特的着色器。
它的实际工作原理:
Engine初始化,Game初始化,Figure在另一个线程中调用,抛出
atioglxx.dll: 0xC0000005: Access violation reading location 0x00000728.
当被要求访问任何 OpenGL 功能时。
我怀疑发生这种情况是因为 Figure
不知道所有支持功能都在 Engine
中启动。而且我不能在 Figure
中再做一次。我可以将与视图有关的所有内容移动到 Engine
,但那样我就无法设置单独的着色器,而且我必须为 Engine
中的每个图形构建 VAO(顶点数组对象) ].
那么,如何在引入尽可能少的更改的同时消除错误?
简短的回答是,对给定上下文的所有 OpenGL 调用都需要在同一个线程上。更长的答案正在路上...
首先,Entities
需要能够使用 GL 调用绘制自己。您不能将来自一个线程的绘图代码与另一个线程混合,OpenGL 客户端状态将不正确。 (将 OpenGL 视为 'C' 状态机)。
其次,您需要按帧缓冲实体状态。当您在 Game
线程中开始下一帧时,Engine
可能会或可能不会完成提交绘图调用。所以你需要一些同步的方式来提交一个框架的所有 Entity
状态。这有点棘手,因为您想避免同步原语(例如互斥锁),这可能会使您的管道停滞或导致阻塞。
您可以阅读 Doom III source code,它使用双缓冲管道将绘图调用提交到 Engine
后端。诀窍在于 Doom 在主线程上完成大部分工作,然后在后端 (Engine
) 线程上执行 Draw Call,并在 [=] 上为下一帧提交绘制状态 (Entities
) 12=] 主线程。然后它等待 Engine
线程完成并交换缓冲区。
阅读 Metal 和 Vulkan 多线程。这些很相似。
需要在 Engine
上加载资源并返回句柄供您的实体引用(着色器、纹理、静态几何等。)