相同的程序,同时针对 Open GL 和 Open GL ES 2.0

Same program, target both Open GL and Open GL ES 2.0

可以在 "desktop" OpenGL 和 OpenGL ES 2.0 平台上使用一个 运行 相同的程序(未修改),前提是该程序仅执行 2D 加速渲染吗?

一台普通的 Windows 台式电脑和 Raspberry Pi 将 运行 该程序。 GL上下文是通过优秀的SDL2库提供的函数获得的。对于绘图例程,将使用纹理图集。

如果一个程序可以在 PC 上 developed/debugged 然后在 raspberry Pi 上重新编译为 运行 会很方便。如果两个 OGL 平台大部分兼容,这将不是问题。

由于我是 OpenGL 的初学者,所以我当然首先开始尝试 "hello triangle" 程序。

令我大吃一惊的是,这个三角程序在桌面和 Raspberry Pi (GLES2) 上都可以运行。保存一些 #include 文件差异。

被所有不同的 OpenGL headers 和函数指针体操弄得眼花缭乱 - 现在我不再确定我的桌面是否以某种方式提供了 GLES2(这对我来说似乎不太可能)或者 "desktop"我拥有的 OpenGL 版本只是 "compatible enough" with GLES2.

我特别不清楚 GLES2 是 OpenGL 的精简版还是完全不同的版本。

避免 "advanced" 或缺少 extensions/features 是否足以确保跨这些平台的兼容性?或者还有更多的事情需要考虑?

OpenGLES 是 (或多或少) OpenGL 的精简版 (主要删除了旧的遗留问题,以及任何可能影响电池寿命的功能)。这里和那里有一些非常细微的差异,但大部分情况都是如此。

在 Pi 上,您只能使用 GLES。但是在台式机上,NVidia 和 ATI 都支持 OpenGL 和 OpenGLES。我想你的基于 SDL 的应用程序是针对带有 GLES 的 EGL 上下文,并且由于 SDL 包装了所有平台特定的窗口 APIs,那应该只适用于桌面。

如果您真的想知道血淋淋的细节,请继续阅读...

初始化 OpenGL(和 GLES)的方式是向图形驱动程序查询函数指针。那么让我们举一个垃圾例子:

// This will typically be in gl.h

// some magic to prevent C++ name mangling, and use 
// C naming conventions. 
#ifdef __cplusplus
# define EXTERN extern "C"
#else
# define EXTERN extern
#endif

// declare a function pointer type that matches void glFinish()
typedef void (*GL_FINISH_PTR_TYPE)();

// now declare a function pointer that will hold the address. 
// The actual pointer will be buried away within OpenGL.lib, 
// or GLES2.lib (i.e. within a C file somewhere)
EXTERN GL_FINISH_PTR_TYPE glFinish;

基本上整个 GL 都会重复该过程 API。

然后在某个源文件中,我们将声明指针...

#include "gl.h"

// here is our function pointer, which we will set to NULL initially
GL_FINISH_PTR_TYPE glFinish = NULL;

现在以下内容往往是特定于平台的,但在每个平台上,我们都希望从驱动程序中提取那些 GL 方法的地址。所以在 windows 上它看起来有点像:

#ifdef _WIN32
void initGL()
{
  // extract pointer for glFinish from the driver
  glFinish = (GL_FINISH_PTR_TYPE)wglGetProcAddress("glFinish");
}
#endif

在 raspberry pi 上,它看起来像:

#ifdef RASPBERRY_PI
void initGL()
{
  // extract pointer for glFinish from the driver
  glFinish = (GL_FINISH_PTR_TYPE)eglGetProcAddress("glFinish");
}
#endif

所以平台之间唯一的区别是:

  • 创建 window
  • 所需的 API
  • 创建 OpenGL(或 GLES 上下文)所需的 API
  • 提取函数指针需要调用的函数。

方便地,所有特定于平台的内容都很好地包含在 SDL 中,因此您真的不需要关心它。只针对 SDL,只要您将自己限制在 GLES API 调用中,它就应该可以在两个平台上运行...

警告:您可能会遇到 NVidia/ATI/Intel 硬件之间的细微驱动差异(例如,支持的最大纹理大小等),并且显然不同的硬件将具有不同的 RAM 数量等规格。如果您的应用程序适用于较小的硬件平台,它通常也可以在更好的硬件上运行...