Struggling with slow loading times for Three.JS GLTF models? Discover ways to optimize and speed up the load time

My GLTF model (9mb) is loading slowly in ThreeJS. It takes about 4-5 seconds to load on my PC and around 11 seconds on my iPhone. I'm looking for ways to speed up the rendering times. Surprisingly, examples from the ThreeJS website load faster than my project, even though my project only has one object being loaded. I expected it to load faster than the examples on the ThreeJS website.

You can check out my example project here:

Code

var ourObj;
var ourObj2;

// Instantiate a loader
var loader = new THREE.GLTFLoader();

// Optional: Provide a DRACOLoader instance to decode compressed mesh data
var dracoLoader = new THREE.DRACOLoader();
dracoLoader.setDecoderPath( '/js/draco/' );
loader.setDRACOLoader( dracoLoader );



let scene, camera, renderer, stars, starGeo;

function init() {

  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
  camera.position.z = 25;

  //renderer = new THREE.WebGLRenderer();
 renderer = new THREE.WebGLRenderer();
  renderer.setClearColor("#000000");
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  starGeo = new THREE.Geometry();
  for(let i=0;i<6000;i++) {
    star = new THREE.Vector3(
      Math.random() * 600 - 300,
      Math.random() * 600 - 300,
      Math.random() * 600 - 300
    );
    star.velocity = 0;
    star.acceleration = 0.02;
    starGeo.vertices.push(star);
  }

  let sprite = new THREE.TextureLoader().load( 'star.png' );
  let starMaterial = new THREE.PointsMaterial({
    color: 0xaaaaaa,
    size: 0.7,
    map: sprite
  });

  stars = new THREE.Points(starGeo,starMaterial);
  scene.add(stars);

 // window.addEventListener("resize", onWindowResize, false);
  var hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
  hemiLight.position.set( 0, 300, 0 );
  scene.add( hemiLight );
  
  var dirLight = new THREE.DirectionalLight( 0xffffff );
  dirLight.position.set( 75, 300, -75 );
  scene.add( dirLight );



  loader.load(
    // resource URL
    'objs/dracowolf.gltf',
    // called when the resource is loaded
    function ( gltf ) {
  
      scene.add( gltf.scene );
      ourObj = gltf.scene;
      animate();
  
    },
    // called while loading is progressing
    function ( xhr ) {
  
      console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
  
    },
    // called when loading has errors
    function ( error ) {
  
      console.log( 'An error happened' );
  
    }
  );

  
}



function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  }


  
function animate() {


  requestAnimationFrame(animate);
  renderer.render(scene, camera);

  if(ourObj){
        ourObj.rotation.y -= .01;
    }
  starGeo.vertices.forEach(p => {
    p.velocity += p.acceleration
    p.y -= p.velocity;
    
    if (p.y < -200) {
      p.y = 200;
      p.velocity = 0;
    }
  });
  starGeo.verticesNeedUpdate = true;
  stars.rotation.y +=0.002;

}
init();

Answer №1

Here are a few recommendations for optimizing this particular model:

  1. Opt for the .glb format over .gltf. The binary version of glTF tends to be 25-30% smaller than a .gltf containing embedded binary data, and does not require decoding from a Data URI. You can also use a separate binary .bin file with .gltf. Utilize glTF-Pipeline to implement these changes.
  2. Prioritize loading the Draco decoder by invoking dracoLoader.preload() before the model begins loading. This can potentially save 500ms that would otherwise be spent fetching the decoder after the model has already been downloaded.
  3. Explore the option of utilizing https://github.com/zeux/meshoptimizer#installing-gltfpack to streamline the model, or consider quantizing it and then compressing it using gzip. This serves as an alternative to Draco compression, and although it may not achieve the same level of file compression, it can sometimes reduce overall loading time despite this difference.

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

What is the best way to reference an Angular constant within a Gulp configuration file?

Is it possible to retrieve an Angular constant within a Gulp file? For example: angular.module('app').constant('env', { url: 'http://localhost:1337/' }); What is the method for accessing this constant inside a function ...

The image you are looking for at './expo-asset/assets/${your_img_path}' was not located within React Native or Expo

My current project is an expo ejected react native project and I'm encountering the error message [native] Could not find image on path The file path in question: 'file:///var/mobile/Containers/Data/Application/..../Library/Application%20Support ...

Is there a way to selectively add elements to the Promise.all() array based on certain conditions?

Here is the code snippet that I have written: I am aware that using the 'await' keyword inside a for-loop is not recommended. const booksNotBackedUp: number[] = []; for (let i = 0; i < usersBooks.length; i += 1) { const files = await ...

Webpack has successfully built the production version of your ReactJS application. Upon review, it appears that a minified version of the development build of React is being used

Currently, I am implementing Reactjs in an application and the time has come to prepare it for production. In my package.json file, you can see that there is a "pack:prod" command which utilizes webpack along with a specific webpack.config.js file to build ...

selecting a radio button and saving its value into a JavaScript variable

How can I assign the return value from a JavaScript script function to a variable inside the HTML body? The function will return the selected variable, but how can I assign it to a variable within my HTML body? <body> <form action="somepage.php ...

What is the preferred method for implementing a dynamic select control with Ajax

I'm having an issue with AJAX and MySQL in PHP. Can anyone offer assistance? Within my form, I have a select control: <form action="index.php" method="post" name="pretraga" class="border"> <p>Location:</p> <div ...

Add a trash can or delete icon within every row of a table using Vue.js

I am new to vue.js and I'm struggling to implement a trash icon in each row of a table for deleting rows. Additionally, I'm trying to make the input of a cell act as a dropdown menu or list within the table rows. I recently came across this scrip ...

Features of ES2015's [[class]] attribute

I've been developing a basic clone function var shallowCopy = function (value) { // In ES2017, we could also use // return Object.create(Object.getPrototypeOf(value), Object.getOwnPropertyDescriptors(value)); let propDescriptors = {}; for (le ...

Utilize a recursive function to incorporate data into an array nested within other arrays

I am facing an issue where the data I'm trying to add to an element containing nested arrays is not getting updated in MongoDB, even though it appears correctly in the console. I have developed a function to navigate through the entire structure of th ...

Automated Menu Selection using Selenium

I'm currently facing a challenge in writing a Python script using Selenium to interact with a webpage. I am struggling to use the .click() method to select an expandable list on the page. Despite successfully logging in and navigating to the desired p ...

Encountered an issue with Nextjs dynamic routes and static pages where the error message states that the `paths` variable needs to be an

I have been following the official Next.js guide on generating statically generated pages with dynamic routes (Nextjs - Dynamic Routes). However, I am facing an issue when trying to generate pages with fetched data. The error message I am receiving is as f ...

Exploring the Power of GraphQL Args in Mutation Operations

Currently, I am in the process of developing a blog service using express and apollo-express in conjunction with mongodb (mongoose). While implementing mutation queries, I have encountered difficulties in accessing the arguments of a mutation query. I am ...

Displaying the currently logged in user's name with NodeJS/ExpressJS/Passport

In my quest to showcase the username for logged-in users (function 3), I encountered a dilemma. Initially, only function 1 existed in my codebase. To address this issue, I made modifications and introduced function 2 to facilitate displaying usernames of a ...

Leveraging colons in the process of object destructuring

I'm still trying to wrap my head around all the wonders of ES6. Ran across this snippet in an online article and I'm puzzled by how PrivateRoute is deconstructing the input props. What exactly is the purpose of component: Component here? const P ...

Using JQuery to create an animated slideToggle effect for a multicolumn list

I have a large list where each li element has a width of 33%, resulting in 3 columns: computers monitors hi-fi sex-toys pancakes scissors Each column contains a hidden UL, which is revealed through slideToggle on click. JQuery $('.subCate ...

Each time the button is clicked, the settings and values will rotate, creating a new

I'm looking to create a button system that transitions from "unmarked" to "form" and updates the database with each click. I want users to be able to cycle through the buttons, triggering a post request via ajax to update the associated ID in the data ...

Upload the image data into the input file tag

Is there a way to take a string code stored in a JavaScript variable that is retrieved from the Cropit plugin (used for cropping images) and then set this information into an input file tag? I want to be able to send it via AJAX to PHP. Here is the JavaSc ...

Error message when using Vue Global Filter: Value undefined is not defined

Trying to format currency, I initially attempted to use a global filter in Vue: Vue.filter('formatMoney', (val) => { if (!value) return '' val = val.toString() return val.replace(/\B(?=(\d{3})+(?!\d))/g, ",") ...

Transferring an array of objects from one array to another with the click of a button

I'm facing an issue with moving data between two arrays of objects using buttons in a Nextjs project. The functionality works correctly when selecting a single data item, but it gives unexpected results when selecting multiple items. Although my code ...

Instructions on how to export an HTML table to Excel or PDF by including specific buttons using PHP or JavaScript

I created a table to display leave details of employees with sorting options from date to date. Now, I need to include buttons for exporting the data to Excel and PDF formats. Check out the code below: <form name="filter" method="POST"> <in ...