Im loading a GLTF model (9mb) into ThreeJS. It's definitely loading slow. It takes about 4-5 seconds to load on my PC and about 11 seconds to load on my IPhone. How can i speed up the rendering times? My PC and IPhone load examples from the ThreeJS website faster than my project. My project has only one object being loaded so I feel like it should load faster than the examples on ThreeJS website.
My example project is located here @ /
Code
var ourObj;
var ourObj2;
// Instantiate a loader
var loader = new THREE.GLTFLoader();
// Optional: Provide a DRACOLoader instance to decode pressed 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();
Im loading a GLTF model (9mb) into ThreeJS. It's definitely loading slow. It takes about 4-5 seconds to load on my PC and about 11 seconds to load on my IPhone. How can i speed up the rendering times? My PC and IPhone load examples from the ThreeJS website faster than my project. My project has only one object being loaded so I feel like it should load faster than the examples on ThreeJS website.
My example project is located here @ http://flowolfsworld./
Code
var ourObj;
var ourObj2;
// Instantiate a loader
var loader = new THREE.GLTFLoader();
// Optional: Provide a DRACOLoader instance to decode pressed 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();
Share
Improve this question
edited Sep 1, 2020 at 1:07
user128511
asked Aug 31, 2020 at 22:30
sirshakirsirshakir
1394 silver badges14 bronze badges
2
- This is just the expected behavior for an object of such a large size. 9MB is a big file to download, and a lot of vertices to decode and send to GPU. The examples on Threejs load fast because they don't use 9MB files. You should look into using a normal map instead of such dense geometry, like this example – M - Commented Aug 31, 2020 at 23:18
-
See this website as an example: dogstudio.co Their
glb
file is only 840KB because instead of modeling the fur with real geometry, they used this normal map to save hundreds of thousands of vertices. – M - Commented Aug 31, 2020 at 23:55
1 Answer
Reset to default 7A few suggestions on this particular model:
- Use
.glb
, not.gltf
. The binary form of glTF will be 25-30% smaller than a.gltf
with embedded binary data, and doesn't have to be decoded from a Data URI. Using.gltf
with a separate binary.bin
is also an option. Use glTF-Pipeline to make these changes. - Preload the Draco decoder by calling
dracoLoader.preload()
before your model starts loading. On my test of your page, that would save 500ms spent fetching the decoder after the model has already been downloaded. - Consider using https://github./zeux/meshoptimizer#installing-gltfpack to simplify the model, or at least to quantize it, and then gzip it. This is an alternative to Draco, and may not press the file quite as well, but can sometimes decrease overall loading time despite that.