<canvas id="c"></canvas>
    <div id="loading">
      <div class="progress"><div class="progressbar"></div></div>
    </div>
  
html, body {
  height: 100%;
  margin: 0;
}
#c {
  width: 100%;
  height: 100%;
  display: block;
}
#loading {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
#loading .progress {
  margin: 1.5em;
  border: 1px solid white;
  width: 50vw;
}
#loading .progressbar {
  margin: 2px;
  background: white;
  height: 1em;
  transform-origin: top left;
  transform: scaleX(0);
}
function main() {
  const canvas = document.querySelector("#c");
  const renderer = new THREE.WebGLRenderer({ canvas });

  const fov = 75;
  const aspect = 2;
  const near = 0.1;
  const far = 5;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 2;

  const scene = new THREE.Scene();

  const boxWidth = 1.05;
  const boxHeight = 1.2;
  const boxDepth = 0.3;
  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);

  const cubes = [];
  const loadManager = new THREE.LoadingManager();
  const loader = new THREE.TextureLoader(loadManager);

  // Controls
  const controls = new THREE.OrbitControls(camera);

  controls.rotateSpeed = 0.3;
  controls.zoomSpeed = 0.9;

  controls.minDistance = 1;
  controls.maxDistance = 20;

  controls.minPolarAngle = 0;
  controls.maxPolarAngle = Math.PI;

  controls.enableDamping = true;
  controls.dampingFactor = 0.05;

  const materials = [
    new THREE.MeshBasicMaterial({
      map: loader.load("https://jives.dev/lab/textures/wotlk/right.png")
    }),
    new THREE.MeshBasicMaterial({
      map: loader.load("https://jives.dev/lab/textures/wotlk/left.png")
    }),
    new THREE.MeshBasicMaterial({
      map: loader.load("https://jives.dev/lab/textures/wotlk/top.png")
    }),
    new THREE.MeshBasicMaterial({
      map: loader.load("https://jives.dev/lab/textures/wotlk/bottom.png")
    }),
    new THREE.MeshBasicMaterial({
      map: loader.load("https://jives.dev/lab/textures/wotlk/front.png")
    }),
    new THREE.MeshBasicMaterial({
      map: loader.load("https://jives.dev/lab/textures/wotlk/back.png")
    })
  ];

  const loadingElem = document.querySelector("#loading");
  const progressBarElem = loadingElem.querySelector(".progressbar");

  loadManager.onLoad = () => {
    loadingElem.style.display = "none";
    const cube = new THREE.Mesh(geometry, materials);
    scene.add(cube);
    cubes.push(cube);
  };

  loadManager.onProgress = (urlOfLastItemLoaded, itemsLoaded, itemsTotal) => {
    const progress = itemsLoaded / itemsTotal;
    progressBarElem.style.transform = `scaleX(${progress})`;
  };

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render(time) {
    time *= 0.001;

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }
 
    controls.update();

    renderer.render(scene, camera);
    renderer.setPixelRatio(window.devicePixelRatio);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://unpkg.com/three@0.108.0/build/three.js
  2. https://unpkg.com/three@0.108.0/examples/js/controls/OrbitControls.js