相同的程序,同时针对 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 数量等规格。如果您的应用程序适用于较小的硬件平台,它通常也可以在更好的硬件上运行...
可以在 "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 数量等规格。如果您的应用程序适用于较小的硬件平台,它通常也可以在更好的硬件上运行...