I have been trying to import a GLTF model into Three.js, but I'm encountering several issues. When I import my scene with all the elements, the lights do not work as expected. The directional lights I configured in Blender (using the Eevee engine) do not appear correctly in Three.js.
Object3D
instead of DirectionalLight
.Here is the code I am using to load the model and set up the lights:
import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { ModelViewerProps } from "./types";
export class ModelViewer {
private _container: HTMLDivElement | null;
private _scene: THREE.Scene = new THREE.Scene();
private _camera: THREE.PerspectiveCamera;
private _renderer: THREE.WebGLRenderer;
private _controls?: OrbitControls;
constructor(props: ModelViewerProps) {
this._container = props.container;
this._renderer = new THREE.WebGLRenderer({ antialias: true });
this._renderer.setPixelRatio(window.devicePixelRatio);
this._renderer.setSize(window.innerWidth, window.innerHeight);
this._renderer.shadowMap.enabled = true;
this._renderer.toneMapping = THREE.ACESFilmicToneMapping;
this._renderer.toneMappingExposure = 1.25;
this._renderer.setClearColor(0x000000, 1);
this._camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
this._camera.position.set(0, 2, 5);
if (props.useOrbitControls) {
this._controls = new OrbitControls(
this._camera,
this._renderer.domElement
);
}
this.loadModel(props.modelPath);
if (this._container) {
this._container.appendChild(this._renderer.domElement);
}
window.addEventListener("resize", this.onWindowResize.bind(this));
this.animate();
}
private loadModel(url: string) {
const loader = new GLTFLoader();
loader.load(
url,
(gltf) => {
this._scene.add(gltf.scene);
if (gltf.cameras.length > 0) {
if (gltf.cameras[0] instanceof THREE.PerspectiveCamera) {
this._camera = gltf.cameras[0];
}
}
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
(error) => {
console.error(error);
}
);
}
private onWindowResize() {
const width = window.innerWidth;
const height = window.innerHeight;
this._camera.aspect = width / height;
this._camera.updateProjectionMatrix();
this._renderer.setSize(width, height);
}
private animate() {
requestAnimationFrame(() => this.animate());
if (this._controls) {
this._controls.update();
}
this._renderer.render(this._scene, this._camera);
}
}
A few things to keep in mind:
You may find it easier to create the lighting and post-processing you want directly in three.js, bringing in only the model and materials from Blender. Transferring lighting, effects, and image formation between realtime applications is usually a challenge.
Updated as of Blender 4.2, three.js r174.