-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Support glTF Specular Glossiness Extension #7006
Conversation
Thanks for the pull request @OmarShehata!
Reviewers, don't forget to make sure that:
I am a bot who helps you make Cesium awesome! Contributions to my configuration are welcome. 🌍 🌎 🌏 |
Very cool @OmarShehata!
Yeah we handle that already, for metallic roughness at least - https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js#L529 |
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'; |
There was a problem hiding this comment.
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
.
fragmentShader += ' vec3 specular = vec3(1.0);\n'; | ||
} | ||
if (defined(generatedMaterialValues.u_glossinessFactor)) { | ||
fragmentShader += ' float glossiness *= clamp(u_glossinessFactor, 0.0, 1.0);\n'; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 metalness = 1.0;\n'; | ||
if (defined(generatedMaterialValues.u_diffuseFactor)) { |
There was a problem hiding this comment.
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.
Thanks for the review @emackey, and for the water bottle test case! It should be all good now. The test cases I added check for being able to render a model when all parameters are provided, when none are provided and when no textures are provided, so it would have caught the shader compile error earlier. I also renamed the class to |
@emackey did you want to give this another look for the new commits? (Biggest change is adding tests and renaming the class). |
Sure. Can't today, will try to carve out time tomorrow.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Anyone else want to review?
Travis is having a ton of problems, I have trouble understanding when that's a fluke vs not. |
Thanks Ed! And yeah, I believe those are because the base branch |
Does anyone else need to look at this before it is merged? And what is needed for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one minor comment. Looks good to me.
Source/Scene/processPbrMaterials.js
Outdated
var uniformName; | ||
var pbrMetallicRoughness = material.pbrMetallicRoughness; | ||
if (defined(pbrMetallicRoughness)) { | ||
for (var parameterName in pbrMetallicRoughness) { | ||
var parameterName; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor style note:
var uniformName;
var parameterName;
var pbrMetallicRoughness = material.pbrMetallicRoughness;
looks cleaner than
var uniformName;
var pbrMetallicRoughness = material.pbrMetallicRoughness;
var parameterName;
There was one failing model (CesiumAir.gltf), but we identified the fix in gltf-pipeline and it just needs to be updated back in Cesium. I believe that was the last thing holding up the PR. @ggetz can confirm. |
Source/Scene/processPbrMaterials.js
Outdated
@@ -88,7 +88,7 @@ define([ | |||
return gltf; | |||
} | |||
|
|||
function isPbrMaterial(material) { | |||
function isMetallicRoughnessMaterial(material) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should actually not be renamed. The function is meant to catch if PBR shaders need to be generated. It should be catching whether the material uses metallic roughness, spec gloss, unlit, or the top-level 2.0 material properties. The purpose is to turn away materials that are using KHR_techniques_webgl
or something else processPbrMaterials
doesn't recognize.
One way to test is with a material like:
{
"extensions": {
"KHR_materials_pbrSpecularGlossiness": {}
}
}
Which I don't think will get shaders generated for it right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check probably also belongs before the hasPbrMetallicRoughness
check:
// No need to create new techniques if they already exist,
// the shader should handle these values
if (hasExtension(gltf, 'KHR_techniques_webgl')) {
return gltf;
}
I feel like a lot of the material existence checking was a little messy before this PR and could use some cleanup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good catch! I think it's helpful to have those two functions separately, so I might just add:
function isPbrMaterial(material){
return isMetallicRoughnessMaterial(material) || isSpecularGlossinessMaterial(material);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good - though make sure sure the extreme edge case works too. This should produce a default PBR shader.
"materials": [
{
}
]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, you're right. I didn't realize glTF materials were all PBR by default. That extreme case currently doesn't work in master. It should be good here now.
So isMetallicRoughnessMaterial()
isn't needed at all then. If any material is found, then it is metallic roughness, unless spec-gloss is also found.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it might not be needed at all.
Thanks for the cleanup suggestions @lilleyse ! It should be good to merge now. |
@lilleyse have you gotten a chance to look at this yet/see if it's ready to merge? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one small comment and this is ready to merge.
Source/Scene/processPbrMaterials.js
Outdated
|
||
if (!hasPbrMaterial) { | ||
return gltf; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simpler to just return early if there are no materials.
@lilleyse I simplified that check, but to make it compatible with both glTF 2.0 and 1.0 I had to make sure to check if it's an array vs an object. |
@OmarShehata the 2.0 vs 1.0 distinction isn't necessary. The model will always be 2.0 coming into this function. |
Ah, that makes it even simpler. Should be good now. |
Thanks @OmarShehata! |
This PR adds support for the KHR_materials_pbrSpecularGlossiness glTF extension. Resolves #6921.
I still have to write tests, but I'm opening it now to get some early feedback.
It's currently implemented in
processPbrMetallicRoughness.js
because it seems implementation-wise the only difference between Metallic Roughness and Specular Glossiness is how the BRDF inputs are computed. It'll check for this extension and modify the relevant part of the shader, keeping the rest of it intact.Since
processPbrMetallicRoughness.js
would now be doing both metallic-roughness and specular-glossiness, should it be renamed to something more general likeprocessPbrMaterials.js
? The other option would be to abstract away most ofprocessPbrMetallicRoughness.js
into a common class that could be shared. @emackey what do you think?I added a test model with spec-gloss in
Specs/Data/Models/PBR/BoomBoxSpecularGlossiness/
. Here's a snippet to test it locally in Sandcastle, and to switch between the metallic-roughness and the specular-glossiness versions of the model.For this model, they look identical which I think is intended.
Adding a
specularFactor: [1.0, 0.5, 0.5]
gives the specular a reddish tone:For reference, this is how Threejs implements it.
The only other thing is that the spec says:
@lilleyse do you know if this is something that's already handled?