| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872 | import defaultValue from "../Core/defaultValue.js";import defined from "../Core/defined.js";import WebGLConstants from "../Core/WebGLConstants.js";import webGLConstantToGlslType from "../Core/webGLConstantToGlslType.js";import addToArray from "./GltfPipeline/addToArray.js";import ForEach from "./GltfPipeline/ForEach.js";import usesExtension from "./GltfPipeline/usesExtension.js";import ModelUtility from "./ModelUtility.js";/** * @private */function processModelMaterialsCommon(gltf, options) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  if (!defined(gltf)) {    return;  }  if (!usesExtension(gltf, "KHR_materials_common")) {    return;  }  if (!usesExtension(gltf, "KHR_techniques_webgl")) {    if (!defined(gltf.extensions)) {      gltf.extensions = {};    }    gltf.extensions.KHR_techniques_webgl = {      programs: [],      shaders: [],      techniques: [],    };    gltf.extensionsUsed.push("KHR_techniques_webgl");    gltf.extensionsRequired.push("KHR_techniques_webgl");  }  const techniquesWebgl = gltf.extensions.KHR_techniques_webgl;  lightDefaults(gltf);  const lightParameters = generateLightParameters(gltf);  const primitiveByMaterial = ModelUtility.splitIncompatibleMaterials(gltf);  const techniques = {};  let generatedTechniques = false;  ForEach.material(gltf, function (material, materialIndex) {    if (      defined(material.extensions) &&      defined(material.extensions.KHR_materials_common)    ) {      const khrMaterialsCommon = material.extensions.KHR_materials_common;      const primitiveInfo = primitiveByMaterial[materialIndex];      const techniqueKey = getTechniqueKey(khrMaterialsCommon, primitiveInfo);      let technique = techniques[techniqueKey];      if (!defined(technique)) {        technique = generateTechnique(          gltf,          techniquesWebgl,          primitiveInfo,          khrMaterialsCommon,          lightParameters,          options.addBatchIdToGeneratedShaders        );        techniques[techniqueKey] = technique;        generatedTechniques = true;      }      const materialValues = {};      const values = khrMaterialsCommon.values;      let uniformName;      for (const valueName in values) {        if (          values.hasOwnProperty(valueName) &&          valueName !== "transparent" &&          valueName !== "doubleSided"        ) {          uniformName = `u_${valueName.toLowerCase()}`;          materialValues[uniformName] = values[valueName];        }      }      material.extensions.KHR_techniques_webgl = {        technique: technique,        values: materialValues,      };      material.alphaMode = "OPAQUE";      if (khrMaterialsCommon.transparent) {        material.alphaMode = "BLEND";      }      if (khrMaterialsCommon.doubleSided) {        material.doubleSided = true;      }    }  });  if (!generatedTechniques) {    return gltf;  }  // If any primitives have semantics that aren't declared in the generated  // shaders, we want to preserve them.  ModelUtility.ensureSemanticExistence(gltf);  return gltf;}function generateLightParameters(gltf) {  const result = {};  let lights;  if (    defined(gltf.extensions) &&    defined(gltf.extensions.KHR_materials_common)  ) {    lights = gltf.extensions.KHR_materials_common.lights;  }  if (defined(lights)) {    // Figure out which node references the light    const nodes = gltf.nodes;    for (const nodeName in nodes) {      if (nodes.hasOwnProperty(nodeName)) {        const node = nodes[nodeName];        if (          defined(node.extensions) &&          defined(node.extensions.KHR_materials_common)        ) {          const nodeLightId = node.extensions.KHR_materials_common.light;          if (defined(nodeLightId) && defined(lights[nodeLightId])) {            lights[nodeLightId].node = nodeName;          }          delete node.extensions.KHR_materials_common;        }      }    }    // Add light parameters to result    let lightCount = 0;    for (const lightName in lights) {      if (lights.hasOwnProperty(lightName)) {        const light = lights[lightName];        const lightType = light.type;        if (lightType !== "ambient" && !defined(light.node)) {          delete lights[lightName];          continue;        }        const lightBaseName = `light${lightCount.toString()}`;        light.baseName = lightBaseName;        let ambient;        let directional;        let point;        let spot;        switch (lightType) {          case "ambient":            ambient = light.ambient;            result[`${lightBaseName}Color`] = {              type: WebGLConstants.FLOAT_VEC3,              value: ambient.color,            };            break;          case "directional":            directional = light.directional;            result[`${lightBaseName}Color`] = {              type: WebGLConstants.FLOAT_VEC3,              value: directional.color,            };            if (defined(light.node)) {              result[`${lightBaseName}Transform`] = {                node: light.node,                semantic: "MODELVIEW",                type: WebGLConstants.FLOAT_MAT4,              };            }            break;          case "point":            point = light.point;            result[`${lightBaseName}Color`] = {              type: WebGLConstants.FLOAT_VEC3,              value: point.color,            };            if (defined(light.node)) {              result[`${lightBaseName}Transform`] = {                node: light.node,                semantic: "MODELVIEW",                type: WebGLConstants.FLOAT_MAT4,              };            }            result[`${lightBaseName}Attenuation`] = {              type: WebGLConstants.FLOAT_VEC3,              value: [                point.constantAttenuation,                point.linearAttenuation,                point.quadraticAttenuation,              ],            };            break;          case "spot":            spot = light.spot;            result[`${lightBaseName}Color`] = {              type: WebGLConstants.FLOAT_VEC3,              value: spot.color,            };            if (defined(light.node)) {              result[`${lightBaseName}Transform`] = {                node: light.node,                semantic: "MODELVIEW",                type: WebGLConstants.FLOAT_MAT4,              };              result[`${lightBaseName}InverseTransform`] = {                node: light.node,                semantic: "MODELVIEWINVERSE",                type: WebGLConstants.FLOAT_MAT4,                useInFragment: true,              };            }            result[`${lightBaseName}Attenuation`] = {              type: WebGLConstants.FLOAT_VEC3,              value: [                spot.constantAttenuation,                spot.linearAttenuation,                spot.quadraticAttenuation,              ],            };            result[`${lightBaseName}FallOff`] = {              type: WebGLConstants.FLOAT_VEC2,              value: [spot.fallOffAngle, spot.fallOffExponent],            };            break;        }        ++lightCount;      }    }  }  return result;}function generateTechnique(  gltf,  techniquesWebgl,  primitiveInfo,  khrMaterialsCommon,  lightParameters,  addBatchIdToGeneratedShaders) {  if (!defined(khrMaterialsCommon)) {    khrMaterialsCommon = {};  }  addBatchIdToGeneratedShaders = defaultValue(    addBatchIdToGeneratedShaders,    false  );  const techniques = techniquesWebgl.techniques;  const shaders = techniquesWebgl.shaders;  const programs = techniquesWebgl.programs;  const lightingModel = khrMaterialsCommon.technique.toUpperCase();  let lights;  if (    defined(gltf.extensions) &&    defined(gltf.extensions.KHR_materials_common)  ) {    lights = gltf.extensions.KHR_materials_common.lights;  }  const parameterValues = khrMaterialsCommon.values;  const jointCount = defaultValue(khrMaterialsCommon.jointCount, 0);  let skinningInfo;  let hasSkinning = false;  let hasVertexColors = false;  if (defined(primitiveInfo)) {    skinningInfo = primitiveInfo.skinning;    hasSkinning = skinningInfo.skinned;    hasVertexColors = primitiveInfo.hasVertexColors;  }  let vertexShader = "precision highp float;\n";  let fragmentShader = "precision highp float;\n";  const hasNormals = lightingModel !== "CONSTANT";  // Add techniques  const techniqueUniforms = {    u_modelViewMatrix: {      semantic: usesExtension(gltf, "CESIUM_RTC")        ? "CESIUM_RTC_MODELVIEW"        : "MODELVIEW",      type: WebGLConstants.FLOAT_MAT4,    },    u_projectionMatrix: {      semantic: "PROJECTION",      type: WebGLConstants.FLOAT_MAT4,    },  };  if (hasNormals) {    techniqueUniforms.u_normalMatrix = {      semantic: "MODELVIEWINVERSETRANSPOSE",      type: WebGLConstants.FLOAT_MAT3,    };  }  if (hasSkinning) {    techniqueUniforms.u_jointMatrix = {      count: jointCount,      semantic: "JOINTMATRIX",      type: WebGLConstants.FLOAT_MAT4,    };  }  // Add material values  let uniformName;  let hasTexCoords = false;  for (const name in parameterValues) {    //generate shader parameters for KHR_materials_common attributes    //(including a check, because some boolean flags should not be used as shader parameters)    if (      parameterValues.hasOwnProperty(name) &&      name !== "transparent" &&      name !== "doubleSided"    ) {      const uniformType = getKHRMaterialsCommonValueType(        name,        parameterValues[name]      );      uniformName = `u_${name.toLowerCase()}`;      if (!hasTexCoords && uniformType === WebGLConstants.SAMPLER_2D) {        hasTexCoords = true;      }      techniqueUniforms[uniformName] = {        type: uniformType,      };    }  }  // Give the diffuse uniform a semantic to support color replacement in 3D Tiles  if (defined(techniqueUniforms.u_diffuse)) {    techniqueUniforms.u_diffuse.semantic = "_3DTILESDIFFUSE";  }  // Copy light parameters into technique parameters  if (defined(lightParameters)) {    for (const lightParamName in lightParameters) {      if (lightParameters.hasOwnProperty(lightParamName)) {        uniformName = `u_${lightParamName}`;        techniqueUniforms[uniformName] = lightParameters[lightParamName];      }    }  }  // Add uniforms to shaders  for (uniformName in techniqueUniforms) {    if (techniqueUniforms.hasOwnProperty(uniformName)) {      const uniform = techniqueUniforms[uniformName];      const arraySize = defined(uniform.count) ? `[${uniform.count}]` : "";      if (        (uniform.type !== WebGLConstants.FLOAT_MAT3 &&          uniform.type !== WebGLConstants.FLOAT_MAT4) ||        uniform.useInFragment      ) {        fragmentShader += `uniform ${webGLConstantToGlslType(          uniform.type        )} ${uniformName}${arraySize};\n`;        delete uniform.useInFragment;      } else {        vertexShader += `uniform ${webGLConstantToGlslType(          uniform.type        )} ${uniformName}${arraySize};\n`;      }    }  }  // Add attributes with semantics  let vertexShaderMain = "";  if (hasSkinning) {    vertexShaderMain +=      "    mat4 skinMatrix =\n" +      "        a_weight.x * u_jointMatrix[int(a_joint.x)] +\n" +      "        a_weight.y * u_jointMatrix[int(a_joint.y)] +\n" +      "        a_weight.z * u_jointMatrix[int(a_joint.z)] +\n" +      "        a_weight.w * u_jointMatrix[int(a_joint.w)];\n";  }  // Add position always  const techniqueAttributes = {    a_position: {      semantic: "POSITION",    },  };  vertexShader += "attribute vec3 a_position;\n";  vertexShader += "varying vec3 v_positionEC;\n";  if (hasSkinning) {    vertexShaderMain +=      "  vec4 pos = u_modelViewMatrix * skinMatrix * vec4(a_position,1.0);\n";  } else {    vertexShaderMain +=      "  vec4 pos = u_modelViewMatrix * vec4(a_position,1.0);\n";  }  vertexShaderMain += "  v_positionEC = pos.xyz;\n";  vertexShaderMain += "  gl_Position = u_projectionMatrix * pos;\n";  fragmentShader += "varying vec3 v_positionEC;\n";  // Add normal if we don't have constant lighting  if (hasNormals) {    techniqueAttributes.a_normal = {      semantic: "NORMAL",    };    vertexShader += "attribute vec3 a_normal;\n";    vertexShader += "varying vec3 v_normal;\n";    if (hasSkinning) {      vertexShaderMain +=        "  v_normal = u_normalMatrix * mat3(skinMatrix) * a_normal;\n";    } else {      vertexShaderMain += "  v_normal = u_normalMatrix * a_normal;\n";    }    fragmentShader += "varying vec3 v_normal;\n";  }  // Add texture coordinates if the material uses them  let v_texcoord;  if (hasTexCoords) {    techniqueAttributes.a_texcoord_0 = {      semantic: "TEXCOORD_0",    };    v_texcoord = "v_texcoord_0";    vertexShader += "attribute vec2 a_texcoord_0;\n";    vertexShader += `varying vec2 ${v_texcoord};\n`;    vertexShaderMain += `  ${v_texcoord} = a_texcoord_0;\n`;    fragmentShader += `varying vec2 ${v_texcoord};\n`;  }  if (hasSkinning) {    techniqueAttributes.a_joint = {      semantic: "JOINTS_0",    };    techniqueAttributes.a_weight = {      semantic: "WEIGHTS_0",    };    vertexShader += "attribute vec4 a_joint;\n";    vertexShader += "attribute vec4 a_weight;\n";  }  if (hasVertexColors) {    techniqueAttributes.a_vertexColor = {      semantic: "COLOR_0",    };    vertexShader += "attribute vec4 a_vertexColor;\n";    vertexShader += "varying vec4 v_vertexColor;\n";    vertexShaderMain += "  v_vertexColor = a_vertexColor;\n";    fragmentShader += "varying vec4 v_vertexColor;\n";  }  if (addBatchIdToGeneratedShaders) {    techniqueAttributes.a_batchId = {      semantic: "_BATCHID",    };    vertexShader += "attribute float a_batchId;\n";  }  const hasSpecular =    hasNormals &&    (lightingModel === "BLINN" || lightingModel === "PHONG") &&    defined(techniqueUniforms.u_specular) &&    defined(techniqueUniforms.u_shininess) &&    techniqueUniforms.u_shininess > 0.0;  // Generate lighting code blocks  let hasNonAmbientLights = false;  let hasAmbientLights = false;  let fragmentLightingBlock = "";  for (const lightName in lights) {    if (lights.hasOwnProperty(lightName)) {      const light = lights[lightName];      const lightType = light.type.toLowerCase();      const lightBaseName = light.baseName;      fragmentLightingBlock += "  {\n";      const lightColorName = `u_${lightBaseName}Color`;      if (lightType === "ambient") {        hasAmbientLights = true;        fragmentLightingBlock += `    ambientLight += ${lightColorName};\n`;      } else if (hasNormals) {        hasNonAmbientLights = true;        const varyingDirectionName = `v_${lightBaseName}Direction`;        const varyingPositionName = `v_${lightBaseName}Position`;        if (lightType !== "point") {          vertexShader += `varying vec3 ${varyingDirectionName};\n`;          fragmentShader += `varying vec3 ${varyingDirectionName};\n`;          vertexShaderMain += `  ${varyingDirectionName} = mat3(u_${lightBaseName}Transform) * vec3(0.,0.,1.);\n`;          if (lightType === "directional") {            fragmentLightingBlock += `    vec3 l = normalize(${varyingDirectionName});\n`;          }        }        if (lightType !== "directional") {          vertexShader += `varying vec3 ${varyingPositionName};\n`;          fragmentShader += `varying vec3 ${varyingPositionName};\n`;          vertexShaderMain += `  ${varyingPositionName} = u_${lightBaseName}Transform[3].xyz;\n`;          fragmentLightingBlock += `    vec3 VP = ${varyingPositionName} - v_positionEC;\n`;          fragmentLightingBlock += "    vec3 l = normalize(VP);\n";          fragmentLightingBlock += "    float range = length(VP);\n";          fragmentLightingBlock += `    float attenuation = 1.0 / (u_${lightBaseName}Attenuation.x + `;          fragmentLightingBlock += `(u_${lightBaseName}Attenuation.y * range) + `;          fragmentLightingBlock += `(u_${lightBaseName}Attenuation.z * range * range));\n`;        } else {          fragmentLightingBlock += "    float attenuation = 1.0;\n";        }        if (lightType === "spot") {          fragmentLightingBlock += `    float spotDot = dot(l, normalize(${varyingDirectionName}));\n`;          fragmentLightingBlock += `    if (spotDot < cos(u_${lightBaseName}FallOff.x * 0.5))\n`;          fragmentLightingBlock += "    {\n";          fragmentLightingBlock += "      attenuation = 0.0;\n";          fragmentLightingBlock += "    }\n";          fragmentLightingBlock += "    else\n";          fragmentLightingBlock += "    {\n";          fragmentLightingBlock += `        attenuation *= max(0.0, pow(spotDot, u_${lightBaseName}FallOff.y));\n`;          fragmentLightingBlock += "    }\n";        }        fragmentLightingBlock += `    diffuseLight += ${lightColorName}* max(dot(normal,l), 0.) * attenuation;\n`;        if (hasSpecular) {          if (lightingModel === "BLINN") {            fragmentLightingBlock += "    vec3 h = normalize(l + viewDir);\n";            fragmentLightingBlock +=              "    float specularIntensity = max(0., pow(max(dot(normal, h), 0.), u_shininess)) * attenuation;\n";          } else {            // PHONG            fragmentLightingBlock +=              "    vec3 reflectDir = reflect(-l, normal);\n";            fragmentLightingBlock +=              "    float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess)) * attenuation;\n";          }          fragmentLightingBlock += `    specularLight += ${lightColorName} * specularIntensity;\n`;        }      }      fragmentLightingBlock += "  }\n";    }  }  if (!hasAmbientLights) {    // Add an ambient light if we don't have one    fragmentLightingBlock += "  ambientLight += vec3(0.2, 0.2, 0.2);\n";  }  if (!hasNonAmbientLights && lightingModel !== "CONSTANT") {    fragmentShader += "#ifdef USE_CUSTOM_LIGHT_COLOR \n";    fragmentShader += "uniform vec3 gltf_lightColor; \n";    fragmentShader += "#endif \n";    fragmentLightingBlock += "#ifndef USE_CUSTOM_LIGHT_COLOR \n";    fragmentLightingBlock += "    vec3 lightColor = czm_lightColor;\n";    fragmentLightingBlock += "#else \n";    fragmentLightingBlock += "    vec3 lightColor = gltf_lightColor;\n";    fragmentLightingBlock += "#endif \n";    fragmentLightingBlock += "  vec3 l = normalize(czm_lightDirectionEC);\n";    const minimumLighting = "0.2"; // Use strings instead of values as 0.0 -> 0 when stringified    fragmentLightingBlock += `  diffuseLight += lightColor * max(dot(normal,l), ${minimumLighting});\n`;    if (hasSpecular) {      if (lightingModel === "BLINN") {        fragmentLightingBlock += "  vec3 h = normalize(l + viewDir);\n";        fragmentLightingBlock +=          "  float specularIntensity = max(0., pow(max(dot(normal, h), 0.), u_shininess));\n";      } else {        // PHONG        fragmentLightingBlock += "  vec3 reflectDir = reflect(-l, normal);\n";        fragmentLightingBlock +=          "  float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess));\n";      }      fragmentLightingBlock +=        "  specularLight += lightColor * specularIntensity;\n";    }  }  vertexShader += "void main(void) {\n";  vertexShader += vertexShaderMain;  vertexShader += "}\n";  fragmentShader += "void main(void) {\n";  let colorCreationBlock = "  vec3 color = vec3(0.0, 0.0, 0.0);\n";  if (hasNormals) {    fragmentShader += "  vec3 normal = normalize(v_normal);\n";    if (khrMaterialsCommon.doubleSided) {      fragmentShader += "  if (czm_backFacing())\n";      fragmentShader += "  {\n";      fragmentShader += "    normal = -normal;\n";      fragmentShader += "  }\n";    }  }  let finalColorComputation;  if (lightingModel !== "CONSTANT") {    if (defined(techniqueUniforms.u_diffuse)) {      if (techniqueUniforms.u_diffuse.type === WebGLConstants.SAMPLER_2D) {        fragmentShader += `  vec4 diffuse = texture2D(u_diffuse, ${v_texcoord});\n`;      } else {        fragmentShader += "  vec4 diffuse = u_diffuse;\n";      }      fragmentShader += "  vec3 diffuseLight = vec3(0.0, 0.0, 0.0);\n";      colorCreationBlock += "  color += diffuse.rgb * diffuseLight;\n";    }    if (hasSpecular) {      if (techniqueUniforms.u_specular.type === WebGLConstants.SAMPLER_2D) {        fragmentShader += `  vec3 specular = texture2D(u_specular, ${v_texcoord}).rgb;\n`;      } else {        fragmentShader += "  vec3 specular = u_specular.rgb;\n";      }      fragmentShader += "  vec3 specularLight = vec3(0.0, 0.0, 0.0);\n";      colorCreationBlock += "  color += specular * specularLight;\n";    }    if (defined(techniqueUniforms.u_transparency)) {      finalColorComputation =        "  gl_FragColor = vec4(color * diffuse.a * u_transparency, diffuse.a * u_transparency);\n";    } else {      finalColorComputation =        "  gl_FragColor = vec4(color * diffuse.a, diffuse.a);\n";    }  } else if (defined(techniqueUniforms.u_transparency)) {    finalColorComputation =      "  gl_FragColor = vec4(color * u_transparency, u_transparency);\n";  } else {    finalColorComputation = "  gl_FragColor = vec4(color, 1.0);\n";  }  if (hasVertexColors) {    colorCreationBlock += "  color *= v_vertexColor.rgb;\n";  }  if (defined(techniqueUniforms.u_emission)) {    if (techniqueUniforms.u_emission.type === WebGLConstants.SAMPLER_2D) {      fragmentShader += `  vec3 emission = texture2D(u_emission, ${v_texcoord}).rgb;\n`;    } else {      fragmentShader += "  vec3 emission = u_emission.rgb;\n";    }    colorCreationBlock += "  color += emission;\n";  }  if (defined(techniqueUniforms.u_ambient) || lightingModel !== "CONSTANT") {    if (defined(techniqueUniforms.u_ambient)) {      if (techniqueUniforms.u_ambient.type === WebGLConstants.SAMPLER_2D) {        fragmentShader += `  vec3 ambient = texture2D(u_ambient, ${v_texcoord}).rgb;\n`;      } else {        fragmentShader += "  vec3 ambient = u_ambient.rgb;\n";      }    } else {      fragmentShader += "  vec3 ambient = diffuse.rgb;\n";    }    colorCreationBlock += "  color += ambient * ambientLight;\n";  }  fragmentShader += "  vec3 viewDir = -normalize(v_positionEC);\n";  fragmentShader += "  vec3 ambientLight = vec3(0.0, 0.0, 0.0);\n";  // Add in light computations  fragmentShader += fragmentLightingBlock;  fragmentShader += colorCreationBlock;  fragmentShader += finalColorComputation;  fragmentShader += "}\n";  // Add shaders  const vertexShaderId = addToArray(shaders, {    type: WebGLConstants.VERTEX_SHADER,    extras: {      _pipeline: {        source: vertexShader,        extension: ".glsl",      },    },  });  const fragmentShaderId = addToArray(shaders, {    type: WebGLConstants.FRAGMENT_SHADER,    extras: {      _pipeline: {        source: fragmentShader,        extension: ".glsl",      },    },  });  // Add program  const programId = addToArray(programs, {    fragmentShader: fragmentShaderId,    vertexShader: vertexShaderId,  });  const techniqueId = addToArray(techniques, {    attributes: techniqueAttributes,    program: programId,    uniforms: techniqueUniforms,  });  return techniqueId;}function getKHRMaterialsCommonValueType(paramName, paramValue) {  let value;  // Backwards compatibility for COLLADA2GLTF v1.0-draft when it encoding  // materials using KHR_materials_common with explicit type/value members  if (defined(paramValue.value)) {    value = paramValue.value;  } else if (defined(paramValue.index)) {    value = [paramValue.index];  } else {    value = paramValue;  }  switch (paramName) {    case "ambient":      return value.length === 1        ? WebGLConstants.SAMPLER_2D        : WebGLConstants.FLOAT_VEC4;    case "diffuse":      return value.length === 1        ? WebGLConstants.SAMPLER_2D        : WebGLConstants.FLOAT_VEC4;    case "emission":      return value.length === 1        ? WebGLConstants.SAMPLER_2D        : WebGLConstants.FLOAT_VEC4;    case "specular":      return value.length === 1        ? WebGLConstants.SAMPLER_2D        : WebGLConstants.FLOAT_VEC4;    case "shininess":      return WebGLConstants.FLOAT;    case "transparency":      return WebGLConstants.FLOAT;    // these two are usually not used directly within shaders,    // they are just added here for completeness    case "transparent":      return WebGLConstants.BOOL;    case "doubleSided":      return WebGLConstants.BOOL;  }}function getTechniqueKey(khrMaterialsCommon, primitiveInfo) {  let techniqueKey = "";  techniqueKey += `technique:${khrMaterialsCommon.technique};`;  const values = khrMaterialsCommon.values;  const keys = Object.keys(values).sort();  const keysCount = keys.length;  for (let i = 0; i < keysCount; ++i) {    const name = keys[i];    if (values.hasOwnProperty(name)) {      techniqueKey += `${name}:${getKHRMaterialsCommonValueType(        name,        values[name]      )}`;      techniqueKey += ";";    }  }  const jointCount = defaultValue(khrMaterialsCommon.jointCount, 0);  techniqueKey += `${jointCount.toString()};`;  if (defined(primitiveInfo)) {    const skinningInfo = primitiveInfo.skinning;    if (jointCount > 0) {      techniqueKey += `${skinningInfo.type};`;    }    techniqueKey += primitiveInfo.hasVertexColors;  }  return techniqueKey;}function lightDefaults(gltf) {  const khrMaterialsCommon = gltf.extensions.KHR_materials_common;  if (!defined(khrMaterialsCommon) || !defined(khrMaterialsCommon.lights)) {    return;  }  const lights = khrMaterialsCommon.lights;  const lightsLength = lights.length;  for (let lightId = 0; lightId < lightsLength; lightId++) {    const light = lights[lightId];    if (light.type === "ambient") {      if (!defined(light.ambient)) {        light.ambient = {};      }      const ambientLight = light.ambient;      if (!defined(ambientLight.color)) {        ambientLight.color = [1.0, 1.0, 1.0];      }    } else if (light.type === "directional") {      if (!defined(light.directional)) {        light.directional = {};      }      const directionalLight = light.directional;      if (!defined(directionalLight.color)) {        directionalLight.color = [1.0, 1.0, 1.0];      }    } else if (light.type === "point") {      if (!defined(light.point)) {        light.point = {};      }      const pointLight = light.point;      if (!defined(pointLight.color)) {        pointLight.color = [1.0, 1.0, 1.0];      }      pointLight.constantAttenuation = defaultValue(        pointLight.constantAttenuation,        1.0      );      pointLight.linearAttenuation = defaultValue(        pointLight.linearAttenuation,        0.0      );      pointLight.quadraticAttenuation = defaultValue(        pointLight.quadraticAttenuation,        0.0      );    } else if (light.type === "spot") {      if (!defined(light.spot)) {        light.spot = {};      }      const spotLight = light.spot;      if (!defined(spotLight.color)) {        spotLight.color = [1.0, 1.0, 1.0];      }      spotLight.constantAttenuation = defaultValue(        spotLight.constantAttenuation,        1.0      );      spotLight.fallOffAngle = defaultValue(spotLight.fallOffAngle, 3.14159265);      spotLight.fallOffExponent = defaultValue(spotLight.fallOffExponent, 0.0);      spotLight.linearAttenuation = defaultValue(        spotLight.linearAttenuation,        0.0      );      spotLight.quadraticAttenuation = defaultValue(        spotLight.quadraticAttenuation,        0.0      );    }  }}export default processModelMaterialsCommon;
 |