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

标签 c++ opengl

我有一台只支持 OpenGL 2.1 的工作笔记本电脑,我家里有一台装有 OpenGL 4.4 的台式机。我正在我的桌面上处理一个项目。所以我使我的程序与现代 OpenGL 兼容。但我想在我的工作笔记本电脑上开发这个项目。我的问题是我能否使该项目与旧版和现代 OpenGL 兼容?

像这样。

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

最佳答案

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

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

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


编辑:关于什么是“传统”OpenGL 和什么不是的重要说明

所以这里有一些非常重要的东西我一开始就忘了写:Legacy OpenGL 不是glBegin/glEnd。这是关于默认情况下具有固定功能管道和顶点数组作为客户端

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

在遗留的固定功能管道 OpenGL 中,您有许多预定义的属性和函数,您可以使用它们将 OpenGL 指向保存这些属性数据的内存区域,然后再进行 glDraw... 调用。

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

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

底线是:您可以完美地为 OpenGL 编写与大量版本配置文件兼容的代码,并且只需要非常少的特定于版本的代码来管理遗留/现代转换。

关于c++ - 在同一个应用程序中使用 Legacy OpenGL 和 Modern OpenGL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42039584/

相关文章:

c++ - 返回数组值时出现问题

c++ - 在 MacOS 上使用 QOpenGLDebugLogger

c++ - 动画 glutWireSphere

c++ - 为什么 Graphics Pipeline 如此特化? (OpenGL)

opengl - 在 OpenGL 中使用列主矩阵会导致在 GPU 上大步前进吗?

c++ - 更改 char 变量值并使用指针打印

c++如何将类序列化为json并解析json文件?

java - 当数据写入 Protocol Buffer 时,如何让 Java 触发 C++ 程序,反之亦然?

c++ - 如何像在 C++ 中那样做函数指针,但对于变量

python - 如何使用 pyglet 提高批处理的性能?