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);
});
});
}