From 899d845c96c52075a75f2e37eff1dae802884c7b Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 25 Apr 2018 17:44:11 -0400 Subject: [PATCH] Support for emissive only materials and materials without normals --- .../processPbrMetallicRoughness.js | 377 ++++++++++-------- 1 file changed, 202 insertions(+), 175 deletions(-) diff --git a/Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js b/Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js index 0734761af1aa..48dbbfea43de 100644 --- a/Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js +++ b/Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js @@ -30,7 +30,7 @@ define([ var hasPbrMetallicRoughness = false; ForEach.material(gltf, function(material) { - if (defined(material.pbrMetallicRoughness)) { + if (isPbrMaterial(material)) { hasPbrMetallicRoughness = true; } }); @@ -46,17 +46,17 @@ define([ gltf.techniques = []; } - // Pre-processing to address incompatibilities between primitives using the same materials. Handles skinning and vertex color incompatibilities. + // Pre-processing to address incompatibilities between primitives using the same materials. splitIncompatibleMaterials(gltf); ForEach.material(gltf, function(material, materialIndex) { - var pbrMetallicRoughness = material.pbrMetallicRoughness; - if (defined(pbrMetallicRoughness)) { - var technique = generateTechnique(gltf, material, materialIndex, options); - - material.values = pbrMetallicRoughness; - material.technique = technique; - delete material.pbrMetallicRoughness; + if (isPbrMaterial(material)) { + var values = {}; + var technique = generateTechnique(gltf, material, materialIndex, values, options); + gltf.materials[materialIndex] = { + values : values, + technique : technique + }; } }); @@ -68,7 +68,18 @@ define([ return gltf; } - function generateTechnique(gltf, material, materialIndex, options) { + function isPbrMaterial(material) { + return defined(material.pbrMetallicRoughness) || + defined(material.normalTexture) || + defined(material.occlusionTexture) || + defined(material.emissiveTexture) || + defined(material.emissiveFactor) || + defined(material.alphaMpde) || + defined(material.alphaCutoff) || + defined(material.doubleSided); + } + + function generateTechnique(gltf, material, materialIndex, values, options) { var optimizeForCesium = defaultValue(options.optimizeForCesium, false); var hasCesiumRTCExtension = defined(gltf.extensions) && defined(gltf.extensions.CESIUM_RTC); var addBatchIdToGeneratedShaders = defaultValue(options.addBatchIdToGeneratedShaders, false); @@ -77,7 +88,15 @@ define([ var shaders = gltf.shaders; var programs = gltf.programs; - var parameterValues = material.pbrMetallicRoughness; + var parameterValues = values; + var pbrMetallicRoughness = material.pbrMetallicRoughness; + if (defined(pbrMetallicRoughness)) { + for (var parameterName in pbrMetallicRoughness) { + if (pbrMetallicRoughness.hasOwnProperty(parameterName)) { + parameterValues[parameterName] = pbrMetallicRoughness[parameterName]; + } + } + } for (var additional in material) { if (material.hasOwnProperty(additional) && ((additional.indexOf('Texture') >= 0) || additional.indexOf('Factor') >= 0) || additional === 'doubleSided') { parameterValues[additional] = material[additional]; @@ -98,31 +117,29 @@ define([ var skinningInfo; var hasSkinning = false; var hasVertexColors = false; + var hasMorphTargets = false; + var hasNormals = false; + var hasTangents = false; + var hasTexCoords = false; if (defined(primitiveInfo)) { skinningInfo = primitiveInfo.skinning; hasSkinning = skinningInfo.skinned && (joints.length > 0); hasVertexColors = primitiveInfo.hasVertexColors; + hasMorphTargets = primitiveInfo.hasMorphTargets; + hasNormals = primitiveInfo.hasNormals; + hasTangents = primitiveInfo.hasTangents; + hasTexCoords = primitiveInfo.hasTexCoords; } - var hasNormals = true; - var hasTangents = false; - var hasMorphTargets = false; var morphTargets; ForEach.mesh(gltf, function(mesh) { ForEach.meshPrimitive(mesh, function(primitive) { if (primitive.material === materialIndex) { var targets = primitive.targets; - if (!hasMorphTargets && defined(targets)) { - hasMorphTargets = true; + if (defined(targets)) { morphTargets = targets; } - var attributes = primitive.attributes; - for (var attribute in attributes) { - if (attribute.indexOf('TANGENT') >= 0) { - hasTangents = true; - } - } } }); }); @@ -164,16 +181,10 @@ define([ } // Add material parameters - var hasTexCoords = false; for (var name in parameterValues) { - //generate shader parameters if (parameterValues.hasOwnProperty(name)) { - var valType = getPBRValueType(name); - if (!hasTexCoords && (valType === WebGLConstants.SAMPLER_2D)) { - hasTexCoords = true; - } techniqueParameters[name] = { - type : valType + type : getPBRValueType(name) }; } } @@ -237,9 +248,11 @@ define([ type : WebGLConstants.FLOAT_VEC3 }; vertexShader += 'attribute vec3 a_position;\n'; - vertexShader += 'varying vec3 v_positionEC;\n'; - if (optimizeForCesium) { - vertexShader += 'varying vec3 v_positionWC;\n'; + if (hasNormals) { + vertexShader += 'varying vec3 v_positionEC;\n'; + if (optimizeForCesium) { + vertexShader += 'varying vec3 v_positionWC;\n'; + } } // Morph Target Weighting @@ -280,16 +293,14 @@ define([ } else { vertexShaderMain += ' vec4 position = vec4(weightedPosition, 1.0);\n'; } - if (optimizeForCesium) { + if (hasNormals && optimizeForCesium) { vertexShaderMain += ' v_positionWC = (czm_model * position).xyz;\n'; } vertexShaderMain += ' position = u_modelViewMatrix * position;\n'; - vertexShaderMain += ' v_positionEC = position.xyz;\n'; - vertexShaderMain += ' gl_Position = u_projectionMatrix * position;\n'; - fragmentShader += 'varying vec3 v_positionEC;\n'; - if (optimizeForCesium) { - fragmentShader += 'varying vec3 v_positionWC;\n'; + if (hasNormals) { + vertexShaderMain += ' v_positionEC = position.xyz;\n'; } + vertexShaderMain += ' gl_Position = u_projectionMatrix * position;\n'; // Final normal computation if (hasNormals) { @@ -307,6 +318,11 @@ define([ } fragmentShader += 'varying vec3 v_normal;\n'; + fragmentShader += 'varying vec3 v_positionEC;\n'; + + if (optimizeForCesium) { + fragmentShader += 'varying vec3 v_positionWC;\n'; + } } // Read tangents if available @@ -387,40 +403,42 @@ define([ vertexShader += '}\n'; // Fragment shader lighting - fragmentShader += 'const float M_PI = 3.141592653589793;\n'; - - fragmentShader += 'vec3 lambertianDiffuse(vec3 baseColor) \n' + - '{\n' + - ' return baseColor / M_PI;\n' + - '}\n\n'; - - fragmentShader += 'vec3 fresnelSchlick2(vec3 f0, vec3 f90, float VdotH) \n' + - '{\n' + - ' return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0);\n' + - '}\n\n'; - - fragmentShader += 'vec3 fresnelSchlick(float metalness, float VdotH) \n' + - '{\n' + - ' return metalness + (vec3(1.0) - metalness) * pow(1.0 - VdotH, 5.0);\n' + - '}\n\n'; - - fragmentShader += 'float smithVisibilityG1(float NdotV, float roughness) \n' + - '{\n' + - ' float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;\n' + - ' return NdotV / (NdotV * (1.0 - k) + k);\n' + - '}\n\n'; - - fragmentShader += 'float smithVisibilityGGX(float roughness, float NdotL, float NdotV) \n' + - '{\n' + - ' return smithVisibilityG1(NdotL, roughness) * smithVisibilityG1(NdotV, roughness);\n' + - '}\n\n'; - - fragmentShader += 'float GGX(float roughness, float NdotH) \n' + - '{\n' + - ' float roughnessSquared = roughness * roughness;\n' + - ' float f = (NdotH * roughnessSquared - NdotH) * NdotH + 1.0;\n' + - ' return roughnessSquared / (M_PI * f * f);\n' + - '}\n\n'; + if (hasNormals) { + fragmentShader += 'const float M_PI = 3.141592653589793;\n'; + + fragmentShader += 'vec3 lambertianDiffuse(vec3 baseColor) \n' + + '{\n' + + ' return baseColor / M_PI;\n' + + '}\n\n'; + + fragmentShader += 'vec3 fresnelSchlick2(vec3 f0, vec3 f90, float VdotH) \n' + + '{\n' + + ' return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0);\n' + + '}\n\n'; + + fragmentShader += 'vec3 fresnelSchlick(float metalness, float VdotH) \n' + + '{\n' + + ' return metalness + (vec3(1.0) - metalness) * pow(1.0 - VdotH, 5.0);\n' + + '}\n\n'; + + fragmentShader += 'float smithVisibilityG1(float NdotV, float roughness) \n' + + '{\n' + + ' float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;\n' + + ' return NdotV / (NdotV * (1.0 - k) + k);\n' + + '}\n\n'; + + fragmentShader += 'float smithVisibilityGGX(float roughness, float NdotL, float NdotV) \n' + + '{\n' + + ' return smithVisibilityG1(NdotL, roughness) * smithVisibilityG1(NdotV, roughness);\n' + + '}\n\n'; + + fragmentShader += 'float GGX(float roughness, float NdotH) \n' + + '{\n' + + ' float roughnessSquared = roughness * roughness;\n' + + ' float f = (NdotH * roughnessSquared - NdotH) * NdotH + 1.0;\n' + + ' return roughnessSquared / (M_PI * f * f);\n' + + '}\n\n'; + } fragmentShader += 'void main(void) \n{\n'; @@ -477,6 +495,9 @@ define([ } else { if (defined(parameterValues.baseColorFactor)) { fragmentShader += ' vec4 baseColorWithAlpha = u_baseColorFactor;\n'; + } else if (!hasNormals && (defined(parameterValues.emissiveFactor) || defined(parameterValues.emissiveTexture))) { + // Don't use the default base color of (1,1,1) if the material is emissive only. This handling will be better once we support KHR_materials_unlit. + fragmentShader += ' vec4 baseColorWithAlpha = vec4(vec3(0.0), 1.0);\n'; } else { fragmentShader += ' vec4 baseColorWithAlpha = vec4(1.0);\n'; } @@ -487,102 +508,107 @@ define([ } fragmentShader += ' vec3 baseColor = baseColorWithAlpha.rgb;\n'; - // Add metallic-roughness to fragment shader - if (defined(parameterValues.metallicRoughnessTexture)) { - fragmentShader += ' vec3 metallicRoughness = texture2D(u_metallicRoughnessTexture, ' + v_texcoord + ').rgb;\n'; - fragmentShader += ' float metalness = clamp(metallicRoughness.b, 0.0, 1.0);\n'; - fragmentShader += ' float roughness = clamp(metallicRoughness.g, 0.04, 1.0);\n'; - if (defined(parameterValues.metallicFactor)) { - fragmentShader += ' metalness *= u_metallicFactor;\n'; - } - if (defined(parameterValues.roughnessFactor)) { - fragmentShader += ' roughness *= u_roughnessFactor;\n'; + + if (hasNormals) { + // Add metallic-roughness to fragment shader + if (defined(parameterValues.metallicRoughnessTexture)) { + fragmentShader += ' vec3 metallicRoughness = texture2D(u_metallicRoughnessTexture, ' + v_texcoord + ').rgb;\n'; + fragmentShader += ' float metalness = clamp(metallicRoughness.b, 0.0, 1.0);\n'; + fragmentShader += ' float roughness = clamp(metallicRoughness.g, 0.04, 1.0);\n'; + if (defined(parameterValues.metallicFactor)) { + fragmentShader += ' metalness *= u_metallicFactor;\n'; + } + if (defined(parameterValues.roughnessFactor)) { + fragmentShader += ' roughness *= u_roughnessFactor;\n'; + } + } else { + if (defined(parameterValues.metallicFactor)) { + fragmentShader += ' float metalness = clamp(u_metallicFactor, 0.0, 1.0);\n'; + } else { + fragmentShader += ' float metalness = 1.0;\n'; + } + if (defined(parameterValues.roughnessFactor)) { + fragmentShader += ' float roughness = clamp(u_roughnessFactor, 0.04, 1.0);\n'; + } else { + fragmentShader += ' float roughness = 1.0;\n'; + } } - } else { - if (defined(parameterValues.metallicFactor)) { - fragmentShader += ' float metalness = clamp(u_metallicFactor, 0.0, 1.0);\n'; + + // Generate fragment shader's lighting block + fragmentShader += ' vec3 v = -normalize(v_positionEC);\n'; + fragmentShader += ' vec3 lightColor = vec3(1.0, 1.0, 1.0);\n'; + if (optimizeForCesium) { + fragmentShader += ' vec3 l = normalize(czm_sunDirectionEC);\n'; } else { - fragmentShader += ' float metalness = 1.0;\n'; + fragmentShader += ' vec3 l = vec3(0.0, 0.0, 1.0);\n'; } - if (defined(parameterValues.roughnessFactor)) { - fragmentShader += ' float roughness = clamp(u_roughnessFactor, 0.04, 1.0);\n'; + fragmentShader += ' vec3 h = normalize(v + l);\n'; + if (optimizeForCesium) { + fragmentShader += ' vec3 r = normalize(czm_inverseViewRotation * normalize(reflect(v, n)));\n'; + // Figure out if the reflection vector hits the ellipsoid + fragmentShader += ' czm_ellipsoid ellipsoid = czm_getWgs84EllipsoidEC();\n'; + fragmentShader += ' float vertexRadius = length(v_positionWC);\n'; + fragmentShader += ' float horizonDotNadir = 1.0 - ellipsoid.radii.x / vertexRadius;\n'; + fragmentShader += ' float reflectionDotNadir = dot(r, normalize(v_positionWC));\n'; + // Flipping the X vector is a cheap way to get the inverse of czm_temeToPseudoFixed, since that's a rotation about Z. + fragmentShader += ' r.x = -r.x;\n'; + fragmentShader += ' r = -normalize(czm_temeToPseudoFixed * r);\n'; + fragmentShader += ' r.x = -r.x;\n'; } else { - fragmentShader += ' float roughness = 1.0;\n'; + fragmentShader += ' vec3 r = normalize(reflect(v, n));\n'; + } + fragmentShader += ' float NdotL = clamp(dot(n, l), 0.001, 1.0);\n'; + fragmentShader += ' float NdotV = abs(dot(n, v)) + 0.001;\n'; + fragmentShader += ' float NdotH = clamp(dot(n, h), 0.0, 1.0);\n'; + fragmentShader += ' float LdotH = clamp(dot(l, h), 0.0, 1.0);\n'; + fragmentShader += ' float VdotH = clamp(dot(v, h), 0.0, 1.0);\n'; + + fragmentShader += ' vec3 f0 = vec3(0.04);\n'; + fragmentShader += ' float alpha = roughness * roughness;\n'; + fragmentShader += ' vec3 diffuseColor = baseColor * (1.0 - metalness);\n'; + fragmentShader += ' vec3 specularColor = mix(f0, baseColor, metalness);\n'; + fragmentShader += ' float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n'; + fragmentShader += ' vec3 r90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0));\n'; + fragmentShader += ' vec3 r0 = specularColor.rgb;\n'; + + fragmentShader += ' vec3 F = fresnelSchlick2(r0, r90, VdotH);\n'; + fragmentShader += ' float G = smithVisibilityGGX(alpha, NdotL, NdotV);\n'; + fragmentShader += ' float D = GGX(alpha, NdotH);\n'; + + fragmentShader += ' vec3 diffuseContribution = (1.0 - F) * lambertianDiffuse(baseColor);\n'; + fragmentShader += ' vec3 specularContribution = F * G * D / (4.0 * NdotL * NdotV);\n'; + fragmentShader += ' vec3 color = NdotL * lightColor * (diffuseContribution + specularContribution);\n'; + + if (optimizeForCesium) { + fragmentShader += ' float inverseRoughness = 1.0 - roughness;\n'; + fragmentShader += ' inverseRoughness *= inverseRoughness;\n'; + fragmentShader += ' vec3 sceneSkyBox = textureCube(czm_environmentMap, r).rgb * inverseRoughness;\n'; + + fragmentShader += ' float atmosphereHeight = 0.05;\n'; + fragmentShader += ' float blendRegionSize = 0.1 * ((1.0 - inverseRoughness) * 8.0 + 1.1 - horizonDotNadir);\n'; + fragmentShader += ' float farAboveHorizon = clamp(horizonDotNadir - blendRegionSize * 0.5, 1.0e-10 - blendRegionSize, 0.99999);\n'; + fragmentShader += ' float aroundHorizon = clamp(horizonDotNadir + blendRegionSize * 0.5, 1.0e-10 - blendRegionSize, 0.99999);\n'; + fragmentShader += ' float farBelowHorizon = clamp(horizonDotNadir + blendRegionSize * 1.5, 1.0e-10 - blendRegionSize, 0.99999);\n'; + fragmentShader += ' float smoothstepHeight = smoothstep(0.0, atmosphereHeight, horizonDotNadir);\n'; + fragmentShader += ' float lightScale = smoothstepHeight * 1.5 + 1.0;\n'; + + fragmentShader += ' vec3 diffuseIrradiance = mix(vec3(0.5), vec3(0.05), smoothstepHeight);\n'; + fragmentShader += ' vec3 belowHorizonColor = mix(vec3(0.1, 0.2, 0.4), vec3(0.2, 0.5, 0.7), smoothstepHeight);\n'; + fragmentShader += ' vec3 nadirColor = belowHorizonColor * 0.5;\n'; + fragmentShader += ' vec3 aboveHorizonColor = vec3(0.8, 0.9, 0.95);\n'; + fragmentShader += ' vec3 blueSkyColor = mix(vec3(0.09, 0.13, 0.24), aboveHorizonColor, reflectionDotNadir * inverseRoughness * 0.5 + 0.5);\n'; + fragmentShader += ' vec3 zenithColor = mix(blueSkyColor, sceneSkyBox, smoothstepHeight);\n'; + + fragmentShader += ' vec3 specularIrradiance = mix(zenithColor, aboveHorizonColor, smoothstep(farAboveHorizon, aroundHorizon, reflectionDotNadir) * inverseRoughness);\n'; + fragmentShader += ' specularIrradiance = mix(specularIrradiance, belowHorizonColor, smoothstep(aroundHorizon, farBelowHorizon, reflectionDotNadir) * inverseRoughness);\n'; + fragmentShader += ' specularIrradiance = mix(specularIrradiance, nadirColor, smoothstep(farBelowHorizon, 1.0, reflectionDotNadir) * inverseRoughness);\n'; + + fragmentShader += ' vec2 brdfLut = texture2D(czm_brdfLut, vec2(NdotV, 1.0 - roughness)).rg;\n'; + fragmentShader += ' vec3 IBLColor = (diffuseIrradiance * diffuseColor) + (specularIrradiance * (specularColor * brdfLut.x + brdfLut.y));\n'; + fragmentShader += ' color = color * lightScale + IBLColor;\n'; } - } - fragmentShader += ' vec3 v = -normalize(v_positionEC);\n'; - - // Generate fragment shader's lighting block - fragmentShader += ' vec3 lightColor = vec3(1.0, 1.0, 1.0);\n'; - if (optimizeForCesium) { - fragmentShader += ' vec3 l = normalize(czm_sunDirectionEC);\n'; - } else { - fragmentShader += ' vec3 l = vec3(0.0, 0.0, 1.0);\n'; - } - fragmentShader += ' vec3 h = normalize(v + l);\n'; - if (optimizeForCesium) { - fragmentShader += ' vec3 r = normalize(czm_inverseViewRotation * normalize(reflect(v, n)));\n'; - // Figure out if the reflection vector hits the ellipsoid - fragmentShader += ' czm_ellipsoid ellipsoid = czm_getWgs84EllipsoidEC();\n'; - fragmentShader += ' float vertexRadius = length(v_positionWC);\n'; - fragmentShader += ' float horizonDotNadir = 1.0 - ellipsoid.radii.x / vertexRadius;\n'; - fragmentShader += ' float reflectionDotNadir = dot(r, normalize(v_positionWC));\n'; - // Flipping the X vector is a cheap way to get the inverse of czm_temeToPseudoFixed, since that's a rotation about Z. - fragmentShader += ' r.x = -r.x;\n'; - fragmentShader += ' r = -normalize(czm_temeToPseudoFixed * r);\n'; - fragmentShader += ' r.x = -r.x;\n'; } else { - fragmentShader += ' vec3 r = normalize(reflect(v, n));\n'; - } - fragmentShader += ' float NdotL = clamp(dot(n, l), 0.001, 1.0);\n'; - fragmentShader += ' float NdotV = abs(dot(n, v)) + 0.001;\n'; - fragmentShader += ' float NdotH = clamp(dot(n, h), 0.0, 1.0);\n'; - fragmentShader += ' float LdotH = clamp(dot(l, h), 0.0, 1.0);\n'; - fragmentShader += ' float VdotH = clamp(dot(v, h), 0.0, 1.0);\n'; - - fragmentShader += ' vec3 f0 = vec3(0.04);\n'; - fragmentShader += ' float alpha = roughness * roughness;\n'; - fragmentShader += ' vec3 diffuseColor = baseColor * (1.0 - metalness);\n'; - fragmentShader += ' vec3 specularColor = mix(f0, baseColor, metalness);\n'; - fragmentShader += ' float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n'; - fragmentShader += ' vec3 r90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0));\n'; - fragmentShader += ' vec3 r0 = specularColor.rgb;\n'; - - fragmentShader += ' vec3 F = fresnelSchlick2(r0, r90, VdotH);\n'; - fragmentShader += ' float G = smithVisibilityGGX(alpha, NdotL, NdotV);\n'; - fragmentShader += ' float D = GGX(alpha, NdotH);\n'; - - fragmentShader += ' vec3 diffuseContribution = (1.0 - F) * lambertianDiffuse(baseColor);\n'; - fragmentShader += ' vec3 specularContribution = F * G * D / (4.0 * NdotL * NdotV);\n'; - fragmentShader += ' vec3 color = NdotL * lightColor * (diffuseContribution + specularContribution);\n'; - - if (optimizeForCesium) { - fragmentShader += ' float inverseRoughness = 1.0 - roughness;\n'; - fragmentShader += ' inverseRoughness *= inverseRoughness;\n'; - fragmentShader += ' vec3 sceneSkyBox = textureCube(czm_environmentMap, r).rgb * inverseRoughness;\n'; - - fragmentShader += ' float atmosphereHeight = 0.05;\n'; - fragmentShader += ' float blendRegionSize = 0.1 * ((1.0 - inverseRoughness) * 8.0 + 1.1 - horizonDotNadir);\n'; - fragmentShader += ' float farAboveHorizon = clamp(horizonDotNadir - blendRegionSize * 0.5, 1.0e-10 - blendRegionSize, 0.99999);\n'; - fragmentShader += ' float aroundHorizon = clamp(horizonDotNadir + blendRegionSize * 0.5, 1.0e-10 - blendRegionSize, 0.99999);\n'; - fragmentShader += ' float farBelowHorizon = clamp(horizonDotNadir + blendRegionSize * 1.5, 1.0e-10 - blendRegionSize, 0.99999);\n'; - fragmentShader += ' float smoothstepHeight = smoothstep(0.0, atmosphereHeight, horizonDotNadir);\n'; - fragmentShader += ' float lightScale = smoothstepHeight * 1.5 + 1.0;\n'; - - fragmentShader += ' vec3 diffuseIrradiance = mix(vec3(0.5), vec3(0.05), smoothstepHeight);\n'; - fragmentShader += ' vec3 belowHorizonColor = mix(vec3(0.1, 0.2, 0.4), vec3(0.2, 0.5, 0.7), smoothstepHeight);\n'; - fragmentShader += ' vec3 nadirColor = belowHorizonColor * 0.5;\n'; - fragmentShader += ' vec3 aboveHorizonColor = vec3(0.8, 0.9, 0.95);\n'; - fragmentShader += ' vec3 blueSkyColor = mix(vec3(0.09, 0.13, 0.24), aboveHorizonColor, reflectionDotNadir * inverseRoughness * 0.5 + 0.5);\n'; - fragmentShader += ' vec3 zenithColor = mix(blueSkyColor, sceneSkyBox, smoothstepHeight);\n'; - - fragmentShader += ' vec3 specularIrradiance = mix(zenithColor, aboveHorizonColor, smoothstep(farAboveHorizon, aroundHorizon, reflectionDotNadir) * inverseRoughness);\n'; - fragmentShader += ' specularIrradiance = mix(specularIrradiance, belowHorizonColor, smoothstep(aroundHorizon, farBelowHorizon, reflectionDotNadir) * inverseRoughness);\n'; - fragmentShader += ' specularIrradiance = mix(specularIrradiance, nadirColor, smoothstep(farBelowHorizon, 1.0, reflectionDotNadir) * inverseRoughness);\n'; - - fragmentShader += ' vec2 brdfLut = texture2D(czm_brdfLut, vec2(NdotV, 1.0 - roughness)).rg;\n'; - fragmentShader += ' vec3 IBLColor = (diffuseIrradiance * diffuseColor) + (specularIrradiance * (specularColor * brdfLut.x + brdfLut.y));\n'; - fragmentShader += ' color = color * lightScale + IBLColor;\n'; + fragmentShader += ' vec3 color = baseColor;\n'; } if (defined(parameterValues.occlusionTexture)) { @@ -739,7 +765,7 @@ define([ var attributes = primitive.attributes; for (var target in targets) { - if (defined(target)) { + if (targets.hasOwnProperty(target)) { var targetAttributes = targets[target]; for (var attribute in targetAttributes) { if (attribute !== 'extras') { @@ -805,14 +831,9 @@ define([ var isSkinned = defined(jointAccessorId); var hasVertexColors = defined(primitive.attributes.COLOR_0); var hasMorphTargets = defined(primitive.targets); - - var hasTangents = false; - var attributes = primitive.attributes; - for (var attribute in attributes) { - if (attribute.indexOf('TANGENT') >= 0) { - hasTangents = true; - } - } + var hasNormals = defined(primitive.attributes.NORMAL); + var hasTangents = defined(primitive.attributes.TANGENT); + var hasTexCoords = defined(primitive.attributes.TEXCOORD_0); var primitiveInfo = material.extras._pipeline.primitive; if (!defined(primitiveInfo)) { @@ -824,17 +845,21 @@ define([ }, hasVertexColors : hasVertexColors, hasMorphTargets : hasMorphTargets, - hasTangents : hasTangents + hasNormals : hasNormals, + hasTangents : hasTangents, + hasTexCoords : hasTexCoords }; } else if ((primitiveInfo.skinning.skinned !== isSkinned) || (primitiveInfo.skinning.type !== type) || (primitiveInfo.hasVertexColors !== hasVertexColors) || (primitiveInfo.hasMorphTargets !== hasMorphTargets) || - (primitiveInfo.hasTangents !== hasTangents)) { + (primitiveInfo.hasNormals !== hasNormals) || + (primitiveInfo.hasTangents !== hasTangents) || + (primitiveInfo.hasTexCoords !== hasTexCoords)) { // This primitive uses the same material as another one that either: // * Isn't skinned // * Uses a different type to store joints and weights - // * Doesn't have vertex colors, tangents, or morph targets + // * Doesn't have vertex colors, morph targets, normals, or tangents var clonedMaterial = clone(material, true); clonedMaterial.extras._pipeline.skinning = { skinning : { @@ -844,7 +869,9 @@ define([ }, hasVertexColors : hasVertexColors, hasMorphTargets : hasMorphTargets, - hasTangents : hasTangents + hasNormals : hasNormals, + hasTangents : hasTangents, + hasTexCoords : hasTexCoords }; // Split this off as a separate material materialId = addToArray(materials, clonedMaterial);