Javascript Three.Js GLTF Loading Is Very Slow Compared To Other GLTF Viewers

Viewed 1632

Hello I'm trying to implement a 3D Model Viewer using Three.Js however I have a problem with the loading times and I don't know where the problem might be.

As an example I'm trying to upload this model here (download link): https://opensplit.com/gltf/assets/PromoModel.glb

You can test it In this gltf Viewer here for example: https://gltf-viewer.donmccurdy.com/

It will basically pops up after only a few seconds.

However you can see how ridiculously long it takes on my website: https://opensplit.com/ The same model takes now more than two minutes to load.. this cannot be correct, why is it so slow?

Here is my code:

<canvas id="canvas"></canvas>   
<br>            
<div style="margin:15px; margin-bottom:0px;">
    <progress id="load_lowPoly" value="0" max="100"></progress>
        
    <div id="lowPoly_progress">Loading Raw Model</div>
</div>
<div id="progressElement" style="background: green; width:0%;"></div>
<div id="previewquali" style="margin:15px; margin-top:0px;">
    Material Quality: loading.. 
</div>
<script src="../gltf/libraries/three.js"></script>
<script src="../gltf/libraries/OrbitControls.js"></script>
<script src="../gltf/libraries/GLTFLoader.js"></script>
<script src="../gltf/libraries/RGBELoader.js"></script>
<script src="../gltf/libraries/DRACOLoader.js"></script>
<script src="../gltf/libraries/EquirectangularToCubeGenerator.js"></script>
<script src="../gltf/libraries/PMREMGenerator.js"></script>
<script src="../gltf/libraries/PMREMCubeUVPacker.js"></script>  

<script>
    window.addEventListener( "resize", this.onWindowResize, false );    
    var manager = new THREE.LoadingManager();   
    var loader = new THREE.TextureLoader()
    var windowHeight = 800; 
    var camera = new THREE.PerspectiveCamera( 47, (window.innerWidth/window.innerHeight) / windowHeight, 0.01, 100000 );
    var renderer = new THREE.WebGLRenderer( { canvas: document.getElementById( "canvas" ), antialias: true, alpha: true } );
    var controls = new THREE.OrbitControls( camera, renderer.domElement );
    var scene = new THREE.Scene();
    var loadAsset = true;
    var percentComplete;
    var gltfSource;
    var envMap;
    var mesh;
    onWindowResize();
    init();
    animate();
    
    function onWindowResize() {
        camera.aspect = (window.innerWidth/1.15) / windowHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth/1.15, windowHeight );
    }

    function init() {   
        camera.position.z = 0;
        camera.position.y = 0;
        camera.position.x = 2000.00;
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth/1.15, windowHeight );
        renderer.physicallyCorrectLights = true;
        renderer.gammaOutput = true;
        renderer.gammaFactor = 2.8;
        renderer.setClearColor( 0xf2f2f2, 1 );
        updateWindow();
        createCubeMap( "../gltf/hdri/machine_shop_02_1k.hdr", 1024 );
        loadDraco6141012( "../gltf/assets/PromoModel.glb" );
    }

    function animate() {
        requestAnimationFrame( animate );
        controls.update();  
        renderer.render( scene, camera );
        
    };  

    function createCubeMap( src, res ) {
        new THREE.RGBELoader().setDataType( THREE.UnsignedByteType ).load( src, function ( texture ) {  
            var cubeGenerator = new THREE.EquirectangularToCubeGenerator( texture, { resolution: res } );
            var pmremGenerator = new THREE.PMREMGenerator( cubeGenerator.renderTarget.texture );
            var pmremCubeUVPacker = new THREE.PMREMCubeUVPacker( pmremGenerator.cubeLods );
            envMap = pmremCubeUVPacker.CubeUVRenderTarget.texture;
            cubeGenerator.update( renderer );
            pmremGenerator.update( renderer );
            pmremCubeUVPacker.update( renderer );
            pmremGenerator.dispose();
            pmremCubeUVPacker.dispose();
        } );
    }
    
    function loadDraco6141012( src ) {
        var loader = new THREE.GLTFLoader();
        loader.setDRACOLoader( new THREE.DRACOLoader() );
        loader.load( src, function( gltf ) {
            gltf.scene.traverse( function ( child ) {
                if ( child.isMesh ) {
                    child.material.envMap = envMap;
                    child.material.envMapIntensity = 0.8;
                    mesh = child;
                }
            } );
            scene.add( gltf.scene );
        }, function ( xhr ) {
            if ( xhr.lengthComputable ) {
                percentComplete = xhr.loaded / xhr.total * 100;
                console.log( "Loading Model - " + Math.round(percentComplete, 2) + "%" );
                document.getElementById("lowPoly_progress").innerHTML = "Loading Raw Model " + Math.round(percentComplete, 2) + "%";
                document.getElementById("load_lowPoly").value = percentComplete;
            }
        } );
    }
                
    function updateWindow() {
        onWindowResize();
    }

</script>

I thought this was the most simple way to do it. But as you can see for yourself on my website this takes forever to load. How can I fix this issue?

2 Answers

Here is my guess:

Your website is slow since it has to download the glb file first, which just takes a while.

You probably compared it with Dons website by downloading the glb file to your computer and dragging it into the viewer. This way the download is already finished and everything happens locally on your computer, so you don't have to wait anymore... which is faster of course.

How could you solve problems like this in the future? Open the developer tools in Chrome, go to "Performance" and start a recording. Refresh your webpage. When the model is visible, stop the recording. Now you can see a small dropdown (or something like that) called "Network" below the rendered frames in the profiler. If you open this, you will see that loading your .glb file took 1.2 minutes.

Related