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

Bat*_*gen 7 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
Run Code Online (Sandbox Code Playgroud)

dat*_*olf 5

您提出的建议完全有可能,但是,如果通过预处理器宏执行此操作,则最终将陷入条件编译的境地。最好的选择是将其编译到共享库中,一个针对旧版进行编译,另一个针对现代版进行编译,并按需加载正确的变体。但是,从该方向接近它时,您也可以抛弃预处理器的处理,只需将渲染路径变体移到其自己的编译单元中即可。

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

如果您担心性能,请记住,实际上,允许多态函数覆盖的每个运行时环境都必须克服该瓶颈。是的,这确实要付出一定的成本,但是OTOH太普遍了,以至于现代CPU的指令预取和间接跳转电路都已经过优化以应对这一问题。


编辑:关于什么是“遗留” OpenGL是什么,什么不是重要说明

因此,这是我首先要忘记写的非常重要的东西:旧版OpenGL不是glBegin/ glEnd。它是关于默认情况下具有固定功能管道,并且顶点数组是客户端。

让我重申一下:旧版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编写代码,该代码与范围广泛的版本配置文件兼容,并且只需要很少的特定于版本的代码即可管理旧版/现代事务。


w1c*_*h3r 0

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