6

(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 上下文渲染到随机画布元素(或任何其他元素,并不重要)的良好经验?

我的想法如下:

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

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

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

谢谢

在此处输入图像描述

ps 底部图(带有红色波浪线)现在由 WebAssembly 和 OpenGL(GLFW 等)渲染

- - - 更新 - - -

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

4

1 回答 1

5

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

我只使用 1 个上下文 (GLFW) 并通过 JS 触发 C++ 函数来呈现图表,一旦完成 c++ 信号返回给 JS,使用 EM_ASM_ 和相应的图表 ID 将结果(图像)呈现到其目标画布宽度:

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

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

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

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

于 2017-07-23T13:03:38.657 回答