gpt4 book ai didi

javascript - HTML5 Canvas 与 requestAnimationFrame 撕裂

转载 作者:可可西里 更新时间:2023-11-01 13:03:43 29 4
gpt4 key购买 nike

更新:这整个问题最终成为系统图形驱动程序的问题,而不是(看似)浏览器/API 问题。撕裂的框架归结为实际的显示更新。再次感谢那些参与讨论并试图提供帮助的人。


我的页面使用 Canvas 和 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

最佳答案

我不认为代码在做你认为它在做的事情

首先,据我所知,您不能将新数据分配给 ImageData,所以这一行

cached_frame.data = frame.data;

什么都不做。我们可以测试显示它不起作用的东西

var ctx = document.createElement("canvas").getContext("2d");
document.body.appendChild(ctx.canvas);

var imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
var data = new Uint8ClampedArray(imageData.length);

// fill imageData.data with red
fillWithColor(255, 0, 0, 255, imageData.data);

// fill data with green
fillWithColor(0, 255, 0, 255, data);

// assign imageData.data to data
imageData.data = data;

// Draw. If assigning imageData.data works result will
// be green, if not result will be red
ctx.putImageData(imageData, 0, 0);

function fillWithColor(r, g, b, a, dst) {
for (ii = 0; ii < dst.length; ii += 4) {
dst[ii + 0] = r;
dst[ii + 1] = g;
dst[ii + 2] = b;
dst[ii + 3] = a;
}
}
  

其次,您的 draw 函数正在连续绘制,至少从您发布的代码来看 cached_frame 设置在第 2 行,因此它始终为真并且始终为正在画画。如果您以某种方式部分更新 cached_frame 中的实际数据,那么它将在只有部分结果时绘制。

我想你想要这样的东西

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var frame;
var framerate = 30;

function draw() {
context.putImageData(frame, 0, 0);
}

setInterval(function() {
frame = context.getImageData(0, 0, canvas.width, canvas.height);

// Do things to manipulate frame.data

// frame is ready, draw it at next rAF
requestAnimationFrame(draw);
}, 1000 / framerate);

如果您认为解码比 raf 更快,您可能想检查抽奖是否已经排队。不过,我认为在这种情况下您实际上不需要 rAF。我很确定您可以在 setInterval 结束时绘制,它会显示下一帧,不会撕裂。

这是一个测试,它对我来说不是撕裂。

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var frame;
var framerate = 30;
var frameCount = 0;

setInterval(function() {
++frameCount;
frame = context.getImageData(0, 0, canvas.width, canvas.height);
var data = frame.data;
var width = frame.width;
var height = frame.height;
// Do things to manipulate frame.data
for (var yy = 0; yy < height; ++yy) {
for (var xx = 0; xx < width; ++xx) {
var offset = (yy * width + xx) * 4;
data[offset + 0] = ((xx >> 2 & 0x1) ^ frameCount & 0x1) ? 255 : 0;
data[offset + 3] = 255;
}
}

// frame is ready, draw it at next rAF
context.putImageData(frame, 0, 0);
}, 1000 / framerate);
<canvas id="canvas" width="1280" height="720"></canvas>

关于javascript - HTML5 Canvas 与 requestAnimationFrame 撕裂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35645278/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com