Skip to content

Commit e88ac9d

Browse files
authored
Merge pull request #7006 from OmarShehata/specgloss-ext
Support glTF Specular Glossiness Extension
2 parents b137ab4 + 4d5d53f commit e88ac9d

23 files changed

+830
-51
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Change Log
44
### 1.50 - 2018-10-01
55

66
##### Additions :tada:
7+
* 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).
78
* Added support for glTF extension [KHR_materials_unlit](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit) [#6977](https://github.com/AnalyticalGraphicsInc/cesium/pull/6977).
89
* Added support for glTF extensions [KHR_techniques_webgl](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_techniques_webgl) and [KHR_blend](https://github.com/KhronosGroup/glTF/pull/1302). [#6805](https://github.com/AnalyticalGraphicsInc/cesium/pull/6805)
910
* Update [gltf-pipeline](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/) to 2.0. [#6805](https://github.com/AnalyticalGraphicsInc/cesium/pull/6805)

Source/Scene/ClassificationModel.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ define([
3030
'./ModelLoadResources',
3131
'./ModelUtility',
3232
'./processModelMaterialsCommon',
33-
'./processPbrMetallicRoughness',
33+
'./processPbrMaterials',
3434
'./SceneMode',
3535
'./Vector3DTileBatch',
3636
'./Vector3DTilePrimitive'
@@ -66,7 +66,7 @@ define([
6666
ModelLoadResources,
6767
ModelUtility,
6868
processModelMaterialsCommon,
69-
processPbrMetallicRoughness,
69+
processPbrMaterials,
7070
SceneMode,
7171
Vector3DTileBatch,
7272
Vector3DTilePrimitive) {
@@ -123,7 +123,7 @@ define([
123123
updateVersion(gltf);
124124
addDefaults(gltf);
125125
processModelMaterialsCommon(gltf);
126-
processPbrMetallicRoughness(gltf);
126+
processPbrMaterials(gltf);
127127
} else {
128128
throw new RuntimeError('Only binary glTF is supported as a classifier.');
129129
}

Source/Scene/Model.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ define([
6969
'./ModelNode',
7070
'./ModelUtility',
7171
'./processModelMaterialsCommon',
72-
'./processPbrMetallicRoughness',
72+
'./processPbrMaterials',
7373
'./SceneMode',
7474
'./ShadowMode'
7575
], function(
@@ -143,7 +143,7 @@ define([
143143
ModelNode,
144144
ModelUtility,
145145
processModelMaterialsCommon,
146-
processPbrMetallicRoughness,
146+
processPbrMaterials,
147147
SceneMode,
148148
ShadowMode) {
149149
'use strict';
@@ -4067,8 +4067,9 @@ define([
40674067
var options = {
40684068
addBatchIdToGeneratedShaders: this._addBatchIdToGeneratedShaders
40694069
};
4070+
40704071
processModelMaterialsCommon(gltf, options);
4071-
processPbrMetallicRoughness(gltf, options);
4072+
processPbrMaterials(gltf, options);
40724073
}
40734074

40744075
// Skip dequantizing in the shader if not encoded

Source/Scene/ModelUtility.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,9 @@ define([
473473
'KHR_draco_mesh_compression' : true,
474474
'KHR_materials_common' : true,
475475
'KHR_techniques_webgl' : true,
476-
'WEB3D_quantized_attributes' : true,
477-
'KHR_materials_unlit' : true
476+
'KHR_materials_unlit' : true,
477+
'KHR_materials_pbrSpecularGlossiness' : true,
478+
'WEB3D_quantized_attributes' : true
478479
};
479480

480481
ModelUtility.checkSupportedExtensions = function(extensionsRequired) {

Source/Scene/processPbrMetallicRoughness.js Source/Scene/processPbrMaterials.js

+94-40
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,21 @@ define([
2323
/**
2424
* @private
2525
*/
26-
function processPbrMetallicRoughness(gltf, options) {
26+
function processPbrMaterials(gltf, options) {
2727
options = defaultValue(options, {});
2828

29-
var hasPbrMetallicRoughness = false;
30-
ForEach.material(gltf, function(material) {
31-
if (isPbrMaterial(material)) {
32-
hasPbrMetallicRoughness = true;
33-
}
34-
});
35-
36-
if (!hasPbrMetallicRoughness) {
37-
return gltf;
38-
}
39-
4029
// No need to create new techniques if they already exist,
4130
// the shader should handle these values
4231
if (hasExtension(gltf, 'KHR_techniques_webgl')) {
4332
return gltf;
4433
}
4534

35+
// All materials in glTF are PBR by default,
36+
// so we should apply PBR unless no materials are found.
37+
if (gltf.materials.length === 0) {
38+
return gltf;
39+
}
40+
4641
if (!defined(gltf.extensions)) {
4742
gltf.extensions = {};
4843
}
@@ -60,25 +55,24 @@ define([
6055
shaders: [],
6156
techniques: []
6257
};
58+
6359
gltf.extensionsUsed.push('KHR_techniques_webgl');
6460
gltf.extensionsRequired.push('KHR_techniques_webgl');
6561

6662
var primitiveByMaterial = ModelUtility.splitIncompatibleMaterials(gltf);
6763

6864
ForEach.material(gltf, function(material, materialIndex) {
69-
if (isPbrMaterial(material)) {
70-
var generatedMaterialValues = {};
71-
var technique = generateTechnique(gltf, material, materialIndex, generatedMaterialValues, primitiveByMaterial, options);
72-
73-
if (!defined(material.extensions)) {
74-
material.extensions = {};
75-
}
65+
var generatedMaterialValues = {};
66+
var technique = generateTechnique(gltf, material, materialIndex, generatedMaterialValues, primitiveByMaterial, options);
7667

77-
material.extensions.KHR_techniques_webgl = {
78-
values : generatedMaterialValues,
79-
technique : technique
80-
};
68+
if (!defined(material.extensions)) {
69+
material.extensions = {};
8170
}
71+
72+
material.extensions.KHR_techniques_webgl = {
73+
values : generatedMaterialValues,
74+
technique : technique
75+
};
8276
});
8377

8478
// If any primitives have semantics that aren't declared in the generated
@@ -88,15 +82,9 @@ define([
8882
return gltf;
8983
}
9084

91-
function isPbrMaterial(material) {
92-
return defined(material.pbrMetallicRoughness) ||
93-
defined(material.normalTexture) ||
94-
defined(material.occlusionTexture) ||
95-
defined(material.emissiveTexture) ||
96-
defined(material.emissiveFactor) ||
97-
defined(material.alphaMode) ||
98-
defined(material.alphaCutoff) ||
99-
defined(material.doubleSided);
85+
function isSpecularGlossinessMaterial(material) {
86+
return defined(material.extensions) &&
87+
defined(material.extensions.KHR_materials_pbrSpecularGlossiness);
10088
}
10189

10290
function generateTechnique(gltf, material, materialIndex, generatedMaterialValues, primitiveByMaterial, options) {
@@ -107,16 +95,30 @@ define([
10795
var shaders = techniquesWebgl.shaders;
10896
var programs = techniquesWebgl.programs;
10997

98+
var useSpecGloss = isSpecularGlossinessMaterial(material);
99+
110100
var uniformName;
101+
var parameterName;
111102
var pbrMetallicRoughness = material.pbrMetallicRoughness;
112-
if (defined(pbrMetallicRoughness)) {
113-
for (var parameterName in pbrMetallicRoughness) {
103+
if (defined(pbrMetallicRoughness) && !useSpecGloss) {
104+
for (parameterName in pbrMetallicRoughness) {
114105
if (pbrMetallicRoughness.hasOwnProperty(parameterName)) {
115106
uniformName = 'u_' + parameterName;
116107
generatedMaterialValues[uniformName] = pbrMetallicRoughness[parameterName];
117108
}
118109
}
119110
}
111+
112+
if (useSpecGloss) {
113+
var pbrSpecularGlossiness = material.extensions.KHR_materials_pbrSpecularGlossiness;
114+
for (parameterName in pbrSpecularGlossiness) {
115+
if (pbrSpecularGlossiness.hasOwnProperty(parameterName)) {
116+
uniformName = 'u_' + parameterName;
117+
generatedMaterialValues[uniformName] = pbrSpecularGlossiness[parameterName];
118+
}
119+
}
120+
}
121+
120122
for (var additional in material) {
121123
if (material.hasOwnProperty(additional) && ((additional.indexOf('Texture') >= 0) || additional.indexOf('Factor') >= 0)) {
122124
uniformName = 'u_' + additional;
@@ -538,8 +540,40 @@ define([
538540
fragmentShader += ' vec3 baseColor = baseColorWithAlpha.rgb;\n';
539541

540542
if (hasNormals) {
541-
// Add metallic-roughness to fragment shader
542-
if (defined(generatedMaterialValues.u_metallicRoughnessTexture)) {
543+
if (useSpecGloss) {
544+
if (defined(generatedMaterialValues.u_specularGlossinessTexture)) {
545+
fragmentShader += ' vec4 specularGlossiness = SRGBtoLINEAR4(texture2D(u_specularGlossinessTexture, ' + v_texcoord + '));\n';
546+
fragmentShader += ' vec3 specular = specularGlossiness.rgb;\n';
547+
fragmentShader += ' float glossiness = specularGlossiness.a;\n';
548+
if (defined(generatedMaterialValues.u_specularFactor)) {
549+
fragmentShader += ' specular *= u_specularFactor;\n';
550+
}
551+
if (defined(generatedMaterialValues.u_glossinessFactor)) {
552+
fragmentShader += ' glossiness *= u_glossinessFactor;\n';
553+
}
554+
} else {
555+
if (defined(generatedMaterialValues.u_specularFactor)) {
556+
fragmentShader += ' vec3 specular = clamp(u_specularFactor, vec3(0.0), vec3(1.0));\n';
557+
} else {
558+
fragmentShader += ' vec3 specular = vec3(1.0);\n';
559+
}
560+
if (defined(generatedMaterialValues.u_glossinessFactor)) {
561+
fragmentShader += ' float glossiness = clamp(u_glossinessFactor, 0.0, 1.0);\n';
562+
} else {
563+
fragmentShader += ' float glossiness = 1.0;\n';
564+
}
565+
}
566+
if (defined(generatedMaterialValues.u_diffuseTexture)) {
567+
fragmentShader += ' vec4 diffuse = SRGBtoLINEAR4(texture2D(u_diffuseTexture, ' + v_texcoord + '));\n';
568+
if (defined(generatedMaterialValues.u_diffuseFactor)) {
569+
fragmentShader += ' diffuse *= u_diffuseFactor;\n';
570+
}
571+
} else if (defined(generatedMaterialValues.u_diffuseFactor)) {
572+
fragmentShader += ' vec4 diffuse = clamp(u_diffuseFactor, vec4(0.0), vec4(1.0));\n';
573+
} else {
574+
fragmentShader += ' vec4 diffuse = vec4(1.0);\n';
575+
}
576+
} else if (defined(generatedMaterialValues.u_metallicRoughnessTexture)) {
543577
fragmentShader += ' vec3 metallicRoughness = texture2D(u_metallicRoughnessTexture, ' + v_texcoord + ').rgb;\n';
544578
fragmentShader += ' float metalness = clamp(metallicRoughness.b, 0.0, 1.0);\n';
545579
fragmentShader += ' float roughness = clamp(metallicRoughness.g, 0.04, 1.0);\n';
@@ -561,6 +595,7 @@ define([
561595
fragmentShader += ' float roughness = 1.0;\n';
562596
}
563597
}
598+
564599
fragmentShader += ' vec3 v = -normalize(v_positionEC);\n';
565600

566601
// Generate fragment shader's lighting block
@@ -583,11 +618,19 @@ define([
583618
fragmentShader += ' float NdotH = clamp(dot(n, h), 0.0, 1.0);\n';
584619
fragmentShader += ' float LdotH = clamp(dot(l, h), 0.0, 1.0);\n';
585620
fragmentShader += ' float VdotH = clamp(dot(v, h), 0.0, 1.0);\n';
586-
587621
fragmentShader += ' vec3 f0 = vec3(0.04);\n';
622+
// Whether the material uses metallic-roughness or specular-glossiness changes how the BRDF inputs are computed.
623+
// It does not change the implementation of the BRDF itself.
624+
if (useSpecGloss) {
625+
fragmentShader += ' float roughness = 1.0 - glossiness;\n';
626+
fragmentShader += ' vec3 diffuseColor = diffuse.rgb * (1.0 - max(max(specular.r, specular.g), specular.b));\n';
627+
fragmentShader += ' vec3 specularColor = specular;\n';
628+
} else {
629+
fragmentShader += ' vec3 diffuseColor = baseColor * (1.0 - metalness) * (1.0 - f0);\n';
630+
fragmentShader += ' vec3 specularColor = mix(f0, baseColor, metalness);\n';
631+
}
632+
588633
fragmentShader += ' float alpha = roughness * roughness;\n';
589-
fragmentShader += ' vec3 diffuseColor = baseColor * (1.0 - metalness) * (1.0 - f0);\n';
590-
fragmentShader += ' vec3 specularColor = mix(f0, baseColor, metalness);\n';
591634
fragmentShader += ' float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n';
592635
fragmentShader += ' vec3 r90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0));\n';
593636
fragmentShader += ' vec3 r0 = specularColor.rgb;\n';
@@ -725,8 +768,19 @@ define([
725768
return WebGLConstants.SAMPLER_2D;
726769
case 'u_emissiveFactor':
727770
return WebGLConstants.FLOAT_VEC3;
771+
// Specular Glossiness Types
772+
case 'u_diffuseFactor':
773+
return WebGLConstants.FLOAT_VEC4;
774+
case 'u_specularFactor':
775+
return WebGLConstants.FLOAT_VEC3;
776+
case 'u_glossinessFactor':
777+
return WebGLConstants.FLOAT;
778+
case 'u_diffuseTexture':
779+
return WebGLConstants.SAMPLER_2D;
780+
case 'u_specularGlossinessTexture':
781+
return WebGLConstants.SAMPLER_2D;
728782
}
729783
}
730784

731-
return processPbrMetallicRoughness;
785+
return processPbrMaterials;
732786
});

Specs/Data/Models/PBR/BoomBox/BoomBox.gltf

+2-2
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@
115115
],
116116
"images": [
117117
{
118-
"uri": "BoomBox_baseColor.jpg"
118+
"uri": "BoomBox_baseColor.png"
119119
},
120120
{
121-
"uri": "BoomBox_occlusionRoughnessMetallic.jpg"
121+
"uri": "BoomBox_occlusionRoughnessMetallic.png"
122122
},
123123
{
124124
"uri": "BoomBox_normal.png"
Binary file not shown.
Loading
Loading
2.69 MB
Loading
Loading

0 commit comments

Comments
 (0)