1

Emscripten对OpenGL的支持

翻译:云荒杯倾
本文是Emscripten-WebAssembly专栏系列文章之一,更多文章请查看专栏。
也可以去作者的博客阅读文章。
欢迎加入Wasm和emscripten技术交流群,群聊号码:939206522。


Emscripten支持三种OpenGL编译模式:

  • OpenGL ES 2.0/3.0的WebGL子集(默认)----支持OpenGL ES 2.0/3.0中可以直接映射到WebGL 1/2的子集。
  • 模拟OpenGL ES 2.0/3.0----支持一些WebGL中没有的OpenGL ES 2.0/3.0特性。
  • 模拟桌面OpenGL API----支持一些OpenGL 1.X 的特性和命令。

本篇文章介绍一些这几种模式的信息,并告诉大家怎么启用这些模式。

tip:
我们强烈推荐你的代码使用OpenGL ES 2.0/3.0的WebGL子集,甚至尽可能移植你的代码到这些API上。其他两种模式效率不高,只有你的代码非常依赖这两种模式的API的时候(再不得已而)用。

OpenGL ES 2.0/3.0的WebGL子集

默认下,Emscripten编译代码为OpenGL ES 2.0/3.0的WebGL子集。它是OpenGL ES可以直接映射到WebGL的一些命令。这个子集包括了OpenGL ES 2.0的绝大多数命令,除了客户端数组(client-sede arrays)和一些其他特性,可以在这个地址查看

为了针对OpenGL ES的WebGL子集编程,要使用GL ES 2.0头文件和GL ES 2.0 API,同时遵守WebGL规范第6章中具体的限制(上个地址)。

之所以默认情况下是使用此模式,是因为它能最好匹配浏览器提供的WebGL特性。

如果想让编译后的代码创建的是WebGL2上下文,请编译时设置链接标记-s USE_WEBGL2=1。在运行时,指定此标志会在运行时允许(并且默认情况下,除非在上下文创建时指定,才能)创建WebGL 2上下文,但仍有可能创建WebGL 1上下文,因此应用程序可以选择是否需要WebGL 2,或者是否支持回退到WebGL 1。

模拟OpenGL ES 2.0/3.0

这种编译模式模拟了一些不在WebGL 1规范中的OpenGL ES 2.0/3.0特性。

尤其是对OpenGL ES 2.0/3.0的WebGL子集没有包括进来的客户端数组(client-sede arrays)提供了模拟。

这允许您在没有绑定缓冲区的情况下使用glDrawArrays和glDrawElements等函数,并且Emscripten的GL bindings将自动设置缓冲区(WebGL要求绑定缓冲区)。

note:
这种构建模式有一个限制,即客户端索引缓冲区中最大的索引必须小于该缓冲区的总索引数。

要启用OpenGL ES 2.0,请指定选项-s FULL_ES2=1。

要启用OpenGL ES 2.0,请指定选项-s FULL_ES3=1。这就增加了将内存块映射到客户端内存的模拟。标记- s FULL_ES2= 1和- s FULL_ES3= 1是正交的,因此可以指定其中一个或两个同时指定来模拟不同的特性。

模拟桌面OpenGL API

OpenGL模式支持许多遗留在桌面OpenGL 1.x的特性和命令。(例如“immediate mode”和“glNormalPointer”)。

虽然这部分模拟并没有完成,但已有的模拟已经足以使用Emscripten将Sauerbraten 3D游戏(BananaBread项目)和一些其他的代码库移植了。

要启用这种模式,请指定emcc选项-s LEGACY_GL_EMULATION=1。

优化设置

在这种模式下,除了-s LEGACY_GL_EMULATION=1,还有一些额外的flags可以用来调整GL 模拟层的性能表现:

  • -s GL_UNSAFE_OPTS=1 尝试跳过冗余的GL工作和清理。这种优化不安全,所以默认下不启用。
  • -s GL_FFP_ONLY=1 告诉GL仿真层,您的代码将不会使用可编程的管道pipeline/着色器。这允许GL仿真代码在知道安全的情况下执行额外的优化。
  • 将Module.GL_MAX_TEXTURE_IMAGE_UNITS整数添加到模板文件.html,以明确代码使用的纹理单元的最大数。这确保了在检查固定函数管道(FFP)仿真着色器运行时,GL仿真层不会浪费时钟周期迭代未使用的纹理单元。(This ensures that the GL emulation layer does not waste clock cycles iterating over unused texture units when examining which Fixed Function Pipeline (FFP) emulation shader to run.)

如果我的代码依赖一个目前尚不支持的桌面OpenGL特性怎么办?

您可以考虑在Regal桌面OpenGL仿真库中构建代码库,该库旨在支持OpenGL ES 2.0上的桌面OpenGL功能。根据项目的不同,这可能比Emscripten的GL模拟效果更好或更差。

OpenGL ES 扩展

当移植代码时,应该注意到桌面OpenGL、OpenGL ES和WebGL都有自己的扩展注册表。这意味着,这三者的扩展都不是自动完成的。请参阅WebGL 1.0扩展注册表,以获得已注册扩展的完整列表。

此外,在WebGL中,与桌面或移动OpenGL不同的是,扩展必须首先在其公开的特性生效之前被激活。如果您使用一个本地的api 如SDL、EGL、GLUT或GLFW来创建您的GL上下文,那么这将自动完成大多数扩展。如果使用HTML5 WebGL上下文创建API,则必须显式地选择是否自动启用WebGL扩展。如果在上下文创建时没有自动启用扩展,那么可以使用HTML5 API函数emscripten_webgl_enable_extension来激活它。调试相关的扩展、草案扩展和供应商-前缀扩展(MOZ_ ,WEBKIT_ )在创建时不会自动启用,但必须始终手动激活。

当从WebGL 1迁移到WebGL 2时,注意一些WebGL 1扩展迁移到为 WebGL 2的核心特性,因此它们的功能不再被宣传为GL扩展。这并不意味着这些特性应该被丢弃,而是在WebGL 2中可以使用这些特性不需要首先这个测试GL扩展的存在。


Emscripten代码移植系列文章

Emscripten代码移植主题系列文章是emscripten中文站点的一部分内容。
第一个主题介绍代码可移植性与限制
第二个主题介绍Emscripten的运行时环境
第三个主题第一篇文章介绍连接C++和JavaScript
第三个主题第二篇文章介绍embind
第四个主题介绍文件和文件系统
第六个主题介绍Emscripten如何调试代码


飞叶_前端
1.4k 声望139 粉丝

Wasm和emscripten技术交流群:939206522