GLTFLoader performance question during the first renderer

thunk.glb.zip (3.5 MB)

I am new to Threejs.
I use this gltfloader example three.js examples and I change the model to one of my model thunk.glb.

At begining, everything is fine.

When I comment the following lines.

var urls = [ ‘posx.jpg’, ‘negx.jpg’, ‘posy.jpg’, ‘negy.jpg’, ‘posz.jpg’, ‘negz.jpg’ ];
var loader = new THREE.CubeTextureLoader().setPath( ‘/three/examples/textures/cube/Bridge2/’ );
var background = loader.load( urls );
scene.background = background;

It become very slow for the first render.

After a few hours reseach I figure out maybe it is because the warning THREE.WebGLRenderer: Texture has been resized from (905x208) to (512x128). cause problem.

When I use glb file model without the warning , The first render is fine with or without comments the above lines.

Anyone have the same problem and how can I solve this problem?

So you mean when you are using CubeTextureLoader in order to load a cube texture for the scene’s background, it takes longer to render the first frame?

Try to use power-of-two textures in order to avoid the resizing at runtime. That means the width and height of your texture should be a multiple of 2 (e.g. 1024x1024). An other options is to set Texture.minFilter to THREE.LinearFilter. In this way, you don’t have to resize your texture and can use it as it is.

1 Like

@ Mugen87 , thanks for reply!

The fact is with CubeTextureLoader , loading is very fast.
Without CubeTextureLoader , loading is very slow. almost 10 times slow.

31%20PM 11%20PM

I digger more about this topic today, I figure out it is not about texture at all.

I use the glb model which is export from Threejs Editor https://threejs.org/editor/
this model don’t have texture warning.
and I compare the result with and without CubeTextureLoader.
22%20PM 05%20PM

thunk-n.glb.zip (3.4 MB)

The result is the same:

With CubeTextureLoader , loading is very fast.
Without CubeTextureLoader , loading is very slow. almost 10 times slow.

function init() {

    container = document.createElement( 'div' );
    document.body.appendChild( container );

    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.001, 200 );
    camera.position.set( - 1.8, 0.9, 2.7 );

    controls = new THREE.OrbitControls( camera );
    controls.target.set( 0, - 0.2, - 0.2 );
    controls.update();

    scene = new THREE.Scene();
    /*
    var urls = [ 'posx.jpg', 'negx.jpg', 'posy.jpg', 'negy.jpg', 'posz.jpg', 'negz.jpg' ];
    var loader = new THREE.CubeTextureLoader().setPath( '/three/examples/textures/cube/grey/' );
    var background = loader.load( urls );
    scene.background = background;
    */
    
    light = new THREE.HemisphereLight( 0xbbbbff, 0x444422 );
    light.position.set( 0, 1, 0 );
    scene.add( light );

    
    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.gammaOutput = true;
    container.appendChild( renderer.domElement );

    window.addEventListener( 'resize', onWindowResize, false );

    // model
    //var loader = new THREE.GLTFLoader().setPath( '/three/examples/models/gltf/DamagedHelmet/glTF/' );
    //loader.load( 'DamagedHelmet.gltf', function ( gltf ) {
    var loader = new THREE.GLTFLoader().setPath( '/assets/gltf/' );
    loader.load( 'thunk-n.glb', function ( gltf ) {
        scene.add( gltf.scene );
    }, undefined, function ( e ) {
        console.error( e );
    } );

    // stats
    stats = new Stats();
    stats.setMode(1);
    container.appendChild( stats.dom );
}

Note that the first render is when textures are uploaded to the GPU, unless you do that in advance. This will always be slower than later renders.

@donmccurdy you are right.

I use the following code get fast first rendering frame.

    var totalScene = new THREE.Object3D();
    var loader = new THREE.GLTFLoader().setPath( '/assets/gltf/' );
    loader.load( 'thunk-n.glb', function ( gltf ) {
        gltf.scene.traverse( function ( child ) {
            if ( child.isMesh ) {
                setTimeout(function(){
                    var mesh=child.clone();
                    scene.add(mesh);
                    renderer.render( scene, camera );
                }, 1);
                
            }
		    } );
    }, undefined, function ( e ) {
        console.error( e );
    } );