+#ifdef THREE_TEX
+ // The albedo may be defined from a base texture or a flat color
+#ifdef BASECOLOR_TEX
+ lowp vec4 baseColor = texture(sAlbedoAlpha, vUV);
+ baseColor = vec4(linear(baseColor.rgb), baseColor.w) * uColorFactor;
+#else // BASECOLOR_TEX
+ lowp vec4 baseColor = vColor * uColorFactor;
+#endif // BASECOLOR_TEX
+
+#ifdef METALLIC_ROUGHNESS_TEX
+ lowp vec4 metrou = texture(sMetalRoughness, vUV);
+ metallic = metrou.METALLIC * metallic;
+ perceptualRoughness = metrou.ROUGHNESS * perceptualRoughness;
+#endif // METALLIC_ROUGHNESS_TEX
+
+#ifdef NORMAL_TEX
+ n = texture(sNormal, vUV).rgb;
+ n = normalize(vTBN * ((2.0 * n - 1.0) * vec3(uNormalScale, uNormalScale, 1.0)));
+#endif // NORMAL_TEX
+#else // THREE_TEX
+ vec4 albedoMetal = texture(sAlbedoMetal, vUV);
+ lowp vec4 baseColor = vec4(linear(albedoMetal.rgb), 1.0) * vColor * uColorFactor;
+
+ metallic = albedoMetal.METALLIC * metallic;
+
+ vec4 normalRoughness = texture(sNormalRoughness, vUV);
+ perceptualRoughness = normalRoughness.ROUGHNESS * perceptualRoughness;
+
+ n = normalRoughness.rgb;
+ n = normalize(vTBN * ((2.0 * n - 1.0) * vec3(uNormalScale, uNormalScale, 1.0)));
+#endif // THREE_TEX
+
+ // The value of uOpaque and uMask can be 0.0 or 1.0.
+ // If uOpaque is 1.0, alpha value of final color is 1.0;
+ // If uOpaque is 0.0 and uMask is 1.0, alpha value of final color is 0.0 when input alpha is lower than uAlphaThreshold or
+ // 1.0 when input alpha is larger than uAlphaThreshold.
+ // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_material_alphamode
+ baseColor.a = mix(baseColor.a, 1.0, uOpaque);
+ baseColor.a = min(mix(baseColor.a, floor(baseColor.a - uAlphaThreshold + 1.0), uMask), 1.0);
+
+ metallic = clamp(metallic, 0.0, 1.0);
+ // Roughness is authored as perceptual roughness; as is convention,
+ // convert to material roughness by squaring the perceptual roughness [2].
+ perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
+ lowp float alphaRoughness = perceptualRoughness * perceptualRoughness;
+
+ lowp vec3 f0 = vec3(0.04);
+ lowp vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
+ diffuseColor *= (1.0 - metallic);
+ lowp vec3 specularColor = mix(f0, baseColor.rgb, metallic);
+
+ // Compute reflectance.
+ lowp float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
+
+ // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
+ // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
+ lowp float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
+ lowp vec3 specularEnvironmentR0 = specularColor.rgb;
+ lowp vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
+
+ mediump vec3 v = normalize(vPositionToCamera); // Vector from surface point to camera
+ mediump float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
+ mediump vec3 reflection = -normalize(reflect(v, n));
+
+ lowp vec3 color = vec3(0.0);
+ lowp vec3 diffuseLight = linear(texture(sDiffuseEnvSampler, n).rgb);
+ lowp vec3 specularLight = linear(texture(sSpecularEnvSampler, reflection).rgb);
+ // retrieve a scale and bias to F0. See [1], Figure 3
+ lowp vec3 brdf = linear(texture(sbrdfLUT, vec2(NdotV, 1.0 - perceptualRoughness)).rgb);
+
+ lowp vec3 diffuse = diffuseLight * diffuseColor;
+ lowp vec3 specular = specularLight * (specularColor * brdf.x + brdf.y);
+ color += (diffuse + specular) * uIblIntensity;