【发布时间】:2017-01-05 05:10:54
【问题描述】:
更新:这整个问题最终是系统图形驱动程序的问题,而不是(看似)浏览器/API问题。撕裂的框架归结为实际的显示更新。再次感谢那些参与讨论并试图提供帮助的人。
我的页面使用画布和 2d 上下文以 720p 显示预渲染帧。我正在单独渲染帧并使用新的 ImageData 更新变量。然后,在 requestAnimationFrame 中,我只需执行 context.putImageData(cached_image_data);。尽管提前完全渲染了帧并有效地进行了双重缓冲,但我仍然经常撕裂。我在 SO 上发现了一些其他问题,但它们都以“使用 RAF”结尾。代码归结为:
var canvas = document.getElementById("canvas");
var cached_frame = new ImageData(new Uint8ClampedArray(canvas.width * canvas.height * 4), canvas.width, canvas.height);
var context = canvas.getContext("2d");
var framerate = 30;
function draw() {
if (cached_frame)
context.putImageData(cached_frame, 0, 0);
requestAnimationFrame(draw);
}
setInterval(function() {
var frame = context.getImageData(0, 0, canvas.width, canvas.height);
// Do things to manipulate frame.data.
// Save the resultant pixel data for the cached_frame.
cached_frame.data = frame.data;
}, 1000 / framerate);
draw();
如果不使用 webgl,我还能做些什么吗?
任何建议表示赞赏。泰都:D
【问题讨论】:
-
剪毛是一直在同一个位置还是随机移动?它只是一台机器,还是您尝试过的所有机器?它依赖于浏览器吗?您不应该期望任何剪切,因此我们需要更多信息来弄清楚发生了什么。
-
画布已经被双缓冲了。对于需要经常发生的任何事情(超级慢),请避免使用 putImageData 和 getImageData。通过代码创建一个新画布并绘制其结果。
-
这部分代码
setInterval(function() { cached_frame = new ImageData(new Uint8ClampedArray(pixel_data)将杀死内存。垃圾收集器将一直触发,因为每次间隔触发时您都会创建一个新的 Image 和 Uint8ClampedArray。将它们保存为变量并至少重复使用它们。 -
只是基于@ericjbasti 的优秀 cmets 的一些快速思考: 如果可能,出于性能原因避免使用
getImageData/putImageData。 rAF 将帮助您剪毛。在同一个 rAF 中执行 getImageData 和 putImageData 操作。使用自动输入draw(timestamp)的时间戳参数来执行定时活动。将requestAnimationFrame(draw)放在draw() 的底部(不是顶部)。画布本身是双缓冲的,但如果您正在展示视频,您可能需要缓冲额外的帧。 -
@markE LOL,讽刺的是我专攻计算机图形学。 :)
标签: javascript html canvas vsync