javascript - Webgl 动画纹理性能与 canvas drawImage 性能

标签 javascript html canvas webgl

我正在开始一个项目,我想从单个视频中切出部分并将这些部分重新绘制到屏幕上的不同对象上。我知道我可以通过使用 drawImage 将视频的各个部分重新绘制到 Canvas 元素上来做到这一点。在做研究时,似乎可以用 WebGL 中的动画纹理做同样的事情。有谁知道使用 WebGL 动画纹理而不是 drawImage 来执行此操作是否会提高性能?

最佳答案

WebGL 在性能方面优于 2D Canvas ,但是,由于您处理的是视频,那么问题是使用 WebGL 是否有任何意义。

考虑到 NTSC 世界中的视频很少超过 30 FPS(PAL 25 fps),您将有一个很好的时间预算来分割视频并重新绘制它们。还考虑到 drawImage 是一个非常快速的操作并且也有硬件支持(并且在没有硬件支持的情况下也可以工作),你可以权衡这些与 WebGL 的打扰,它不能在所有硬件上工作(比如低端消费者和较旧的硬件),并且对它的支持各不相同(在撰写本文时)。

在这种情况下,我最初会坚持使用 2D Canvas 。如果您需要将切片包裹和投影到 3D 对象上,那么 2D Canvas 不是最佳选择。您可以直接在 Canvas 元素上对一些事物使用 CSS 3D 变换,例如四边形变换。如果您需要不同的转换,只需使用不同的 Canvas 元素,每个元素代表一个切片。

顺便说一句,这里有一个技巧。是创建一个离屏 Canvas ,您首先将框架绘制到其中。这样您就不必从元素中获取正在运行的视频,这可能是一项昂贵的操作,具体取决于浏览器获取视频位图数据的方式。

一个例子:

var ctx = canvas.getContext('2d'),
    sw = 32,
    frame = document.createElement("canvas"), // "frame buffer"
    fctx = frame.getContext("2d");

frame.width = 500;
frame.height = 280;

video.addEventListener("playing", sliceAndDice, false);
function sliceAndDice() {

  fctx.drawImage(video, 0, 0); // video to "frame buffer" to make it more smooth
  
    // some misc slicing
    for(var x = 0; x < frame.width; x += sw) {
        var y = Math.sin(x*1.5) * sw + 20;
        ctx.drawImage(frame, x      , 0, sw, frame.height,   // source slice
                             x * 1.1, y, sw, frame.height);  // dest. slice
    }
    requestAnimationFrame(sliceAndDice);
}
<canvas id="canvas" width=560 height=320></canvas>
<video style="display:none" id="video" width="500" height="280" preload="auto" autoplay="true">
  <source src="//clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
  <source src="//clips.vorwaerts-gmbh.de/big_buck_bunny.webm" type="video/webm">
  <source src="//clips.vorwaerts-gmbh.de/big_buck_bunny.ogv" type="video/ogg">
</video>

一个包含 320 个切片的替代演示,展示您可以仅使用 2D Canvas 将它推得相当远:

var ctx = canvas.getContext('2d'),
    frame = document.createElement("canvas"),         // "frame buffer"
    fctx = frame.getContext("2d"),
    dlt = 0;

frame.width = video.width;
frame.height = video.height;

video.addEventListener("playing", sliceAndDice, false);
function sliceAndDice() {

  fctx.drawImage(video, 0, 0);   // video to frame buffer to make it smoother
  
  // some misc slicing
  for(var x = 0, y; x < frame.width; x++) {
      y = Math.sin(x*32+dlt) * 3 + 10;               // "random" y pos.
      ctx.drawImage(frame, x, 0, 1, frame.height,   // source slice
                           x, y, 1, frame.height);  // dest. slice
  }
  dlt += 0.2;
  requestAnimationFrame(sliceAndDice);
};
<canvas id="canvas" width=560 height=320></canvas>
<video style="display:none" id="video" width="500" height="280"
       preload="auto" autoplay="true">
<source src="//clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
<source src="//clips.vorwaerts-gmbh.de/big_buck_bunny.webm"type="video/webm">
<source src="//clips.vorwaerts-gmbh.de/big_buck_bunny.ogv" type="video/ogg">
</video>

关于javascript - Webgl 动画纹理性能与 canvas drawImage 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27208715/

相关文章:

javascript - 使用鼠标上下绘制 Canvas

javascript解析带有动态变量的嵌套json

javascript - Javascript 预加载内容 three.js

javascript - 如何在 Javascript 中迭代嵌套对象数组

jquery - Jquery 中的 mouseleave 时 Div 不会返回

javascript - 使用数字键盘但没有箭头按钮的跨浏览器数字输入

javascript - 如何通过手动在文本字段中输入内容来填充时间戳?

javascript - 每次更改后刷新 Canvas

javascript - 需要 JQuery 建议

javascript IF 嵌套在 FOR 循环中不过滤结果