Too Low FPS When I Use Envmap

Hi everyone,


I’m developing an app needs realistic view. But for sure at the same time performance should be good.

I didn’t even start to put all of objects but when i use envmap it breaks the performance and im getting really bad fps like 7-10.

I’m not using dirlight or spotlight. I used lightmap and aomap generally. And i have just one ambient light in the scene.

I’m sharing my all code. Maybe im making a mistake somewhere i dont know.

import * as THREE from './three/build/three.module';
import { GLTFLoader } from './three/examples/jsm/loaders/GLTFLoader';
import { IndoorControls } from './three/examples/jsm/controls/IndoorControls';
import { RGBELoader } from './three/examples/jsm/loaders/RGBELoader';
import Stats from './three/examples/jsm/libs/stats.module';


var scene, camera, renderer, controls;

var gltfLoader, textureLoader;
var stats;

var scenes, activeRoom = 'room1';

var helperMaterial, helperGeometry, mouseHelper;
var ringMaterial, ringGeometry, ring;

var roomOne, roomTwo, roomThree;
var objToRemove = [];

var cubeMap;

init();
animate();

function init() {
    //create renderer
    renderer = new THREE.WebGLRenderer({ antialias: true, powerPreference: "high-performance" });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);

    renderer.outputEncoding = THREE.sRGBEncoding;
    renderer.toneMapping = THREE.LinearToneMapping;
    renderer.toneMappingExposure = 0.5;


    document.body.appendChild(renderer.domElement);
    window.addEventListener('resize', onWindowResize, true);

    // create scene
    scene = new THREE.Scene();

    // Camera
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 20);
    camera.position.set(-4, 1.6, 3)
    camera.rotation.y = -1.4;
    scene.add(camera);

    // Controls
    controls = new IndoorControls(camera, renderer.domElement);

    // Loader
    gltfLoader = new GLTFLoader();

    // Texture Loader
    textureLoader = new THREE.TextureLoader();

    // controls cursor
    helperMaterial = new THREE.MeshBasicMaterial();
    helperMaterial.transparent = true;
    helperMaterial.opacity = 0.2;
    helperGeometry = new THREE.CircleBufferGeometry(0.2, 64);
    mouseHelper = new THREE.Mesh(helperGeometry, helperMaterial);

    ringMaterial = new THREE.MeshBasicMaterial();
    ringMaterial.transparent = true;
    ringMaterial.opacity = 0.8;
    ringGeometry = new THREE.RingBufferGeometry(0.2, 0.22, 64);
    ring = new THREE.Mesh(ringGeometry, ringMaterial);
    mouseHelper.add(ring);
    mouseHelper.visible = false;
    ring.renderOrder = 2;
    mouseHelper.renderOrder = 2;
    scene.add(mouseHelper);

    //Create a new statistics object
    stats = new Stats();
    //Show the statistics
    stats.showPanel(0);
    //Append the statistics to dom
    document.body.appendChild(stats.dom);

    // Rooms
    roomOne = createRoomOne();
    scene.add(roomOne)

    scenes = {
        room1: roomOne
    }

    onWindowResize()
}

// Load HDR
loadEnvironment('data/rooms/one/env/ninomaru_teien_1k.hdr').then(function (envMap) {
    scene.environment = envMap;
    scene.background = envMap;
});

function createRoomOne() {
    // load room
    var group = new THREE.Object3D();

    // lights
    var ambientLight = new THREE.AmbientLight(0xffffff, 1);
    group.add(ambientLight);
    objToRemove.push(ambientLight)

    gltfLoader.load(
        // resource URL
        'data/rooms/one/model.gltf',
        // called when the resource is loaded
        function (gltf) {
            gltf.scene.traverse(function (obj) {

                gltf.castShadow = true;
                gltf.receiveShadow = true;

                if (obj instanceof THREE.Mesh) {
                    if (obj.material.name == "floor") {
                        obj.material.roughness = 0.7;
                        obj.material.metalness = 0.3;

                        let lightMapImg = "data/rooms/one/bake/floorLightMap.jpg";
                        let lightMap = LoadTextureCorrected(textureLoader, lightMapImg);
                        lightMap.flipY = false;
                        obj.geometry.attributes.uv2 = obj.geometry.attributes.uv;
                        obj.material.side = 2;
                        obj.material.lightMap = lightMap;
                        obj.material.lightMapIntensity = 2;

                        obj.material.map.wrapS = obj.material.map.wrapT = THREE.RepeatWrapping;
                        obj.material.map.repeat.set(4, 4);
                        controls.ground.push(obj);
                    }

                    if (obj.material.name == "curtain") {

                        obj.material.aoMapIntensity = 0.3;
                    }

                    if (obj.material.name == "walldecor3") {

                        let lightMapImg = "data/rooms/one/bake/wallDecor3LightMap.jpeg";
                        let lightMap = LoadTextureCorrected(textureLoader, lightMapImg);
                        lightMap.flipY = false;
                        obj.geometry.attributes.uv2 = obj.geometry.attributes.uv;
                        obj.material.side = 2;
                        obj.material.lightMap = lightMap;
                        obj.material.lightMapIntensity = 1.5;
                        obj.material.aoMapIntensity = 0.8;
                    }

                    if (obj.material.name == "3seaterfabric") {

                        let lightMapImg = "data/rooms/one/bake/3seaterLightMap.jpg";
                        let lightMap = LoadTextureCorrected(textureLoader, lightMapImg);
                        lightMap.flipY = false;
                        obj.geometry.attributes.uv2 = obj.geometry.attributes.uv;
                        obj.material.side = 2;
                        obj.material.lightMap = lightMap;
                        obj.material.lightMapIntensity = 2;
                        obj.material.aoMapIntensity = 0.8;
                    }

                    if (obj.material.name == "walls") {
                        // obj.material.envMapIntensity = 0.4;
                        obj.material.aoMapIntensity = 0.8;
                        let lightMapImg = "data/rooms/one/bake/wallsLightMap.jpg";
                        let lightMap = LoadTextureCorrected(textureLoader, lightMapImg);
                        lightMap.flipY = false;
                        obj.geometry.attributes.uv2 = obj.geometry.attributes.uv;
                        obj.material.side = 2;
                        obj.material.lightMap = lightMap;
                        // obj.material.lightMapIntensity = 2;

                    }
                    objToRemove.push(obj)
                }
            });
            gltf.scene.rotation.y = -1;
            group.add(gltf.scene);
        },
        // 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');

        }
    );
    group.name = "roomOne";
    objToRemove.push(group)
    return group
}

function createRoomTwo() {
    // load room
    var group = new THREE.Object3D();

    // lights
    var ambientLight = new THREE.AmbientLight(0xcccccc, 1);
    group.add(ambientLight);
    objToRemove.push(ambientLight)

    // global lights
    const lightSun = new THREE.DirectionalLight(0xffffff);
    lightSun.name = 'sun';
    lightSun.position.set(0.2, 1, 0.1);

    //Lights for fill the main light
    const lightFill = new THREE.DirectionalLight(0xffffff, 0.7);
    lightFill.name = 'fillLight';
    lightFill.position.set(-0.2, -1, -0.1);

    group.add(lightSun, lightFill);

    gltfLoader.load(
        // resource URL
        'data/rooms/two/model.gltf',
        // called when the resource is loaded
        function (gltf) {
            gltf.scene.traverse(function (obj) {
                gltf.castShadow = true;
                gltf.receiveShadow = true;
                if (obj instanceof THREE.Mesh) {
                    if (obj.material.name == "floor2") {
                        controls.ground.push(obj);
                    }
                    objToRemove.push(obj)
                }
            });
            group.add(gltf.scene);
        },
        // 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');

        }
    );
    group.name = "roomTwo";
    objToRemove.push(group)
    return group
}


controls.addEventListener('mousemove', function (event) {
    var intersect = event.intersect;
    mouseHelper.position.set(0, 0, 0);
    mouseHelper.rotation.x = Math.PI / -2;
    mouseHelper.position.copy(intersect.point);
    mouseHelper.position.y += 0.01;
    mouseHelper.visible = true;
    controls.enabled_move = true;
});

function onWindowResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
    controls.reset(camera, renderer.domElement);
}

function animate() {
    requestAnimationFrame(animate);
    stats.begin();
    // room();
    renderer.render(scene, camera);
    controls.update();
    stats.end();
}

// function room() {
//     for (const key in scenes) {
//         scenes[key].visible = key === activeRoom;
//     }
//     const scene = scenes[activeRoom];
//     if (scene.update) scene.update();
// }

////////////////////
// Configurator
////////////////////

$("body").on("click", "#roomOne", () => {
    // Rooms
    if (activeRoom != "room1") {
        removeRoom()
        controls.ground.pop();
        const roomOne = createRoomOne();
        scenes.room1 = roomOne
        scene.add(roomOne)
        activeRoom = "room1";
    }
});

$("body").on("click", "#roomTwo", () => {
    // Rooms
    if (activeRoom != "room2") {
        removeRoom()
        controls.ground.pop();
        const roomTwo = createRoomTwo();
        scenes.room2 = roomTwo
        scene.add(roomTwo)
        activeRoom = "room2";
    }
});

function removeRoom() {
    if (objToRemove.length > 0) {
        objToRemove.forEach(function (v, i) {
            if (v instanceof THREE.Mesh) {
                v.geometry.dispose();
            }
            if (v.material) {
                if (v.material.map) v.material.map.dispose();
                if (v.material.envMap) v.material.envMap.dispose();
                if (v.material.normalMap) v.material.normalMap.dispose();
                if (v.material.roughnessMap) v.material.roughnessMap.dispose();
                v.material.dispose();
            }
            v.parent.remove(v);
        });
        objToRemove = null;
        objToRemove = [];
    }
}

///////////////////////
///// Helper Functions
//////////////////////

//Function to load texture corrected
function LoadTextureCorrected(_loader, _path) {
    //Load the texture
    var texture = _loader.load(_path);
    //Set repeat wrapping
    texture.wrapT = texture.wrapS = THREE.RepeatWrapping;
    //Flip texture vertically
    texture.repeat.y = -1;
    //Return the corrected texture
    return texture;
}


function loadEnvironment(url) {

    let rgbeLoader = new RGBELoader();
    rgbeLoader.setDataType(THREE.UnsignedByteType);
    return new Promise(resolve => {

        rgbeLoader.load(url, function (texture) {

            let pmremGenerator = new THREE.PMREMGenerator(renderer);
            pmremGenerator.compileEquirectangularShader();

            let envMap = pmremGenerator.fromEquirectangular(texture).texture;
            pmremGenerator.dispose();

            resolve(envMap);
        });

    });

}

It’s best to demonstrate the performance bottleneck with a link to your app or a live example so it’s possible to make a performance analysis with the browser’s dev tools.

Your code does not show an obvious error. And to be honest, a screenshot is in general not helpful for investigating performance related issues.