Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support glTF Specular Glossiness Extension #7006

Merged
merged 16 commits into from
Sep 17, 2018
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Change Log
==========

### 1.50 - 2018-10-01

##### Additions :tada:
* Added support for glTF extension [KHR_materials_pbrSpecularGlossiness](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness) [#7006](https://github.com/AnalyticalGraphicsInc/cesium/pull/7006).

### 1.48 - 2018-08-01

##### Additions :tada:
Expand Down
3 changes: 2 additions & 1 deletion Source/Scene/ModelUtility.js
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,8 @@ define([
'KHR_draco_mesh_compression' : true,
'KHR_materials_common' : true,
'KHR_techniques_webgl' : true,
'WEB3D_quantized_attributes' : true
'KHR_materials_pbrSpecularGlossiness' : true,
'WEB3D_quantized_attributes' : true,
};

ModelUtility.checkSupportedExtensions = function(extensionsRequired) {
Expand Down
117 changes: 96 additions & 21 deletions Source/Scene/processPbrMetallicRoughness.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ define([
defined(material.doubleSided);
}

function isSpecularGlossinessMaterial(material) {
return defined(material.extensions) &&
defined(material.extensions.KHR_materials_pbrSpecularGlossiness);
}

function generateTechnique(gltf, material, materialIndex, generatedMaterialValues, primitiveByMaterial, options) {
var addBatchIdToGeneratedShaders = defaultValue(options.addBatchIdToGeneratedShaders, false);

Expand All @@ -107,16 +112,29 @@ define([
var shaders = techniquesWebgl.shaders;
var programs = techniquesWebgl.programs;

var useSpecGloss = isSpecularGlossinessMaterial(material);

var uniformName;
var pbrMetallicRoughness = material.pbrMetallicRoughness;
if (defined(pbrMetallicRoughness)) {
if (defined(pbrMetallicRoughness) && !useSpecGloss) {
for (var parameterName in pbrMetallicRoughness) {
if (pbrMetallicRoughness.hasOwnProperty(parameterName)) {
uniformName = 'u_' + parameterName;
generatedMaterialValues[uniformName] = pbrMetallicRoughness[parameterName];
}
}
}

if (useSpecGloss) {
var pbrSpecularGlossiness = material.extensions.KHR_materials_pbrSpecularGlossiness;
for (var parameterName in pbrSpecularGlossiness) {
if (pbrSpecularGlossiness.hasOwnProperty(parameterName)) {
uniformName = 'u_' + parameterName;
generatedMaterialValues[uniformName] = pbrSpecularGlossiness[parameterName];
}
}
}

for (var additional in material) {
if (material.hasOwnProperty(additional) && ((additional.indexOf('Texture') >= 0) || additional.indexOf('Factor') >= 0)) {
uniformName = 'u_' + additional;
Expand Down Expand Up @@ -531,29 +549,67 @@ define([
fragmentShader += ' vec3 baseColor = baseColorWithAlpha.rgb;\n';

if (hasNormals) {
// Add metallic-roughness to fragment shader
if (defined(generatedMaterialValues.u_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(generatedMaterialValues.u_metallicFactor)) {
fragmentShader += ' metalness *= u_metallicFactor;\n';
}
if (defined(generatedMaterialValues.u_roughnessFactor)) {
fragmentShader += ' roughness *= u_roughnessFactor;\n';
if (useSpecGloss) {
if (defined(generatedMaterialValues.u_specularGlossinessTexture)) {
fragmentShader += ' vec4 specularGlossiness = SRGBtoLINEAR4(texture2D(u_specularGlossinessTexture, ' + v_texcoord + '));\n';
fragmentShader += ' vec3 specular = specularGlossiness.rgb;\n';
fragmentShader += ' float glossiness = specularGlossiness.a;\n';
if (defined(generatedMaterialValues.u_specularFactor)) {
fragmentShader += ' specular *= u_specularFactor;\n';
}
if (defined(generatedMaterialValues.u_glossinessFactor)) {
fragmentShader += ' glossiness *= u_glossinessFactor;\n';
}
} else {
if (defined(generatedMaterialValues.u_specularFactor)) {
fragmentShader += ' vec3 specular = clamp(u_specularFactor, vec3(0.0), vec3(1.0));\n';
} else {
fragmentShader += ' vec3 specular = vec3(1.0);\n';
}
if (defined(generatedMaterialValues.u_glossinessFactor)) {
fragmentShader += ' float glossiness *= clamp(u_glossinessFactor, 0.0, 1.0);\n';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have float glossiness *= here, that doesn't compile.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried fixing this locally by removing the *. This works and shows my SpecGlossVsMetalRough new test model correctly!

} else {
fragmentShader += ' float glossiness = 1.0;\n';
}
}
} else {
if (defined(generatedMaterialValues.u_metallicFactor)) {
fragmentShader += ' float metalness = clamp(u_metallicFactor, 0.0, 1.0);\n';
if (defined(generatedMaterialValues.u_diffuseTexture)) {
fragmentShader += ' vec4 diffuse = SRGBtoLINEAR4(texture2D(u_diffuseTexture, ' + v_texcoord + '));\n';
if (defined(generatedMaterialValues.u_diffuseFactor)) {
fragmentShader += ' diffuse *= u_diffuseFactor;\n';
}
} else {
fragmentShader += ' float metalness = 1.0;\n';
if (defined(generatedMaterialValues.u_diffuseFactor)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eslint is complaining here, make sure you're set up to run the code style tools.

fragmentShader += ' vec4 diffuse = clamp(u_diffuseFactor, vec4(0.0), vec4(1.0));\n';
} else {
fragmentShader += ' vec4 diffuse = vec4(1.0);\n';
}
}
if (defined(generatedMaterialValues.u_roughnessFactor)) {
fragmentShader += ' float roughness = clamp(u_roughnessFactor, 0.04, 1.0);\n';
} else {
// Add metallic-roughness to fragment shader
if (defined(generatedMaterialValues.u_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(generatedMaterialValues.u_metallicFactor)) {
fragmentShader += ' metalness *= u_metallicFactor;\n';
}
if (defined(generatedMaterialValues.u_roughnessFactor)) {
fragmentShader += ' roughness *= u_roughnessFactor;\n';
}
} else {
fragmentShader += ' float roughness = 1.0;\n';
if (defined(generatedMaterialValues.u_metallicFactor)) {
fragmentShader += ' float metalness = clamp(u_metallicFactor, 0.0, 1.0);\n';
} else {
fragmentShader += ' float metalness = 1.0;\n';
}
if (defined(generatedMaterialValues.u_roughnessFactor)) {
fragmentShader += ' float roughness = clamp(u_roughnessFactor, 0.04, 1.0);\n';
} else {
fragmentShader += ' float roughness = 1.0;\n';
}
}
}

fragmentShader += ' vec3 v = -normalize(v_positionEC);\n';

// Generate fragment shader's lighting block
Expand All @@ -578,9 +634,17 @@ define([
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) * (1.0 - f0);\n';
fragmentShader += ' vec3 specularColor = mix(f0, baseColor, metalness);\n';
if (useSpecGloss) {
fragmentShader += ' float alpha = pow((1.0 - glossiness), 2.0);\n';
fragmentShader += ' vec3 diffuseColor = diffuse.rgb * (1.0 - max(max(specular.r, specular.g), specular.b));\n';
fragmentShader += ' vec3 specularColor = specular;\n';
fragmentShader += ' float roughness = 1.0 - glossiness;\n';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do this above the alpha calculation on line 638 above, then you can avoid the pow and just have float alpha = roughness * roughness.

} else {
fragmentShader += ' float alpha = roughness * roughness;\n';
fragmentShader += ' vec3 diffuseColor = baseColor * (1.0 - metalness) * (1.0 - f0);\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';
Expand Down Expand Up @@ -716,6 +780,17 @@ define([
return WebGLConstants.SAMPLER_2D;
case 'u_emissiveFactor':
return WebGLConstants.FLOAT_VEC3;
// Specular Glossiness Types
case 'u_diffuseFactor':
return WebGLConstants.FLOAT_VEC4;
case 'u_specularFactor':
return WebGLConstants.FLOAT_VEC3;
case 'u_glossinessFactor':
return WebGLConstants.FLOAT;
case 'u_diffuseTexture':
return WebGLConstants.SAMPLER_2D;
case 'u_specularGlossinessTexture':
return WebGLConstants.SAMPLER_2D;
}
}

Expand Down
4 changes: 2 additions & 2 deletions Specs/Data/Models/PBR/BoomBox/BoomBox.gltf
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@
],
"images": [
{
"uri": "BoomBox_baseColor.jpg"
"uri": "BoomBox_baseColor.png"
},
{
"uri": "BoomBox_occlusionRoughnessMetallic.jpg"
"uri": "BoomBox_occlusionRoughnessMetallic.png"
},
{
"uri": "BoomBox_normal.png"
Expand Down
Binary file removed Specs/Data/Models/PBR/BoomBox/BoomBox_baseColor.jpg
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Specs/Data/Models/PBR/BoomBox/BoomBox_emissive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Specs/Data/Models/PBR/BoomBox/BoomBox_normal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading