Three.js canvas.toDataURL有时为空

Three.js canvas.toDataURL有时为空,canvas,three.js,html5-canvas,html2canvas,Canvas,Three.js,Html5 Canvas,Html2canvas,我正在尝试使用html2canvas.js渲染一个THREE.js场景+一些叠加的HTML元素。它大多数时候都有效,但不是所有时候都有效 在失败的情况下,只呈现HTML元素(背景、覆盖等),而不呈现其他内容。3th.js场景的行为就像它是完全空的一样,即使它明显地包含数据。我可以说,它通常不适用于较大的模型,但只适用于渲染的早期。它最终在所有情况下都能工作,但更大的型号大约需要30秒。好像我必须给缓冲区一些时间来稳定 html2canvas按照您的预期处理THREE.js画布——它只是使用dra

我正在尝试使用html2canvas.js渲染一个THREE.js场景+一些叠加的HTML元素。它大多数时候都有效,但不是所有时候都有效

在失败的情况下,只呈现HTML元素(背景、覆盖等),而不呈现其他内容。3th.js场景的行为就像它是完全空的一样,即使它明显地包含数据。我可以说,它通常不适用于较大的模型,但只适用于渲染的早期。它最终在所有情况下都能工作,但更大的型号大约需要30秒。好像我必须给缓冲区一些时间来稳定

html2canvas按照您的预期处理THREE.js画布——它只是使用
drawImage
将THREE.js画布绘制到新画布上,该画布最终由库返回

否则,我会尽力确保画布上没有其他东西,就像这把小提琴:(下面的js代码)

如您所见,我正在尝试阻止渲染循环,并在想要捕获场景时再执行一次渲染。但即使是所有这些预防措施似乎也无济于事

有没有更好的方法从THREE.js画布获取图像?我可以手动完成这一部分,然后将THREE.js画布换成一张抓取的图像,刚好够html2canvas完成它的工作,然后将THREE.js画布换回来。我不希望这样做,所以如果用户创建大量快照(图像资源,到处都是图像资源…),我不会弄乱DOM

不管怎样,这是代码。欢迎提出任何意见或建议。谢谢

var hostDiv、场景、渲染器、摄影机、根、控件、灯光、形状、θ、aniLoopId、动画;
函数snap(){
动画=假;
取消动画帧(aniLoopId);
渲染器。渲染(场景、摄影机);
//html2canvas版本:
/*
var元素=document.getElementById('scenePlusOverlays');
//输入按钮代表我的覆盖图
html2canvas(元素、函数(画布){
//我会将返回的画布转换为PNG
动画=真;
制作动画();
});
*/
//这基本上就是html2canvas对THREE.js画布所做的。
var c=document.getElementById('renderCanvas');
var toC=document.createElement('canvas');
toC.宽度=c.宽度;
toC高度=c高度;
var toCtx=toC.getContext('2d');
toCtx.drawImage(c,0,0);
log(toC.toDataURL('image/png');
动画=真;
制作动画();
}
函数addGeometry(){
//var geo=新的三箱几何体(1,1,1);
var geo=新的三种球墨法(5,32,32);
var beo=new THREE.BufferGeometry().fromGeometry(geo);
geo.dispose();
geo=null;
var mat=新的3.MeshPhongMaterial({color:'red'});
var-msh;
var计数=10;
计数/=2;
var i=20;
var topLayer=new THREE.Object3D();
变量zLayer、xLayer、yLayer;
for(var Z=-count;Z
编辑: 以所描述的方式调用readPixels或toDataURL是可能的——我曾考虑过一种类似的方法来获取缓冲区,但由于所需的异步代码数量太多而推迟了。大概是这样的:

var global_callback = null;
function snapshot_method() {
   global_callback = function(returned_image) {
      // do something with the image
   }
}
// ...
function render() {
   renderer.render();
   if(global_callback !== null) {
      global_callback(renderer.domElement.toDataURL());
      global_callback = null;
   }
} 
(为了未来谷歌的利益):实例化
WebGLRenderer
时,需要将
preserveDrawingBuffer
设置为
true

renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });
(原始代码有这个,但有一个打字错误)。这是必需的,因为默认情况下,WebGL不需要浏览器在每个绘图帧后保存深度/颜色缓冲区,因此如果要使用
readPixels
toDataURL
,则需要显式告诉实现使用该标志保存图形缓冲区

但是,这样做会带来性能损失;:

虽然有时需要保留图形缓冲区,但它可以 在某些平台上造成严重的性能损失。无论何时 可能此标志应保持为假,并使用其他技术。 同步绘图缓冲区访问(例如调用 readPixels或toDataURL在呈现给 图形缓冲区)可用于获取图形缓冲区的内容。 如果作者需要在系列上渲染到同一图形缓冲区 对于调用,可以使用帧缓冲区对象

我不确定这两个建议中的哪一个