Three.js canvas.toDataURL 有时为空

2024-05-10

我正在尝试使用 html2canvas.js 渲染 THREE.js 场景 + 一些覆盖的 HTML 元素。有用大多数时候,但并非一直如此。

在失败的情况下,将渲染 HTML 元素(背景、覆盖层等),但不会渲染其他元素。 THREE.js 场景表现得好像完全是空的,尽管它明显包含数据。我可以说,对于较大的模型,它通常会失败,但只是在渲染的早期阶段。确实如此最终在所有情况下都有效,但较大的模型大约需要 30 秒。就好像我必须给缓冲区一些时间来稳定。

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

否则,我会尝试确保画布上没有其他东西忙碌,就像这个小提琴一样:http://jsfiddle.net/TheJim01/k6dto5sk/63/ http://jsfiddle.net/TheJim01/k6dto5sk/63/(下面是js代码)

正如您所看到的,我做了很多工作来尝试阻止渲染循环,并在我想要捕获场景时再执行一次渲染。但即使所有这些预防措施似乎也没有帮助。

有没有更好的方法从 THREE.js 画布中获取图像?我可以手动完成该部分,然后将 THREE.js 画布换成足够长的时间,以便 html2canvas 完成其工作,然后将 THREE.js 画布换回。我不想这样做,所以如果用户制作大量快照(图像资源、到处都是图像资源......),我不会弄乱 DOM。

无论如何,这是代码。欢迎任何想法或建议。谢谢!

var hostDiv, scene, renderer, camera, root, controls, light, shape, theta, aniLoopId, animating;
function snap() {
    animating = false;
    cancelAnimationFrame(aniLoopId);
    renderer.render(scene, camera);

    // html2canvas version:
    /*
    var element = document.getElementById('scenePlusOverlays');
    // the input buttons represent my overlays
    html2canvas( element, function(canvas) {
        // I'd convert the returned canvas to a PNG
        animating = true;
        animate();
    });
    */

    // This is basically what html2canvas does with the THREE.js canvas.
    var c = document.getElementById('rendererCanvas');
    var toC = document.createElement('canvas');
    toC.width = c.width;
    toC.height = c.height;
    var toCtx = toC.getContext('2d');
    toCtx.drawImage(c, 0, 0);
    console.log(toC.toDataURL('image/png'));
    animating = true;
    animate();
}
function addGeometry() {
    //var geo = new THREE.BoxGeometry(1, 1, 1);
    var geo = new THREE.SphereGeometry(5, 32, 32);
    var beo = new THREE.BufferGeometry().fromGeometry(geo);
    geo.dispose();
    geo = null;
    var mat = new THREE.MeshPhongMaterial({color:'red'});
    var msh;

    var count = 10;
    count /= 2;
    var i = 20;
    var topLayer = new THREE.Object3D();
    var zLayer, xLayer, yLayer;
    for(var Z = -count; Z < count; Z++){
        zLayer = new THREE.Object3D();
        for(var X = -count; X < count; X++){
            xLayer = new THREE.Object3D();
            for(var Y = -count; Y < count; Y++){
                yLayer = new THREE.Object3D();
                msh = new THREE.Mesh(beo, mat);
                yLayer.add(msh);
                msh.position.set((X*i)+(i/2), (Y*i)+(i/2), (Z*i)+(i/2));
                xLayer.add(yLayer);
            }
            zLayer.add(xLayer);
        }
        topLayer.add(zLayer);
    }
    scene.add(topLayer);
}
var WIDTH = '500';//window.innerWidth,
    HEIGHT = '500';//window.innerHeight,
    FOV = 35,
    NEAR = 0.1,
    FAR = 10000;

function init() {
    hostDiv = document.getElementById('hostDiv');
    document.body.insertBefore(hostDiv, document.body.firstElementChild);

    renderer = new THREE.WebGLRenderer({ antialias: true, preserverDrawingBuffer: true });
    renderer.setSize(WIDTH, HEIGHT);
    renderer.domElement.setAttribute('id', 'rendererCanvas');
    hostDiv.appendChild(renderer.domElement);

    camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
    camera.position.z = 500;

    controls = new THREE.TrackballControls(camera, renderer.domElement);

    light = new THREE.PointLight(0xffffff, 1, Infinity);
    light.position.copy(camera.position);

    scene = new THREE.Scene();
    scene.add(camera);
    scene.add(light);

    animating = true;
    animate();
}

function animate() {
    if(animating){
        light.position.copy(camera.position);
        aniLoopId = requestAnimationFrame(animate);    
    }
    renderer.render(scene, camera);
    controls.update();
}

EDIT:以所描述的方式调用 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;
   }
} 

(为了未来的 Google 员工的利益):您需要设置preserveDrawingBuffer to true当你实例化时WebGLRenderer:

renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });

(原始代码有这个,但有一个错字)。这是必需的,因为默认情况下,WebGL 不要求浏览器在每个绘图帧之后保存深度/颜色缓冲区,因此如果您想使用readPixels or toDataURL,您需要明确告诉实现使用该标志保存绘图缓冲区。

然而,这样做会降低性能;如果这对您来说是个问题,该规范提供了一些指导 https://www.khronos.org/registry/webgl/specs/1.0.1/#2.2:

虽然有时需要保留绘图缓冲区,但它可以 在某些平台上导致显着的性能损失。每当 可能此标志应保持为 false 并使用其他技术。 同步绘图缓冲区访问等技术(例如,调用 readPixels 或 toDataURL 在渲染到的同一函数中 绘图缓冲区)可用于获取绘图缓冲区的内容。 如果作者需要在一系列上渲染到同一个绘图缓冲区 调用时,可以使用帧缓冲区对象。

我不确定这些建议在当前版本的 Three.js (r68) 中是否可行,但还有另一种替代解决方案(调用readPixels or toDataURL在画布的副本上)讨论了其他几个问题(为什么我的画布在转换为图像后变成空白? https://stackoverflow.com/questions/12538193/why-does-my-canvas-go-blank-after-converting-to-image , 如何从 Three.js 画布保存图像? https://stackoverflow.com/questions/15558418/how-do-you-save-an-image-from-a-three-js-canvas).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Three.js canvas.toDataURL 有时为空 的相关文章

  • 将 css 背景设置为本地存储中的图像

    我希望将 base64 格式的图像存储在密钥中的本地存储中ImgStorage在CSS背景中像这样 data image png base64 iVBORw0KGgoAAAANS 到目前为止 我尝试了两种方法 1 从存储加载并放入css标签
  • 在 TypeScript 中使用三个 Js + OrbitControl

    我无法得到this http www example com 在 TypeScript 中使用上述组合的示例 I have and 在我的html中和打字稿文件
  • 如何检测形状是否被单击(HTML5 画布)?

    我正在使用画布绘制不同的形状 如矩形 三角形 六边形等lineTo方法如这个博客 http blog riacode in 2011 03 03 drawing regular polygons in html5 canvas 我只是想要一
  • HTML5 - 创建画布视口

    我有一个 2D 数组 宽 30 下 20 然而 视口仅绘制横向 15 和向下 10 的内容 我最初有一个这样的游戏 我一直在努力实现这样的目标 这是我的小提琴 http jsfiddle net sTr7q http jsfiddle ne
  • HTML5 Canvas 避免任何子像素渲染

    As seen here https stackoverflow com questions 7017998 html 5 canvas avoid fill behaviour on overlap我在画布中的亚像素精度方面遇到了一些问题
  • 尝试使用掩码裁剪位图会抛出 IllegalArgumentException:

    我正在使用以下代码 public void cropSelection Bitmap bitmap annotationBitmap copy annotationBitmap getConfig true Canvas canvas ne
  • Three.js canvas.toDataURL 有时为空

    我正在尝试使用 html2canvas js 渲染 THREE js 场景 一些覆盖的 HTML 元素 有用大多数时候 但并非一直如此 在失败的情况下 将渲染 HTML 元素 背景 覆盖层等 但不会渲染其他元素 THREE js 场景表现得
  • 如何始终将焦点保持在画布上?

    我一直在这个论坛寻找解决方案 但尚未找到 无论我在页面上的哪个位置单击 我都需要始终将焦点放在画布元素上 我有几个按钮 在每个 onclick 事件中我写 document getElementById canvas focus 这确实有效
  • 是否可以像 html 视频元素一样将流作为源添加到 html canvas 元素?

    根据MDN The HTMLMediaElement https developer mozilla org en US docs Web API HTMLMediaElement界面添加到HTMLElement属性 支持基本媒体相关功能所
  • 三-mtl-loader 错误:THREE.MeshPhongMaterial:.shading 已被删除 -> 对象不可见

    昨天我问了这个问题 未捕获的类型错误 THREE MTLLoader 不是构造函数 2 0 https stackoverflow com questions 47741644 uncaught typeerror three mtlloa
  • JavaScript 原型继承和 html canvas

    我是一名 Ruby 开发人员 最终决定认真学习 JavaScript 所以我买了一些书 开始深入研究 但当我试图理解原型继承时 我很快就陷入了困境 这本书的例子之一如下 给定一个 Shape 其原型有一个绘制方法 以及两个子形状 一个 Tr
  • 为什么对于大于 65776 像素的画布源,drawImage 性能差异很大

    我在 jsperf 上写了一些与以下相关的测试用例 1 在屏幕外画布上绘图 2 将图像绘制到屏幕画布上 我发现如果源画布中的像素数 无论 dst 小于 65776 像素 性能会高得多 我预计这个性能限制是 65536 像素 如果有的话 He
  • 如何在css3中制作曲线风格的菜单?

    是否可以用css3制作曲线 圆弧样式的菜单 我可以使用canvas或HTML5中的其他东西来实现这一点吗 预先感谢 洛根 不幸的是 我不知道有什么优雅的解决方案 特别是当涉及到菜单项时 但弧线本身应该可以在纯 css 和几个 html 元素
  • 三.js环境光意想不到的效果

    在下面的代码中 我渲染了一些立方体并使用点光源和环境光照亮它们 然而 当设置为 0xffffff 时 AmbientLight 会将侧面的颜色更改为白色 无论其指定的颜色如何 奇怪的是 点光源按预期工作 我怎样才能使环境光表现得像点光 因为
  • 有没有办法从画布上清除一个元素而不消除其他元素?

    我正在使用画布构建页面加载器 并使用 es6 类 虽然目前我无法使其正常工作 原因之一是我找不到清除画布的方法进展 到目前为止 这是我的代码 class Loader constructor width height this width
  • 在 Three.js 中从 Web Worker 加载纹理

    当将大纹理图像应用到网格上一段明显的时间时 Three js 会锁定浏览器的主线程 让我们考虑以下示例 var texLoader new THREE TextureLoader texLoader load someLargeTextur
  • 如何在react-三纤维中提取并播放动画

    嗯 我有 gltf 动画模型 我成功加载模型 但无法播放嵌入的动画 我想知道是否可以以任何方式解决它 顺便说一句 我正在反应中工作 先感谢您 在这里您可以找到型号https drive google com file d 1ZVyklaQu
  • Arbor Js - 节点 Onclick?

    我在用着arbor js http arborjs org 创建图表 我如何创建一个onclick节点的事件 或者在单击时在某处创建节点链接 Arborjs org 主页的节点在单击时链接到外部页面 我如何复制它 或者使节点在单击时调用 j
  • 在 HTML5 中创建可拖动和可缩放的网格

    与其他 HTML5 不同如何创建网格问题 我想知道如何制作一个可拖动且可扩展的 绘制网格非常简单 var c document getElementById canvas var ctx c getContext 2d var width
  • 将 visjs 网络导出为 jpeg/png 图像

    我正在研究 Angular vis js Vis js 在画布上工作 用于创建节点和节点之间的链接 有没有办法从 visj s 画布中获取图像 jpeg png 看看这个片段 我想它会对你有所帮助 在 vis 画布下 您将看到一个 PNG

随机推荐

  • iOS7 无法隐藏状态栏

    我刚刚将我的 iPhone 5 iOS 7 升级到了四个测试版 现在 当我在这台 iPhone 上通过 Xcode 5 运行我的应用程序时 状态栏不会隐藏 尽管它应该隐藏 不工作 UIApplication sharedApplicatio
  • Dart 包的条件导入/代码

    有没有办法根据 Dart 中的环境标志或目标平台有条件地导入库 代码 我正在尝试在两者之间切换dart io的 ZLibDecoder ZLibEncoder 类和基于目标平台的 zlib js 有一篇文章介绍了如何创建统一的界面 http
  • 如何生成随机凸多边形?

    我正在尝试设计一种生成随机二维凸多边形的方法 它必须具有以下属性 坐标应该是整数 多边形应位于角为 0 0 和 C C 的正方形内 其中 C 已给出 多边形的顶点数量应接近给定数量 N 例如 生成具有 10 个顶点并位于正方形 0 100
  • 使用 Ruby CSV 标头转换器

    假设我有以下课程 class Buyer lt ActiveRecord Base attr accesible first name last name 以及 CSV 文件中的以下内容 First Name Last Name John
  • 使用 ClosedXML 附加到 excel 文件

    我需要将新数据附加到使用 ClosedXML 创建的现有 Excel 文件中 如何使用 ClosedXML 附加到 Excel 文件 如何获取最后一条记录的行号并将其附加到该行号上 或者还有其他内容 Thanks 打开现有工作簿 然后使用L
  • 有没有办法模拟小部件或屏幕特定位置的触摸?

    我想触摸或点击小部件上的某处 而不让用户在此时明确触摸屏幕 有什么办法可以做到吗 我已经检查了SO答案 有些人建议使用 集成测试 但在未物理或以某种方式连接到笔记本电脑的设备上无法执行 集成测试 无法找到更好的措辞 我还尝试进行 hitTe
  • Scikit Learn - K-Means - 肘部 - 标准

    今天我想学习一些关于 K means 的知识 我已经了解该算法并且知道它是如何工作的 现在我正在寻找正确的 k 我发现肘部准则作为检测正确的 k 的方法 但我不明白如何将它与 scikit learn 一起使用 在 scikit learn
  • 防止 Windows 中的崩溃消息

    我的应用程序需要扫描经常导致崩溃的第三方文件 为了克服这个问题 它使用一个单独的进程来扫描这些文件并 每当这个进程崩溃时 我的应用程序就会实例化另一个应用程序 我的问题是 每次崩溃后我都会收到 Windows 崩溃消息 AuxScanner
  • Kotlin 中是否有类似于 #region #endregion 的语法?

    我知道我可以使用 region endregion 包围 C 中的代码片段 Kotlin 中是否有类似的语法 谢谢 region MyRegion protected void Page Load object sender EventAr
  • sql查询连接两个服务器中不同数据库的两个表

    我在 ServerS 上的数据库中有两个表 tableA 在 ServerB 上的数据库中有两个表 我只想根据这些表的公共字段名对这些表执行 fullouter join 在 SQL Server 中 您可以创建一个链接服务器 在 Mana
  • 为什么在尝试使用 Java 连接到 RDS PostgreSQL 数据库时会收到 SocketTimeoutException?

    我有一个 Spring 应用程序 我试图在 AWS 上托管 几天来我一直在努力配置 我有一个 EC2 实例 并且能够通过 SSH 连接到它 我还在 AWS 中设置了 Postgres RDS 数据库 但我无法使用 IDE 中的代码连接到它
  • Sentry 与 @sentry/webpack-plugin 和 heroku

    我正在使用 webpack 来构建我的应用程序 它可以在本地使用 sentry webpack plugin 它自动生成版本并将源映射上传到 Sentry 但是 如果我尝试在 Heroku 上构建相同的应用程序 则会出现以下错误 Error
  • 向伪 shell (pty) 发出命令

    我尝试使用 subprocess popen os spawn 来运行进程 但似乎需要伪终端 import pty master slave pty openpty os write master ls l 应该发送 ls l 到从属终端
  • 哪个更快?按引用传递与按值传递 C++

    我认为按引用传递应该比按值传递更快 因为计算机不复制数据 它只是指向数据的地址 但是 请考虑以下 C 代码 include
  • 指向 VLA 的指针

    你可能知道 VLA 的优点和缺点 https stackoverflow com a 3082302 1606345在 C11 中它们是可选的 我认为使 VLA 成为可选的主要原因是 堆栈可能会爆炸 int arr n where n 10
  • 如何表示类的实例与将其作为输入的类之间的关系?

    我有一堂课叫House 这个类的实例是house class House def init self height length self height height self length length def housePlan hou
  • Bazel:将编译标志添加到默认 C++ 工具链

    我想向默认的 C 工具链添加一些编译器和链接器标志 以便我构建的所有目标 本地或导入 共享它们 我知道可以定义我自己的工具链 但我不想这样做 因为它非常复杂且容易出错 理想情况下我想要这样的东西 cc toolchain cc defaul
  • 在 Swift 中使用 Obj-C 完成块

    在 Objective C 中 我有一个完成块类定义为 File h typedef void MYCompletionBlock BOOL success NSDictionary result NSError error 然后 在 Sw
  • dask allocate() 或 apply() 中的变量列名

    我有适用于pandas 但我在将其转换为使用时遇到问题dask 有一个部分解决方案here https stackoverflow com questions 32363114 how do i change rows and column
  • Three.js canvas.toDataURL 有时为空

    我正在尝试使用 html2canvas js 渲染 THREE js 场景 一些覆盖的 HTML 元素 有用大多数时候 但并非一直如此 在失败的情况下 将渲染 HTML 元素 背景 覆盖层等 但不会渲染其他元素 THREE js 场景表现得