Mobile devices experience crashes when running Three.js projects

I've been experimenting with a three.js project to delve into the framework. I successfully created a basic model that functions well on desktop browsers but crashes when accessed on mobile devices. You can view the project on my server

Is there any way to optimize this for mobile usage? I tested it on both Chrome and Safari for iPhone and iPad.

Here is the code snippet:

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

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

})();

Answer №1

Before we dive into the details of your code, I want to point out a crucial aspect in your JavaScript: make sure to check typeof sneaker !== 'undefined' in your render loop before attempting to rotate your mesh. Failing to do so can lead to errors during loading.

The reason your scene is crashing is due to overly detailed materials, such as a 4096x4096 bump map. These high-resolution textures significantly slow down frame rendering on desktop and cause unresponsiveness on mobile devices due to excessive fragment shader computations.

While it's important not to completely eliminate these intricate details you worked hard on, consider implementing a device detector in your JavaScript. This way, you can display different models based on whether the user is accessing the site from a desktop or mobile device.

Beyond this, there are additional enhancements you can make, which were mentioned in my original post:

  1. Resize your textures to optimize performance. Currently, using two 4096 x 4096 jpg files totaling 4.5MB each is resource-intensive, especially for devices with limited RAM. By reducing the image size to 512x512 and compressing the file, you can significantly decrease loading times. Consider using PNG format if necessary and explore .pvr or .ktx texture formats for better GPU memory utilization.

  2. An issue affecting mobile device compatibility is the excessive number of render calls (23) arising from multiple textures and geometries (15). Aim to minimize render calls to less than 10 for smoother performance on average mobile devices by consolidating geometries and simplifying materials.

I have not examined your .obj file in depth to assess how you ended up with 23 geometries or where the 13 textures originated from—this requires further investigation on your end.

In comparison, many 3D apps found in app stores incorporate more complex elements than what you currently have. However, store platforms possess the capability to filter out incompatible apps based on device specifications.

To analyze your render calls, geometries, and materials within the scene, add a reference to the renderer object in your main function like so: window.renderer = renderer. Then, during runtime, access the console and type renderer.info to retrieve these metrics in an object format.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Dynamically resizable overlapping divs in CSS

Encountering an issue with a div element on a webpage. When resizing the browser page in Chrome, the div overlaps other elements and part of it is hidden. However, in IE, the height:auto property behaves as expected without any overlapping. I have attempte ...

I tried moving the onchange(this) function from HTML to JavaScript, but I seem to have missed a parameter. The code ends

I'm currently building a website for a fictional ice cream shop to enhance my JavaScript skills. function hideAAndB() { var pickupDiv = document.getElementById("pickupDiv"); var deliveryDiv = document.getElementById("deliveryDiv"); pickupDi ...

Tips for showing form values in pop-up boxes based on their unique identifiers

I am experiencing an issue with displaying posted values in a pop-up box. Specifically, when I click on "Book now", it only shows one set of id values for all entries. For example, if I click on the 1st row's "Book now" button, it displays the values ...

Understanding how to monitor a Boolean value that fluctuates in real-time within a three.js

Currently, I am working on developing a 3D 4x4x4 tic tac toe game using three.js. In order to determine the win condition for combinations, I have created a boolean array. With a total of 64 blocks (16*4), I have initialized a boolean array of size 64 with ...

Trigger a function using ng-click and only execute the second function if the condition is met

Currently in the process of validating a form with a function called "myFunction". <button class="btn btn-lg btn-primary btn-block" type="submit" ng-click='form.$valid && myFunction()'>SEND</button> The function should only ...

Guidelines on navigating a blank page using the Nuxt-js method

I have run into an issue in my Nuxt.js project where I need to open a link in a new target when a user clicks a button. Despite trying various solutions, I haven't been able to find a workaround within the Nuxt.js framework itself. <a :href=&qu ...

"Debunking the Misconceptions of Syntax Errors in Visual

Every time I utilize the @ sign in a Razor page, like this: <script type="text/javascript"> if( @(ProjectName.NameSpace.booleanVariable) ) { doStuff(); } </script> I end up with syntax error alerts all over, which disappear after conversi ...

Is there a way to upload several documents in just one writing?

Can anyone advise me on how to add multiple documents to my Firestore collection using just one write operation? I have over 20,000 records and I'm looking for a cost-effective solution. Is there a way to add multiple docs in a single write? Apprecia ...

Is it possible to only set style.marginLeft one time?

My navigation menu is positioned off-screen to the right, and I am able to hide it by adjusting the style.marginLeft property. However, when I try to reveal it by setting the property again, nothing happens. function navroll(state) { if(state == true) ...

unable to comprehend the remaining section

My divs are not checking/unchecking properly. The else part of my code is unable to read it and displays 'undefined'. Please assist me... (The first click works correctly but the second click shows 'undefined') import React, { useState ...

Delete a filename in Internet Explorer with the power of JavaScript and jQuery

In my attempts to clear the file input field in IE using $('#files').val('');, I found that it was not effective. $('#uploadimgdiv').html(''); var fil1 = document.getElementById("files"); $('#fil1').val(&a ...

show a feature through exporting in a react component

I'm currently learning React by tackling a problem in React. Below is the React code challenge I'm working on. However, I encountered an error in the browser that I couldn't resolve even after searching on Google. I've included my code ...

Steps for launching Angular 5 application using Node.js server

I have developed an Angular 5 application that retrieves data from a node.js server. I successfully deployed the application to my web server hosted by FastComet, which supports node.js, but unfortunately, the server does not seem to be functioning properl ...

Sequelize: Establishing multiple connections

Currently working with Sequelize in Node, I have two tables named User and Auth: User id name Auth: id token My goal is to establish relationships between these models. A User can possess multiple Auth entries, forming a to-many relati ...

Retrieve data from multiple tables using knex.js

I am trying to use Express.js and knex.js to render data from two tables using only one GET function. I have successfully queried each table individually (schools or students), but I am unsure how to query both at the same time. Any ideas? app.get('/ ...

Is it possible to update the state of a specific object by utilizing dynamic form handling techniques?

Trying to dynamically accept state changes from a medium-sized form without hard coding each input's name poses a challenge. The issue lies in the fact that the state consists of diverse categories, such as: this.state = { data: { account: { ...

A guide to troubleshoot and resolve the 500 (Internal Server Error) encountered during an Ajax post request in Laravel

I am facing an issue in my project where I am trying to store data into a database using ajax. However, when I submit the post request, I get an error (500 Internal Server Error). I have tried searching on Google multiple times but the issue remains unreso ...

an observable with an empty array inside

I am working with a ko.observable that holds an object containing three arrays structured like this: self.filter({ file: [], site: [], statut: [] })` However, my attempts to empty these arrays have been unsuccessful. I have tried using the code: array = ...

Guide to setting a default child route in react-router and updating the URL as needed

Currently, I am utilizing react-router v3 and have a segment of my routing code as follows: ... <Route path='dashboard' component={Dashboard}> <Route path='overview' component={Overview}/> <Route path='scan&apo ...

Tips for shifting a stuck div 200px upward once the bottom of the page is reached while scrolling:

I've set up a page layout with two columns, one fixed and the other scrollable. The left column is fixed (containing Google ads) and stays in place as I scroll down the page. The right column displays posts and scrolls along with the rest of the con ...