将 15000 行代码从 C++ 编译为 WebAssembly,是种怎样的体验?
总体的规划
-
为使用 Emscripten 编译代码做好准备; -
修改代码,解决编译到 WebAssembly 遇到的问题。
第一步:准备代码
-
尽可能减少依赖项的数量。 -
修改代码。 -
为导出函数和/或枚举做准备。
依赖关系
-
Emscripten 内置 OpenGL 的支持,但严格来说,只能支持 OpenGL 的子集 WebGL2。 -
glad 是一个 OpenGL 加载库,Emscripten 可以处理这部分,因此不需要在意。 -
glm 是一个只有头文件的数学库。我们可以使用 -I 选项将其包含到构建中。
修改头文件并排除有问题的函数
#ifdef __EMSCRIPTEN__
#include <GL/gl.h>
#include <GLES3/gl3.h>
#else
#include <glad/glad.h>
#endif
-
一些无法用 Emscripten 编译到 WebGL2 的 OpenGL 函数。对于这一类函数,我只能暂时注释掉,然后等到第二步再解决。 -
一些需要读写磁盘的函数,例如加载字体。由于编译好的代码会放到 Web 上运行,因此 Emscripten 禁止访问磁盘。如果你需要从磁盘读取文件,则可以在链接时将其预加载到 Emscripten 提供的虚拟文件系统。我使用了这个虚拟文件系统来预加载所有的着色器。
准备导出函数和/或枚举
-sEXPORTED_FUNCTIONS=’[$(shell cat functions_to_export.txt)]’
-
包含WebAssembly 代码的 .wasm 文件。 -
一个 .js 文件,这是一个“胶水”文件,能够在WebAssembly 和你希望与之交互的其他 JavaScript 或 HTML 文件之间建立链接。 -
一个 .data 文件,其中包含我在 Emscripten 的虚拟文件系统中预加载的文件。
第二步:修改代码
-
选择一个类,比如说球体类。 -
修改代码,使其能够通过新编译的渲染引擎。 -
遇到一些由于从C++ 到 WebAssembly 的转换而引发的错误。 -
修复错误。 -
重复第一步。
问题
-
指针问题。 -
OpenGL 的问题。
指针
例子
-
我有一个 C 函数,经过了 WebAssembly 的编译,可更改背景颜色。这个函数需要一个参数:constfloat* color。 -
在JavaScript 中,颜色存储在一个简单的 JavaScript 数组中。 -
我直接将这个数组传给了 C 函数。
-s ‘EXPORTED_RUNTIME_METHODS=[“ccall”, “cwrap”]’
Module.ccall('wr_post_processing_effect_pass_set_name', null,['number', 'string'], [colorPassTrough, "colorPassThrough"]);
var buf =Module._malloc(myTypedArray.length*myTypedArray.BYTES_PER_ELEMENT);
Module.HEAPU8.set(myTypedArray, buf);
Module.ccall('my_function', 'number', ['number'], [buf]);
Module._free(buf);
float *wrjs_array3(float element0, float element1, floatelement2) {
static float array[3];
array[0] = element0;
array[1] = element1;
array[2] = element2;
return array;
}
OpenGL
-
修改 C++ 代码,用不同的方式来实现相同的功能,同时能与 gcc(必须保证渲染引擎的桌面版能够正常运行)和 WebAssembly 兼容。 -
使用 EM_ASM,这是一种很方便的方法,我们可以直接用 C 编写 WebGL 代码。如果遇到某个 WebGL 2 的函数,而 OpenGL ES 3 没有,就可以使用这种方法。 -
发挥创造力。我直接重新实现了一些着色器或代码中不可用的函数,并利用 ifdef 为编译器 Emscripten 或 gcc 编写了不同的处理。
建议
-
尽量采用纯 C 语言编写的 API,C 版的 API 比 C++ 更容易导出。 -
见机行事,没有某个神奇的解决方案能够解决编译成 WebAssembly引入的所有问题。 -
小心没有任何错误和警告的问题,导出的函数会经常发生这种情况。 -
仔细管理指针,并仔细检查你提供给 WebAssembly 的数据是否得到了正确的解释。 -
减少代码依赖项的数量。
结果
☞
CSDN
成就一亿技术人
Official Account
