Three.js renders a black scene because of texture loading.
I am using three.js inside an angular component (angular version 8).
I was trying to follow an old three.js tutorial on rendering Earth in WebGL which used now deprecated THREE.ImageUtils.loadTexture() to load a texture for mesh material map.
It didn't work for me, so I tried using modern THREE.TextureLoader().load(). However, for some reason, it never acted upon its callback.
So I tried using THREE.TextureLoader().load() paired with THREE.LoadingManager(). While THREE.LoadingManager()'s callback seems to work, it still produces only a black scene with some light.
While I'm new at using three.js, to me it seems that my code:
- Does include light
- Does seem to render not only once
- Doesn't throw any errors to console
Code:
In my component.html:
...
<div #rendererContainer></div>
...
In my component.ts:
import {Component, OnInit, ViewChild, ElementRef, AfterViewInit} from '@angular/core';
import * as THREE from 'three';
export class MyComponent implements OnInit, AfterViewInit {
  @ViewChild('rendererContainer', {static: false}) rendererContainer: ElementRef;
  renderer = new THREE.WebGLRenderer();
  scene = null;
  camera = null;
  mesh = null;
  earthSurface = new THREE.MeshStandardMaterial({color: 0xaaaaaa});
  constructor() {
    // scene and camera
    this.scene = new THREE.Scene();
    this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 1000);
    this.camera.position.z = 1.5;
    // light
    this.scene.add(new THREE.AmbientLight(0x333333));
    const light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(5, 3, 5);
    this.scene.add(light);
    const manager = new THREE.LoadingManager();
    const textureLoader = new THREE.TextureLoader(manager);
    this.earthSurface.map = textureLoader.load('planet.jpg');
    manager.onLoad = () => {
      // call back
      const geometry = new THREE.SphereGeometry(0.5, 32, 32);
      this.mesh = new THREE.Mesh(
        geometry,
        this.earthSurface
      );
      this.scene.add(this.mesh);
      this.rerender();
      console.log(this.earthSurface);
    };
  }
  ngOnInit() {}
  ngAfterViewInit() {
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.rendererContainer.nativeElement.appendChild(this.renderer.domElement);
      this.animate();
      // setInterval(() => {this.rerender();}, 1.5 * 1000);
  }
  rerender() {
    this.renderer.render(this.scene, this.camera);
  }
  animate() {
    this.renderer.render(this.scene, this.camera);
    window.requestAnimationFrame(() => this.animate());
  }
}