Reducing shader compile time on scene initialization

Started a new thread with a link to the app that is now live:

@dllb is reporting some very troubling statistics though. For them it takes a whopping 15-22 seconds in firefox to load the scene after downloading.

Since last posting on this thread I managed to get it down to around 2 seconds on Firefox and 0.5 on Chrome by following @Fyrestar’s advice and essentially make it so every material uses the same constants, resulting in far fewer shaders, I run the following code on the gltf resource before adding to the scene:

var create_color_texture = (col)=>{
  /** @type {HTMLCanvasElement} */
  var canvas = document.createElement("CANVAS");
  canvas.width = canvas.height = 2;
  /** @type {CanvasRenderingContext2D } */
  var ctx = canvas.getContext("2d");
  ctx.fillStyle = col;
  ctx.fillRect(0,0,canvas.width, canvas.height);
  var tex = new THREE.CanvasTexture(canvas);
  tex.format = THREE.RGBAFormat;
  tex.wrapS = THREE.ClampToEdgeWrapping;
  tex.wrapT = THREE.ClampToEdgeWrapping;
  return tex;
};
var black_tex =  create_color_texture("black");
var white_tex =  create_color_texture("white");
var normal_tex = create_color_texture("#8080ff");

/** @param {THREE.ColorRepresentation} c */
var is_black = (c)=>{
  return c.r == 0 && c.g == 0 && c.b == 0;
}

/** @param {THREE.MeshPhysicalMaterialParameters} m */
var get_material = (m)=>{
  /** @type {THREE.MeshPhysicalMaterialParameters} */
  var props = {
    color: m.color,
    map: m.map || white_tex,
    normalMap: m.normalMap || normal_tex,
    normalScale: m.normalScale,
    emissive: m.emissive,
    emissiveMap: m.emissiveMap || (is_black(m.emissive) ? black_tex : white_tex),
    emissiveIntensity: m.emissiveIntensity,
    roughnessMap: m.roughnessMap || white_tex,
    roughness: m.roughness,
    metalnessMap: m.metalnessMap || white_tex,
    metalness: m.metalness,
    envMap: this.env_map || null,
    envMapIntensity: m.metalness ? 1 : 0,
    side: THREE.DoubleSide,
    transparent: m.transparent,
    opacity: m.opacity,
    vertexColors: true,
    flatShading:false,
  };
  var hash = JSON.stringify(Object.values(props).map(v=>{
    if (v && v.uuid) return v.uuid
    return v;
  }));
  if (!new_materials[hash]) {
    var type = (props.transmission) ? THREE.MeshPhysicalMaterial : THREE.MeshStandardMaterial;
    new_materials[hash] = new type(props);
  }
  return new_materials[hash];
}

gltf.scenes.forEach(s=>s.traverse((o)=>{
  if (o.material) {
    o.material = get_material(o.material);
  }
  if (o.geometry) {
    /** @type {THREE.BufferGeometry} */
    var geom = o.geometry;
    var attrib = geom.getAttribute('color');
    if (!attrib) {
      geom.setAttribute("color", new THREE.BufferAttribute(new Float32Array(3 * geom.attributes.position.count).fill(1), 3));
    }
  }
}));

On every machine I’ve tested it on since optimizing the shader compilation it’s been initializing much faster, so what’s going on with @dllb I have no idea.