OpenGL ES中的跨平台渲染器

run*_*ead 6 opengl cross-platform opengl-es renderer

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

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

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

Nic*_*las 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);
Run Code Online (Sandbox Code Playgroud)

序言还可以包括特定于平台的#define.用户定义的当然.这样,您就可#ifdef以为不同的平台编写代码.

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

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