简体   繁体   English

Three.js 项目导致手机崩溃

[英]Three.js project crashes mobile

I've been working on a three.js project to try and learn the framework.我一直在研究一个 Three.js 项目来尝试学习这个框架。 Got a basic model floating around that works fine on the desktop browser but will crash repeatedly on mobile.有一个浮动的基本模型,它在桌面浏览器上运行良好,但在移动设备上会反复崩溃。 I uploaded the project on my server http://threedeesneaker.404vanity.com/我将项目上传到我的服务器http://threedeesneaker.404vanity.com/

Is there any way to optimize this for mobile devices?有没有办法为移动设备优化这个? I tried both chrome and safari for iPhone and iPad.我为 iPhone 和 iPad 尝试了 chrome 和 safari。

The code it self:它自己的代码:

(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 );

}

})();

First a comment on your js : check if typeof sneaker !== 'undefined' in your render loop before asking to rotate your mesh, before loading it generates errors.首先对您的 js 发表评论:在要求旋转网格之前检查渲染循环中的typeof sneaker !== 'undefined' ,然后加载它会产生错误。

Your scene crashes because you are using too detailed materials, I can see a 4096x4096 bump map for instance.你的场景崩溃是因为你使用了太详细的材料,例如我可以看到一个 4096x4096 的凹凸贴图。 It strongly increases frame rendering time on desktop and is probably the reason why the page is irresponsive on mobile : the fragment shader computations become too big.它极大地增加了桌面上的帧渲染时间,这可能是页面在移动设备上无响应的原因:片段着色器计算变得太大。

However it would be a shame to completly delete those details you spent time on.但是,完全删除您花时间处理的那些细节将是一种耻辱。 What you can do is to add a device detector in your js.你可以做的是在你的js中添加一个设备检测器。 You can use that to display two different models on desktop and on mobile.您可以使用它在桌面和移动设备上显示两种不同的模型。

But there are further important improvements you can bring.但是,您还可以带来进一步的重要改进。 As they are part of my original post I let them there :) :因为它们是我原帖的一部分,所以我让它们在那里:):

  1. Resize your textures.调整纹理的大小。 You are using two 4096 x 4096 jpg of 4.5MB, this is heavy (note that there are webgl-enabled smartphones with only 500Mo RAM that get realeased these days).您正在使用两个 4.5MB 的 4096 x 4096 jpg,这很重(请注意,这些天有一些支持 webgl 的智能手机只有500Mo RAM)。 Moreover you have very few details that justifies it.此外,您几乎没有什么细节可以证明这一点。 You could change your uv to reduce a lot the parts with no details, and probably resize the picture to 512x512.您可以更改 uv 以减少很多没有细节的部分,并且可能将图片大小调整为 512x512。 Finally, use a JPG compressor that will reduce the weight by 70-80%.最后,使用 JPG 压缩器,将重量减轻 70-80%。 Depending on your picture PNG can be a better choice also.根据您的图片,PNG 也可能是更好的选择。 The device's GPU memory is still something else, and if you still need to improve performance you can check in the script if the client supports .pvr or .ktx texture formats, optimized for GPU memory.设备的 GPU 内存仍然是其他东西,如果您仍然需要提高性能,您可以在脚本中检查客户端是否支持 .pvr 或 .ktx 纹理格式,针对 GPU 内存进行了优化。

  2. An important problem that makes your visualization unappropriate for mobile devices is that you have ... 23 render calls, because you are using 15 textures and 23 geometries.使您的可视化不适用于移动设备的一个重要问题是您有 ... 23 次渲染调用,因为您使用了 15 个纹理和 23 个几何图形。

What it means is that, for each frame, you will have to bind 23 different geometries before the final frame renders.这意味着,对于每一帧,您必须在最终帧渲染之前绑定 23 个不同的几何图形。 Some mobile CPU-GPU couples cannot do that 60 times per second.一些移动 CPU-GPU 组合不能每秒执行 60 次。 Don't plan more than 10 render calls for average mobile devices.对于普通移动设备,不要计划超过 10 个渲染调用。 That means less geometries with less materials.这意味着更少的几何形状和更少的材料。 Merge.合并。

I have not inspected your .obj file in detail to understand how you get 23 geometries in the end, neither where your 13 textures come from, up to you.我没有详细检查您的 .obj 文件以了解您最终是如何获得 23 个几何图形的,您的 13 个纹理来自哪里,由您决定。

A lot of 3D apps (OpenGL) on the stores have more than 23 objects of course.商店中的许多 3D 应用程序(OpenGL)当然有超过 23 个对象。 But stores know the apps and they know your phone so they can do the compatibility job and hide the app to low devices.但是商店知道应用程序并且他们知道您的手机,因此他们可以执行兼容性工作并将应用程序隐藏到低设备。

Here is the tip to check your render calls, geometries and materials in the scene : in your main function, after having set the renderer , include a pointer to it in the window object window.renderer = renderer .这是检查场景中渲染调用、几何图形和材质的提示:在主函数中,设置renderer ,在窗口对象window.renderer = renderer包含指向它的指针。 Now at runtime in your console, once resources have been loaded, type renderer.info .现在在你的控制台运行时,一旦资源被加载,输入renderer.info It will return those data in an object.它将在对象中返回这些数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM