将 Empscripten webGL canvas 保存为 JS 中的图像

Save Empscripten webGL canvas as image in JS

我有一个 Emscripten 驱动的 webGL canvas,我需要从 Javascript 处理程序保存为图像。假设有一个简单的 JS "Save" 按钮。

<script type="text/javascript">
var Exporter = {
    preRun: [],
    postRun: [],
    save: function() {
    var c=Module.canvas;
    var d=c.toDataURL("image/png");
    var w=window.open('about:blank','image from canvas');
    w.document.write("<img src='"+d+"' alt='from canvas'/>");
    }
};
</script>
<input type="button" value="Save" onclick="Exporter.save()" />

默认情况下,webGL 上下文将 preserveDrawingBuffer 设置为 false,因此生成的图像为空白。

为了显示呈现的 webGL 场景的图像,我需要将 preserveDrawingBuffer: true 添加到在我编译的 Empscripten 代码中的 getContext 调用中传递的属性。我可以通过手动编辑已编译的 empscripten js 代码来完成此操作;结果图像是正确的,但我想避免这种 hack - 每次重新编译后我都必须这样做。

是否有更简单、更简洁的方法从外部将 preserveDrawingBuffer 添加到 webGLContextAttributes?即作为 emcc 的编译选项,C 代码中的一些 SDL 参数或来自托管页面中的 Javascript?

更新 解决方案见下文;我遇到的不相关问题是保存的图像具有较低的位深度和抗锯齿线看起来很糟糕。使用 c.toDataURL( "image/jpeg" ) 解决了这个问题。

嗯,首先,所有 emscripten 及其所有库都是开源的,因此您可以直接更改它们。

特别是将 library_gl.js 复制到您的项目文件夹,然后删除 -lGL 并将 --js-library library_gl.js 添加到您的构建脚本中,然后您可以破解您的本地 library_gl.js 来做随心所欲

否则我根本不知道 SDL,但您可以在调用 emscripten 代码之前自己获取上下文。一个 canvas 只能有一个上下文,如果您再次为相同类型的上下文调用 getContext ,您将获得相同的上下文。换句话说,如果您的 JavaScript 首先创建上下文,则 emscripten 代码将获得相同的上下文

所以这应该有效

 theCanvasElement.getContext("webgl", {preserveDrawingBuffer: true});

 ... now execute emscripten and have it use `theCanvasElement`

如果你连那个都做不到,你可以覆盖 getContext

HTMLCanvasElement.prototype.getContext = (function(oldGetContextFn) {
  return function(type, attrs) {
    attrs = attrs || {};
    if (type === "webgl") {
      attrs.preserveDrawingBuffer = true;
    }
    return oldGetContextFn.call(this, type, attrs);
  };
}(HTMLCanvasElement.prototype.getContext));