Export the SpecularGlossiness model to glb

For models made of SpecularGlossiness material, inconsistent display may occur when exported through glTFExporter.

The glb model of the original SpecularGlossiness:
https://sandbox.babylonjs.com/?assetUrl=https://raw.githubusercontent.com/Jeggery/storageResources/master/models/glb/specularGlossiness/fg22SpecularGlossiness2.glb

Export through BJS’s glTFExporter:
https://sandbox.babylonjs.com/?assetUrl=https://raw.githubusercontent.com/Jeggery/storageResources/master/models/glb/specularGlossiness/bbl-glossinessScene.glb

use https://gltf.report/ Website export (The principle is to use gltf -transform):
https://sandbox.babylonjs.com/?assetUrl=https://raw.githubusercontent.com/Jeggery/storageResources/master/models/glb/specularGlossiness/three-fg22SpecularGlossiness2-v1.glb


BJS’s glTFExporter and gltf-transform cannot restore the original SpecularGlossiness model effect.

In addition, BJS glTFExporter has modified the basic color texture

Is it because the conversion algorithm of each exporter is inconsistent?

cc @PatrickRyan

cc @alexchuber who owns the gltf exporter

@brightMoon, this looks to be the result of how the material is set up. If you take a look at your material without the specular glossiness texture applied, you can see that the light in the scene has a purple cast to it:

This is due to the material having that color added in the reflectivity parameter (circled in red). What appears to be happening is that there is no direct mapping for our reflectivity parameter in glTF so the exporter is adding that color to the albedo texture to compensate. The fix here would be to move the color from the reflectivity parameter to your specular texture. Right now, you have white as the specular color in the texture. Changing this color to the purple color that has been added to reflectivity should do the same thing, but the exporter should not get tripped up.

There may be a discussion to have with @alexchuber about if the exporter is doing the right thing in the first place. Maybe if we can determine that the model is using specular glossiness materials and there’s a color other than white in Reflectivity of the material, we write that color into the RGB channels of the spec-gloss texture. How much to overlay could be contentious as we would have no idea what the intent of the artist would be if there were color data other than white in the spec-gloss RGB channels.

4 Likes

BJS’s glTFExporter and gltf-transform cannot restore the original SpecularGlossiness model effect.

Yes. This is because the original model uses KHR_materials_pbrSpecularGlossiness, which has been effectively deprecated in favor of KHR_materials_specular. Neither our exporter nor gltf-transform will serialize KHR_materials_pbrSpecularGlossiness for this reason, hence why the original model looks different after both exports.

Is it because the conversion algorithm of each exporter is inconsistent?

As for the difference between our exporter’s output vs gltf-transform’s, it goes with what Patrick noted. We bake the spec/gloss information into the regular glTF metal/rough parameters without using KHR_materials_specular, while gltf-transform does use KHR_materials_specular. There may be other reasons, too, but that’s what stands out the most.

I do think we should have a better roundtrip for this situation. A temporary fix would be to support KHR_materials_pbrSpecularGlossiness on export until we can find better conversions. Or maybe find a way to incorporate KHR_materials_specular into our spec/gloss → metal/rough conversions like gltf-transform does. But, either way, I’m not sure any exporter can perfectly match the original model without preserving its KHR_materials_pbrSpecularGlossiness on export.

Tagging @bghgary the master of workflow conversions ⁠:)

2 Likes

My understanding is that KHR_materials_specular is supposed to handle everything that KHR_materials_pbrSpecularGlossines can handle (see here), so if KHR_materials_specular and KHR_materials_ior are used, it should be lossless. And as @alexchuber says, Babylon’s exporter does not yet do this conversion (we should add this to the backlog).

I would expect glTF-Transform to give an exact replication of the original asset since it understands KHR_materials_pbrSpecularGlossines, KHR_materials_specular, and KHR_materials_ior, but maybe there are some issues. FYI @donmccurdy

3 Likes

The spec/gloss to metal/rough conversion in glTF Transform should be lossless, yes. Given an input using KHR_materials_pbrSpecularGlossiness the metalRough() transform will produce an output using KHR_materials_specular and KHR_materials_ior with the same appearance. Here’s the implementation. It’s also fine to process the file in glTF Transform without doing this conversion, if needed.

I’m not sure I follow the part about the “reflectivity” property though… is that something in the source glTF file?

2 Likes

Don’t worry about that. It’s a material property name in Babylon.js that is analogous to specular color.

Thank you @donmccurdy , glTF Transformer is excellent. But now we are using the Babylonjs engine, which adjusts the model after loading, making it easier to convert and export

@bghgary @PatrickRyan @alexchuber Can BJS glTFExporter refer to the content code of metalRough() in glTF Transform to convert KHR_materials_pbrSpecular Glossiness to KHR_materials-specular? I think this is a high-quality solution

For sure, the implementation should be similar to glTF transform’s metalRough(). We definitely want to incorporate the KHR_materials_specular + KHR_materials_ior solution into our conversions.

The only issue with referencing metalRough() is that we won’t have the same information. If I understand correctly, metalRough() is converting glTF → glTF, so it has the original KHR_materials_pbrSpecularGlossiness to work with. We do not. We’ll need to deal with Babylon material properties → glTF, which I expect will have a lot of edge cases (considering how robust Babylon’s PBR materials are :))

2 Likes