什么时候需要使用 OpenGL 函数加载器?

When do I need to use an OpenGL function loader?

我对什么时候需要使用像 GLEW 这样的 OpenGL 函数加载器感到有点困惑。通常,您似乎首先获得 window 和有效的 OpenGL 上下文,然后尝试加载函数。

OpenGL 函数(核心或扩展)必须在运行时动态加载,只要相关函数不是平台原始 OpenGL ABI 的一部分(应用程序 binary 接口)。

  • 对于 Windows,ABI 涵盖的是 OpenGL-1.1
  • 对于 Linux,ABI 涵盖 OpenGL-1.2(其他 *nixes 没有官方的 OpenGL ABI,但它们通常也需要 OpenGL-1.2)
  • 对于 MacOS X 可用的 OpenGL 版本及其 ABI 由 OS 版本定义。

这导致以下规则:

  • 在 Windows 中,除了单纹理、无着色器、固定函数绘图之外,几乎所有内容都需要一个函数加载器;可以加载更多功能,但这不是给定的。
  • 在 Linux 中,几乎所有内容都需要一个函数加载器,除了基本的多纹理,只有基本的 texenv 模式、无着色器、固定函数绘图;可以加载更多功能,但这不是给定的。
  • 在 MacOS X 中你根本不需要函数加载器,但是你可以使用的 OpenGL 特性严格由 OS版本,要么有,要么没有。

核心 OpenGL 功能和扩展之间的区别在于,核心功能在 OpenGL 规范中找到,而扩展是除了可用的 OpenGL 版本提供的功能之外可能提供或不提供的功能。

扩展和更新版本的核心功能都是通过相同的机制加载的。

datenwolf 的回答很好,但我想澄清一下你在问题的第一个要点中所说的内容。

核心和扩展状态不依赖于平台,甚至不相互排斥。

核心意味着在某个版本的 OpenGL 中引入了一些功能。有核心功能,这些功能保证存在于版本 X.Y 中,甚至还有核心扩展,即与版本 X.Y 一起引入的 扩展 .核心扩展仅以不需要特定版本的扩展形式提供与核心功能相同的功能、类型、枚举等。

Framebuffer 对象成为 OpenGL 3.0 的核心,并且比 OpenGL 3.0 之前的 EXT 扩展 (GL_EXT_framebuffer_object) 的限制稍微少一些。但是,无需 OpenGL 3.0 实现即可访问 FBO 的核心版本 - OpenGL 2.1 实现可能会提供核心功能。

GL_ARB_framebuffer_object 的扩展规范中,您会发现:

Issues

(8) Why don't the new tokens and entry points in this extension have "ARB" suffixes like other ARB extensions?

RESOLVED: Unlike most ARB extensions, this is a strict subset of functionality already approved in OpenGL 3.0. This extension exists only to support that functionality on older hardware that cannot implement a full OpenGL 3.0 driver. Since there are no possible behavior changes between the ARB extension and core features, source code compatibility is improved by not using suffixes on the extension.

这是我第一次提到核心扩展,但不是最后一次。从那时起,许多 ARB 扩展被创建,"backport"(如果你愿意的话)来自更高版本的核心功能。

这是通过解析 gl.xml 为另一个核心扩展收集的一些示例输出:

 >> Command:  void glBufferStorage (GLenum target, GLsizeiptr size, const void *
                                    data, GLbitfield flags)

  * Provided by GL_ARB_buffer_storage (gl|glcore)

  * Core in                   GL_VERSION_4_4    (   gl 4.4)

它是 4.4 中的核心(保证在 4.4 实现中存在),但是因为提供它的扩展是 glcore,所以这个 core 如果核心扩展可用,则功能可能在较旧的实现中可用。

我编写的用于解析 gl.xml 此信息的简单软件可以找到 here 如果您有兴趣。

函数加载器仅在 Windows 和 Linux 上需要。下面简要介绍了如何在不同平台上针对各种 OpenGL 版本进行构建。

Windows

Windows 开发工具仅包含用于 OpenGL 1.1 的 header。阴谋论者可能会声称微软对简化 OpenGL 的使用不感兴趣,因为它希望开发人员使用专有的 API。

对于 1.1 之后的任何版本,您需要通过调用 wglGetProcAddress() 动态加载入口点。 GLEW 等库为更高版本的 OpenGL 提供了 header 文件,并封装了加载入口点的逻辑。

Linux

我还没有在 Linux 上进行过 OpenGL 编程。据我所知,它需要类似于 Windows 的函数加载。我将遵从@datenwolf 的详细回答。

Mac OS

Mac OS 支持两个主要的 OpenGL 功能集:

  • 具有遗留功能的 OpenGL 2.1。这是通过包含 <OpenGL/gl.h>.
  • 使用的
  • OpenGL 3.x 及更高版本,仅限核心配置文件。通过包含 <OpenGL/gl3.h>.
  • 使用

在这两种情况下,您都不需要任何动态函数加载。 header 文件包含可以支持的最大版本的所有 declarations/definitions,并且您 link 反对的框架(使用 -framework OpenGL)解析函数名称。

您在构建时可以使用的最高版本取决于您构建的平台 SDK。默认情况下,这是与您的构建机器的 OS 相匹配的平台 SDK。但是您可以使用 -isysroot 构建选项更改它。

在 运行 时,机器必须 运行 至少 OS 匹配构建时使用的平台 SDK,并且您只能使用支持版本的功能由 GPU。您可以大致了解哪些硬件支持哪些版本:

https://developer.apple.com/opengl/capabilities/ http://support.apple.com/en-us/HT202823

Android, NDK

使用 Android 上的本机代码,您可以在设置上下文和表面时选择 OpenGL 版本。然后,您的代码包含针对匹配库的所需 header(如 <GLES2/gl2.h><GLES3/gl3.h>)和 link。不需要动态函数加载。

如果目标设备不支持您尝试使用的版本,上下文创建将失败。您可以在清单中添加一个条目,以防止应用程序安装在不支持所需 ES 版本的设备上。

Android,Java

这与 NDK 的情况非常相似。所需版本在安装期间指定,例如在创建 GLSurfaceView.

GLES20 class 包含 ES 2.0 的定义。 GLES30 派生自 GLES20,并添加了 ES 3.0 的附加定义。

iOS

毫不奇怪,这与 Mac OS 非常相似。您包含与所需 OpenGL ES 版本(例如 <OpenGLES/ES3/gl.h>)相匹配的 header 文件,针对框架 link,您就完成了。

也匹配 Mac OS,您可以构建的最高版本取决于您选择的平台 SDK 版本。您要 运行 的设备必须至少使用与此平台 SDK 版本匹配的 OS 版本,并支持您正在使用的 OpenGL ES 版本。

一个主要区别显然是您在 Mac 上交叉编译应用程序。 iOS 使用一组不同的平台 SDK,具有不同的 header 和框架,但整个过程与为 Mac OS.[=24= 构建几乎相同]