最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Problem importing GLTF model in Three.js: Lights not working properly - Stack Overflow

programmeradmin1浏览0评论

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.

Context:

  • I exported my model from Blender in GLTF/GLB format with all materials and textures.
  • I am using Three.js to render the scene.
  • The lights are imported as Object3D instead of DirectionalLight.

Code:

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

This is how the scene looks in Blender:

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.

Context:

  • I exported my model from Blender in GLTF/GLB format with all materials and textures.
  • I am using Three.js to render the scene.
  • The lights are imported as Object3D instead of DirectionalLight.

Code:

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

This is how the scene looks in Blender:

Share Improve this question asked Mar 15 at 3:12 holman rugamaholman rugama 333 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 3

A few things to keep in mind:

  1. Blender does not export lights to glTF files by default. Under export options, enable Include > Data > Punctual Lights.
  2. Conversions between different lighting systems (Blender to glTF to three.js) are not always straightforward. In Blender there are three options for lighting unit export: Standard, Unitless, and Raw. Standard applies the most technically-correct conversions, but in practice — if you aren't being pretty careful with lighting units and scene sizes and exposure values in three.js — you might find unitless easier to work with.
  3. The image produced in a render is not a predetermined output of particular lighting data. The image formation process (including exposure, tone mapping, color grading, ...) are subjective choices by software and humans. Blender and three.js have some commonalities here (both support AgX tone mapping, for example) but some differences are to be expected.
  4. The image you've rendered in Blender appears to include a "bloom" effect, creating the glow-like haze around the numbers. Effects like bloom are not included in exports, and would need to be re-created manually in three.js, based on its post-processing documentation.

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.

发布评论

评论列表(0)

  1. 暂无评论