这个问题可能很奇怪,但假设我们有一个画布,例如绘制一些像这个实验这样的 3D 内容。
不考虑使用 ThreeJS、Babylon 或任何其他库来实现相同的效果,是否可以设置一些间隔来复制每个体素的诞生并在以后重复(重绘)它。
只是我想记录画布绘制过程并重播它,而不使用 RTC 、视频或图像序列。
做了什么?
我一直在尝试使用WebGl Context 和Stream Capture,但不幸的是无法达到预期的结果。
有人能帮忙吗?
这个问题可能很奇怪,但假设我们有一个画布,例如绘制一些像这个实验这样的 3D 内容。
不考虑使用 ThreeJS、Babylon 或任何其他库来实现相同的效果,是否可以设置一些间隔来复制每个体素的诞生并在以后重复(重绘)它。
只是我想记录画布绘制过程并重播它,而不使用 RTC 、视频或图像序列。
做了什么?
我一直在尝试使用WebGl Context 和Stream Capture,但不幸的是无法达到预期的结果。
有人能帮忙吗?
我不知道您是如何尝试使用该captureStream
方法的,但在您的示例页面上,此代码确实有效。
let s = mycanvas.captureStream(),
r = new MediaRecorder(s),
chunks = [];
r.ondataavailable = e => chunks.push(e.data);
r.onstop = e => {
let videoURL = URL.createObjectURL(new Blob(chunks));
doSomethingWith(videoURL);
};
r.start();
setTimeout(_=>r.stop(), 3000); // records 3 seconds
现在您已经有了一个指向画布记录的有效 blobURL,您可以在一个<video>
元素中播放它,然后在您的 webgl 上下文中绘制它。
您可以包装 WebGL 上下文并捕获所有函数调用。包装 WebGL 上下文的示例类似于
const rawgl = document.querySelector("canvas").getContext("webgl");
const gl = wrapContext(rawgl);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.enable(gl.SCISSOR_TEST);
gl.scissor(40, 50, 200, 60);
gl.clearColor(0,1,1,1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.scissor(60, 40, 70, 90);
gl.clearColor(1,0,1,1);
gl.clear(gl.COLOR_BUFFER_BIT);
function wrapContext(gl) {
const wrapper = {};
for (let name in gl) {
var prop = gl[name];
if (typeof(prop) === 'function') {
wrapper[name] = wrapFunction(gl, name, prop);
} else {
wrapProperty(wrapper, gl, name);
}
}
return wrapper;
}
function wrapFunction(gl, name, origFn) {
// return a function that logs the call and then calls the original func
return function(...args) {
log(`gl.${name}(${[...args].join(", ")});`);
origFn.apply(gl, arguments);
};
}
function wrapProperty(wrapper, gl, name) {
// make a getter because these values are dynamic
Object.defineProperty(wrapper, name, {
enumerable: true,
get: function() {
return gl[name];
},
});
}
function log(...args) {
const elem = document.createElement("pre");
elem.textContent = [...args].join(" ");
document.body.appendChild(elem);
}
canvas { border: 1px solid black; }
pre { margin: 0; }
<canvas></canvas>
在您的情况下,您不会记录调用,而是将它们添加到仅在您想要捕获的帧上的一些调用数组中。
然后,您需要以某种方式跟踪所有资源(缓冲区、纹理帧缓冲区、渲染缓冲区、着色器、程序)及其所有参数(如纹理上的过滤设置),您还需要跟踪统一设置等。
WebGL-Inspector可以做到这一点并且可以播放帧,所以它可能是一个很好的例子。还有这个webgl-capture库。
您需要为程序捕获的内容取决于您的程序。例如,如果您知道缓冲区和纹理永远不会改变,并且当您想要播放时它们仍在内存中,那么您可能不需要尝试捕获上述两个示例都必须执行的缓冲区和纹理的状态。