OpenGL ES中的跨平台渲染器

时间:2012-01-19 09:52:45

标签: opengl opengl-es cross-platform renderer

我正在编写一个跨平台的渲染器。我想在Windows,Linux,Android,iOS上使用它。

您是否认为避免绝对抽象并直接在OpenGL ES 2.0中编写它是一个好主意?

据我所知,我应该可以在PC上针对标准OpenGL进行编译,只需对代码进行一些小的更改即可处理上下文和连接到窗口系统。

2 个答案:

答案 0 :(得分:8)

  

您是否认为避免绝对抽象并直接在OpenGL ES 2.0中编写它是一个好主意?

您对此的主要困难是处理ES 2.0规范中与OpenGL 2.1实际上不相同的部分。

例如,您无法通过桌面GLSL 1.20编译器推送ES 2.0着色器。在ES 2.0中,您可以使用指定精度等内容;这些是GLSL 1.20中的非法结构。

可以#define围绕着他们,但这需要一些人工干预。您必须在着色器源文件中插入#ifdef。你可以使用着色器编译技巧来使这更容易。

确实,因为GL ES使用完全不同的扩展集(尽管有些是桌面GL扩展的镜像和子集),您可能希望这样做。

每个GLSL着色器(桌面或ES)都需要有一个“前导码”。着色器中的第一个非注释事项需要是#version声明。幸运的是,桌面GL 2.1和GL ES 2.0之间的版本相同:#version 1.20。问题是下一步:#extension列表(如果有的话)。这样可以启用着色器所需的扩展。

由于GL ES使用来自桌面GL的不同扩展名,因此您需要更改此扩展名列表。由于赔率很​​高,你需要比桌面GL 2.1扩展更多的GLSL ES扩展,这些列表不仅仅是1:1的映射,而是完全不同的列表。

我的建议是使用能够为GLSL着色器提供多个字符串。也就是说,您的实际着色器文件有任何前导码。它们只有 具有实际的定义和功能。着色器的主体。

在GL ES上运行时,您将拥有一个全局前导码,您将附加到着色器的开头。您将在桌面GL中拥有不同的全局序言。代码如下所示:

GLuint shader = glCreateShader(/*shader type*/);
const char *shaderList[2];
shaderList[0] = GetGlobalPreambleString(); //Gets preamble for the right platform
shaderList[1] = LoadShaderFile(); //Get the actual shader file
glShaderSource(shader, 2, shaderList, NULL);

序言包含特定于平台的#define。用户定义的当然。这样,您可以为不同平台#ifdef代码。

两者之间还存在其他差异。例如,虽然有效的ES 2.0纹理上传函数调用在桌面GL 2.1中正常工作,但它们不一定是最佳的。像所有移动系统一样在大端机器上上传的东西需要在小端台式机中稍微偏离驱动程序。因此,您可能希望有一种方法在GL ES和桌面GL上指定不同的像素传输参数。

此外,您还希望利用ES 2.0和桌面版GL 2.1中的不同扩展集。虽然他们中的许多人试图互相镜像(OES_framebuffer_object是EXT_framebuffer_object的一个子集),但你可能会遇到类似上面提到的类似“不完全子集”的问题。

答案 1 :(得分:3)

在我谦逊的经历中,满足这种要求的最佳方法是用纯C风格开发发动机,而不需要额外的层。

我是PATRIA 3D引擎的主要开发人员,它基于您在可移植性方面提到的基本原则,我们通过在基本标准库上开发工具来实现这一目标。

然后在不同平台上编译代码的工作非常少。

根据您要嵌入引擎的组件,可以计算移植整个解决方案的实际工作量。

例如:


标准C:

引擎3D

游戏逻辑

游戏AI

物理


+


窗口界面(GLUT,EGL等) - 取决于平台,无论如何可以是用于桌面的GLUT和用于移动设备的EGL。

人机界面 - 取决于移植,Android版Java,IOS版OC,版本桌面

声音管理器 - 取决于移植

市场服务 - 取决于移植


通过这种方式,您可以无缝地重复使用95%的工作量。

我们已经为我们的发动机采用了这种解决方案,到目前为止,它确实值得进行初始投资。