【问题标题】:Using Legacy OpenGL and Modern OpenGL in same application在同一应用程序中使用 Legacy OpenGL 和 Modern OpenGL
【发布时间】:2017-02-05 05:41:12
【问题描述】:

我有一台仅支持 OpenGL 2.1 的工作笔记本电脑,而我的家中有使用 OpenGL 4.4 的台式机。我正在我的桌面上处理一个项目。所以我让我的程序与现代 OpenGL 兼容。但我想在我的工作笔记本电脑上开发这个项目。我的问题是我可以让这个项目与 Le​​gacy 和 Modern OpenGL 兼容吗?

像这样。

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

【问题讨论】:

    标签: c++ opengl


    【解决方案1】:

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

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

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


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

    所以这里有一些非常重要的东西我一开始忘了写:旧版 OpenGL 不是 glBegin/glEnd。这是关于默认情况下有一个固定的函数管道,并且顶点数组是 client 端。

    让我重申一下:旧版 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 编写与大量版本配置文件兼容的代码,并且只需要很少的特定于版本的代码来管理传统/现代转换。

    【讨论】:

    • "但是缓冲区对象也可通过 ARB 扩展用于旧版 OpenGL(甚至是固定功能管道)" 缓冲区对象是 GL 1.5 的核心。因此,如果他使用的是 2.1,那么他可以访问它们。
    【解决方案2】:

    我将首先使用“新的”OpenGL 3/4 Core API 编写您的应用程序,但将自己限制在 OpenGL 2.1 支持的子集。正如上面 datenwolf 指出的那样,即使在 2.1 中,您也有顶点属性指针和缓冲区

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多