将Empscripten webGL画布保存为JS中的图像

时间:2017-05-15 10:20:47

标签: javascript canvas webgl emscripten

我有一个Emscripten驱动的webGL画布,我需要将其保存为来自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代码;结果图像是正确的,但我想避免这种黑客攻击 - 我必须在每次重新编译后都这样做。

是否有更简单,更清晰的方式从外部向preserveDrawingBuffer添加webGLContextAttributes?即作为emcc的编译选项,C代码中的某些SDL参数或托管页面中的Javascript?

更新 请参阅下面的解决方案;我遇到的无关问题是保存的图像具有较低的位深度,并且消除锯齿的线看起来非常糟糕。使用c.toDataURL( "image/jpeg" )解决了这个问题。

1 个答案:

答案 0 :(得分:1)

嗯,首先,所有的emscripten和所有的库都是开源的,所以你可以改变它们。

特别是将library_gl.js复制到您的项目文件夹,然后移除-lGL并将--js-library library_gl.js添加到您的构建脚本中,然后您可以破解您当地的library_gl.js做任何事情想。

否则我根本不了解SDL,但您可以在调用emscripten代码之前自己获取上下文。画布只能有一个上下文,如果再次为同一类型的上下文调用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.apply(this, type, attrs);
  };
}(HTMLCanvasElement.prototype.getContext));