javascript - WebAssembly 和 OpenGL - 单一上下文,多个输出(到 Canvas )

标签 javascript opengl emscripten asm.js webassembly

(OpenGL/Emscripten 新手)

对于我正在构建的股票交易客户端应用程序,需要 40 多个打开的图表。其中大约 50% 处于某种“自由绘制”状态,这意味着它们显示烛台以及其他线条/箭头/图像等。

在过去几个月尝试了很多选择之后,归根结底是这样的。

  • HighCharts:简单但缓慢;
  • CanvasJS:更快但不够快
  • WebAssembly + OpenGL:快很多,但需要做很多工作(仍然值得 它)

我引导一个 WebAssembly 应用程序实例,并调用它的函数让 C++ 使用 OpenGL 创建图表,映射到 WebGL(2)。一切正常。

我选择 (WebAssembly + OpenGL) -> Emscripten 的原因是因为有很多数字运算,而 c++ 也适合这项工作:)

问题是 WebGL 在 Chrome(59) 中的上下文限制约为 10。所以拥有 40-100 个 WebGL 上下文(图表)不是一个聪明的主意,而且我的直觉告诉我,拥有这么多几乎总是输出为静态图像的上下文是对 OpenGL 资源的浪费,除非你滚动图表等。

有没有人有将单个 OpenGL 上下文渲染到随机 Canvas 元素(或任何其他元素,并不重要)的良好经验?

我的思路如下:

  1. 在另一个线程中使用离屏 Canvas 启动 c++ OpenGL, https://github.com/OleksandrChekhovskyi/emscripten-offscreen-canvas-test/blob/master/main.c#L35
  2. Javascript 告诉 c++ 渲染图形
  3. 通过共享 Uint8Array 与 JS 共享/渲染 OpenGL 后备缓冲区...SharedArrayBuffers 由 JS 工作线程中的 C++ 填充,而主(渲染)线程仅读取/转译以将图像写入 canvas/html 元素。

我似乎没有任何其他方法可以不创建许多 OpenGL 上下文。

问题是:这样做的性能如何,基本上将 OpenGL 缓冲区复制到 Javascript 等?它偏离轨道很远吗?

谢谢

enter image description here

附注底部图形(带有红色波浪线)现在由 WebAssembly 和 OpenGL(GLFW 等)呈现

------ 更新 -----

选项 2:始终渲染到同一个 Canvas ,并使用 JS 将 Canvas 的上下文复制到另一个 Canvas (但如果上下文更新,它可能会被删除..)

最佳答案

因此,在构建更多之后,我找到了一个快速的解决方案。

我仅使用 1 个上下文 (GLFW) 并通过 JS 触发 C++ 函数来渲染图表,一旦完成,C++ 会使用带有相应图表 ID 的 EM_ASM_ 将结果(图像)渲染到其目标 Canvas 宽度的信号返回给 JS:

chart.el.getContext('2d').drawImage(Module.canvas, 0, 0, width, height, 0, 0, width, height);

我测试了它,它运行得非常快,从 Canvas 复制图像总是不到 1 毫秒。即使在具有 2K+ 图像的 4K 屏幕上也是如此。

当 Chrome 完全支持离屏 Canvas 时,我可以在 Web Worker 中加载 WebAssembly 渲染部分并完全绕过主线程,并且可以动态切换 Canvas 上下文以立即渲染到目标 Canvas 。让它更快。但现在还不可能(再过几个月 :))

因此,除非浏览器支持 100 多个 webGL 上下文,否则我猜这将是不久的将来最快的解决方案。

关于javascript - WebAssembly 和 OpenGL - 单一上下文,多个输出(到 Canvas ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45121115/

相关文章:

webassembly - 将 protobuf c++ 程序编译为 wasm(WebAssembly)

javascript - 动态加载 JavaScript 并监控下载进度

使用 emscripten 编译 Xcode 项目

javascript - 指定你想要的事件

javascript - 如何使用僵尸js检测元素可见性?

java - 我想每帧调用一次 glBegin 和 glEnd

c++ - CreateWindowEx WS_POPUP 为什么要打边框?

javascript - 使用 jquery css 覆盖的同位素过滤器无法按预期工作

javascript - Fancytree:在 DOM 中可见的新 child (通过 LacyLoad 加载)之后的事件

java - gluProject 将 3D 坐标转换为 2D 坐标不会正确转换 2D Y 坐标