JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://raw.githubusercontent.com/mrdoob/three.js/dev/build/three.module.min.js"></script>
<script src="https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/jsm/loaders/GLTFLoader.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.0/jszip.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>

<div id="webgl"></div>

CSS

#webgl {
  margin: 0;
  position: absolute;
  left: 0;
  top: 0;
  width: 512px;
  height: 512px;
}

JavaScript

import * as THREE from 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js';
import {
  GLTFLoader
} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/loaders/GLTFLoader.js';

let scene, renderer, camera;
const jsZip = new JSZip();

init();

async function addCanvasToZip(filename) {
  const webgl_div = document.getElementById('webgl');
  let webgl_canvas = webgl_div.querySelectorAll('canvas')[0];

  const blob = await new Promise((res) => webgl_canvas.toBlob(res));

  jsZip.file(filename, blob, {
    binary: true
  });
}

function init() {
  function getContainer() {
    return document.getElementById('webgl');
  }

  function getContainerSize() {
    const elem = getContainer();

    return {
      width: elem.clientWidth,
      height: elem.clientHeight,
    };
  }

  const ctr_size = getContainerSize();
  camera = new THREE.PerspectiveCamera(
    75,
    ctr_size.width / ctr_size.height,
    0.01,
    10,
  );

  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x66aa66);

  renderer = new THREE.WebGLRenderer({
    antialias: true,
    preserveDrawingBuffer: true,
  });

  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(ctr_size.width, ctr_size.height);
  getContainer().appendChild(renderer.domElement);

  camera.position.set(0.0, 2.0, -1.25);
  camera.lookAt(new THREE.Vector3(0.0, 1.0, 0.0));

  const gltfLoader = new GLTFLoader();
  const material = new THREE.MeshNormalMaterial();

  let model_loader_promises = [];

  const webgl_div = document.getElementById('webgl');
  let webgl_canvas = webgl_div.querySelectorAll('canvas')[0];

  const total = 50;
  for (let count = 0; count < total; ++count) {
    model_loader_promises.push(gltfLoader.loadAsync('https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Soldier.glb'));
  }

  Promise.all(model_loader_promises)


    .then((loaded_models) => {

      let blob_promises = [];
      loaded_models.forEach(function(loaded_gltf, index)...