在同一个应用程序中使用Legacy OpenGL和Modern OpenGL

时间:2017-02-04 11:03:27

标签: c++ opengl

我有一台只支持OpenGL 2.1的工作笔记本电脑,我家里有OpenGL 4.4。我在桌面上正在开发一个项目。所以我使我的程序与Modern OpenGL兼容。但我想在我的工作笔记本电脑中开发这个项目。我的问题是,我可以使这个项目与Legacy和Modern OpenGL兼容吗?

喜欢这个。

#ifdef MODERN_OPENGL
some code..
glBegin(GL_TRIANGLES);
...
glEnd();
#else
glGenBuffers(&vbo);
...
#endif

3 个答案:

答案 0 :(得分:5)

你的建议是完全可能的,但是如果你通过预处理器宏完成它,你将最终进入条件编译地狱。您的方法最好的选择是编译成共享库,一个为遗留编译而一个为现代编译,并根据需要加载正确的变体。然而,当从那个方向接近它时,您也可以放弃预处理器杂耍,只需将渲染路径变体移动到它们自己的编译单元中。

另一种方法是决定在运行时使用什么渲染路径。这是我的首选方法,我通常通过函数指针表(vtable)实现它。例如,我提供的卷光栅化器库完全支持OpenGL-2.x和现代核心配置文件,并将动态调整其代码路径着色器的GLSL代码,以匹配OpenGL上下文的功能。正在使用。

如果您担心性能,请记住,允许多态功能覆盖的每个运行时环境都必须经历这个瓶颈。是的,它确实需要花费一些成本,但OTOH很常见,现代CPU的指令预取和间接跳转电路已经过优化处理。

编辑:关于“遗留”OpenGL是什么以及什么不是

的重要说明

所以这里有一件非常重要的事情我忘了首先写一下:遗产OpenGL不是glBegin / glEnd。它是关于默认情况下具有固定功能管道,而顶点数组是客户端侧。

让我重申一下: Legacy OpenGL-1.1及更高版本确实有顶点数组!这实际上意味着,与布局有关的大量代码并填充顶点数组的内容将适用于所有OpenGL。不同之处在于顶点数组数据实际上是如何提交给OpenGL的。

在传统的固定功能管道OpenGL中,您有许多预定义的属性和功能,您可以在进行glDraw…调用之前将OpenGL指向包含这些属性数据的内存区域。

当引入着色器(OpenGL-2.x,或之前通过ARB扩展)时,它们出现了与现代OpenGL仍在使用的非常相同的 glVertexAttribPointer函数。事实上,在OpenGL-2中,您仍然可以将它们指向客户端缓冲区。

OpenGL-3.3核心强制使用缓冲区对象。但是,缓冲区对象也可用于较旧的OpenGL版本(OpenGL-1.5中的核心)或ARB扩展;您甚至可以将它们用于上个世纪的非可编程GPU(这意味着有效的第一代Nvidia GeForce)。

最重要的是:您可以完美地编写OpenGL的代码,该代码与版本配置文件的大范围兼容,并且只需要非常少的版本特定代码来管理传统/现代转换。

答案 1 :(得分:1)

我首先使用“新的”OpenGL 3/4核心API编写应用程序,但限制自己使用OpenGL 2.1支持的子集。正如datenwolf指出的那样,即使在2.1

中也有顶点属性指针和缓冲区

所以没有glBegin / End块,也没有矩阵推/弹/加载,没有推/弹播放状态,没有灯光。使用制服在顶点和片段着色器中执行所有操作。

将自己限制在2.1比使用OpenGL 4中的酷炫新东西要痛苦得多,但不是很多。根据我的经验,从矩阵堆栈和内置照明切换是最难的部分,无论哪个版本的OpenGL,无论如何它都是你必须要做的工作。

最后,您将拥有一个代码版本,如果/当您决定放弃2.1支持时更新会更容易。

答案 2 :(得分:0)

根据您正在使用的实用程序库/扩展加载程序,您可以通过选中GLAD_GL_VERSION_X_XglfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR/MINOR)等在运行时检查当前上下文支持哪个版本,并创建适当的渲染器