【问题标题】:Three.js project crashes mobileThree.js 项目在移动端崩溃
【发布时间】:2017-03-13 18:42:09
【问题描述】:

我一直在做一个 three.js 项目来尝试学习这个框架。有一个浮动的基本模型在桌面浏览器上运行良好,但在移动设备上会反复崩溃。我将项目上传到我的服务器http://threedeesneaker.404vanity.com/

有什么方法可以针对移动设备进行优化吗?我尝试了适用于 iPhone 和 iPad 的 chrome 和 safari。

它自己的代码:

(function() {

var scene, camera, renderer;
var geometry, material, mesh, sneaker;

init();
animate();

function init() {

    scene = new THREE.Scene();
    var WIDTH = window.innerWidth,
        HEIGHT = window.innerHeight;

        var ambient = new THREE.AmbientLight( 0x444444 );
                scene.add( ambient );

    camera = new THREE.PerspectiveCamera( 3, WIDTH / HEIGHT, 1, 20000 );
    camera.position.z = 1000;



    window.addEventListener('resize', function() {
      var WIDTH = window.innerWidth,
          HEIGHT = window.innerHeight;
      renderer.setSize(WIDTH, HEIGHT);
      camera.aspect = WIDTH / HEIGHT;
      camera.updateProjectionMatrix();
    });

    geometry = new THREE.BoxGeometry( 200, 200, 200 );
    material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );

    mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );


    // prepare loader and load the model
    var oLoader = new THREE.OBJMTLLoader();
    oLoader.load('models/sneaker.obj', 'models/sneaker.mtl', function(object) {

      object.scale.set(1, 1, 1);
      object.rotation.y = 600;
      object.rotation.z= 600;
      sneaker = object;
      scene.add(sneaker);
    });


  // var loader = new THREE.OBJLoader();
  // loader.load('models/sneaker.obj', function(object) {
  //   sneaker = object;
  //   sneaker.scale.set(1,1,1);
  //   sneaker.rotation.y = 600;
  //   sneaker.rotation.z= 600;
  //   scene.add(sneaker);

  // });





    renderer = new THREE.WebGLRenderer();
    renderer.setSize( WIDTH, HEIGHT );

    renderer.setClearColor(0x333F47, 1);


    var light = new THREE.PointLight(0xffffff);
    light.position.set(-100,200,100);
    scene.add(light);

    document.body.appendChild( renderer.domElement );

}

function animate() {

    requestAnimationFrame( animate );

    mesh.rotation.x += 0.01;
    mesh.rotation.y += 0.02;
    sneaker.rotation.x += 0.01;
    sneaker.rotation.y += 0.02;


    renderer.render( scene, camera );

}

})();

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    首先对您的 js 进行评论:在请求旋转网格之前检查渲染循环中是否有 typeof sneaker !== 'undefined',然后再加载它会产生错误。

    您的场景崩溃是因为您使用了过于详细的材质,例如,我可以看到 4096x4096 凹凸贴图。它大大增加了桌面上的帧渲染时间,这可能是页面在移动设备上无响应的原因:片段着色器计算变得太大。

    但是,完全删除您花费时间处理的那些细节将是一种耻辱。你可以做的是在你的js中添加一个设备检测器。您可以使用它在桌面和移动设备上显示两种不同的模型。

    但您还可以带来更多重要的改进。因为它们是我原始帖子的一部分,所以我让它们在那里 :) :

    1. 调整纹理大小。您正在使用两个 4.5MB 的 4096 x 4096 jpg,这很重(请注意,现在已经发布了只有 500Mo RAM 的支持 webgl 的智能手机)。此外,您几乎没有任何细节可以证明这一点。您可以更改您的 uv 以减少很多没有细节的部分,并且可能将图片大小调整为 512x512。最后,使用 JPG 压缩器,可以减轻 70-80% 的重量。根据您的图片,PNG 也可能是更好的选择。设备的 GPU 内存仍然是其他东西,如果您仍然需要提高性能,您可以在脚本中检查客户端是否支持 .pvr 或 .ktx 纹理格式,针对 GPU 内存进行了优化。

    2. 使您的可视化不适用于移动设备的一个重要问题是您有... 23 个渲染调用,因为您使用了 15 个纹理和 23 个几何图形。

    这意味着,对于每一帧,您必须在最终帧渲染之前绑定 23 个不同的几何图形。一些移动 CPU-GPU 组合每秒无法做到 60 次。不要为普通移动设备计划超过 10 个渲染调用。这意味着更少的几何形状和更少的材料。合并。

    我没有详细检查您的 .obj 文件,以了解您最终如何获得 23 个几何图形,以及 13 个纹理的来源,这取决于您。

    商店中的许多 3D 应用程序 (OpenGL) 当然有超过 23 个对象。但是商店知道应用程序,他们知道您的手机,因此他们可以完成兼容性工作并将应用程序隐藏到低端设备。

    这里是检查场景中的渲染调用、几何图形和材质的提示:在您的主函数中,设置renderer 后,在窗口对象window.renderer = renderer 中包含指向它的指针。现在在控制台运行时,一旦加载资源,输入renderer.info。它将在一个对象中返回这些数据。

    【讨论】:

    • 好总结!尤其是对于移动 GPU,有很多几何和纹理数据需要处理,尽可能减少所有这些数据应该会有很大帮助。就目前而言,它在移动设备上的表现永远不会很好。
    • 哇,谢谢。一些很棒的信息。对于第 3 点,解决这种情况的最佳方法是什么?
    • @DillonRaphael 我删除了关于 2Mo 几何的部分,它不是移动设备的限制因素。
    猜你喜欢
    • 2018-01-18
    • 2022-09-29
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 2020-05-06
    • 1970-01-01
    • 2023-04-10
    相关资源
    最近更新 更多