See Load from any file type - glTF, OBJ, STL, etc. - Babylon.js Documentation. I’m assuming you are loading one glTF and not multiple glTFs.
Yo @bghgary … Do you have any examples on creating material with the GLTF Extensions.
I tried add a createMaterial function … I see it getting called but it looks like it not actually using the material i returned from createMaterial function…
Are there any other functions i need to implement for my createMaterial function to work ???
Here is my simple createMaterial… That should create a GREEN PBT for everything… But it does nothing in the final scene.
/** @hidden */
public createMaterial(context: string, material: BABYLON.GLTF2.Loader.IMaterial, babylonDrawMode: number): BABYLON.Nullable<BABYLON.Material> {
console.log("*** CREATE MATERIAL: " + material.name);
const babylonMaterial = new BABYLON.PBRMaterial(material.name, this._loader.babylonScene);
babylonMaterial.sideOrientation = this._loader.babylonScene.useRightHandedSystem ? BABYLON.Material.CounterClockWiseSideOrientation : BABYLON.Material.ClockWiseSideOrientation;
babylonMaterial.fillMode = babylonDrawMode;
babylonMaterial.enableSpecularAntiAliasing = true;
//babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage;
//babylonMaterial.useSpecularOverAlpha = !this._parent.transparencyAsCoverage;
babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE;
babylonMaterial.metallic = 1;
babylonMaterial.roughness = 1;
babylonMaterial.albedoColor = BABYLON.Color3.Green();
return babylonMaterial;
}
https://www.babylonjs-playground.com/#20XT9A#0
If you want a PBRMaterial but with different properties set, then override loadMaterialPropertiesAsync instead of createMaterial.
What if i wanna use a CUSTOM PBRMaterial Subclass … What would i do ???
Also… I looks like No Mater what… you just CREATE THE MATERIAL in createMaterial. You dont actually set the textures in createMaterial… But attach the textures in loadMaterialsPropertiesAsync…
If so what kind of properties should be set in createMaterial vs setting properties in loadMaterialPropertiesAsync ???
Thanks Gary for all your help 
This can certainly have more documentation and thanks for testing it out. 
The loader calls createMaterial to synchronously create the material. Then, the loader immediately calls loadMaterialPropertiesAsync asynchronously to load the material properties. The second part is asynchronous because texture loading or other things might be asynchronous.
If you just need to load different properties for a PBR material, then you only need to override loadMaterialPropertiesAsync. An example of this is the KHR_materials_pbrSpecularGlossiness extension.
If you want to completely replace the material, then you should override both createMaterial and loadMaterialPropertiesAsync. That’s the example I gave above. It doesn’t matter a lot what you do in either function since they are called in sequence, but only the second function is asynchronous.
Pinging @PirateJC for the missing doc
Hey @bghgary … i made mods to my load materials function to use a standard material instead of PBR material… I am using the EXACT code you listed in playground… But i get all kind of EXTRA shinning light on my Remy Character
public loadStandardMaterialPropertiesAsync(context: string, material: BABYLON.GLTF2.Loader.IMaterial, babylonMaterial: BABYLON.StandardMaterial): BABYLON.Nullable<Promise<void>> {
if (!(babylonMaterial instanceof BABYLON.StandardMaterial)) throw new Error(`${context}: Material type not supported`);
console.warn("CVTOOLS: LoadStandardMaterialPropertiesAsync: " + material.name);
const commonConstant:any = (material.extras != null && material.extras.metadata != null) ? material.extras.metadata : null;
const promises = new Array<Promise<any>>();
// BASE PROPERTIES
var pbrMetallicRoughness = material.pbrMetallicRoughness;
if (pbrMetallicRoughness) {
if (pbrMetallicRoughness.baseColorTexture) {
promises.push(this._loader.loadTextureInfoAsync(context + "/pbrMetallicRoughness/baseColorTexture", pbrMetallicRoughness.baseColorTexture, function (babylonTexture) {
babylonMaterial.diffuseTexture = babylonTexture;
}));
}
}
if (material.emissiveTexture) {
promises.push(this._loader.loadTextureInfoAsync(context + "/emissiveTexture", material.emissiveTexture, function (babylonTexture) {
babylonMaterial.useEmissiveAsIllumination = true;
babylonMaterial.emissiveTexture = babylonTexture;
}));
}
return Promise.all(promises).then(() => { });
But look at the output:
What do you think is causing this ???
Yo @bghgary … take a look at the demo you made for me but with Remy model…
It still looks really glossy like its STILL a PBR or something:
https://www.babylonjs-playground.com/#20XT9A#1
What do you think is the problem ???
He should look more like this:
This is the original Unity shot using legacy bumped diffuse shader… The look i am going for:
Hey @bghgary … I know you dont like NON standard GLTF stuff. But please bro, can you point me to the code in the BabylonJS source that or handles the RIGHT handed values. I have created a LEFT handled GLTF (basically i just DONT switch handness on all my ExportAccessor functions as well as my node.Translation and node.Rotation values… Thus KEEPING EVERYTHING IN LEFT HANDED coordinate system)
Note: Just forcing babylon to USE RIGHT SYSTEM does not do the trick… things are inverted and look inside out.
There has GOT to be a way to get GLTF parser to use the Original values in the GLTF scene file WHICH ARE LEFT HANDED … Or agaim simple NOT converted to RIGHT HAND values:
Example this is my node TRS export code:
// If object is on top of the selection, use global transform
bool useLocal = !Array.Exists(_rootTransforms, element => element == nodeTransform);
Vector3 position = useLocal ? nodeTransform.localPosition : nodeTransform.position;
Quaternion rotation = useLocal ? nodeTransform.localRotation : nodeTransform.rotation;
Vector3 scale = useLocal ? nodeTransform.localScale : nodeTransform.lossyScale;
if (CanvasToolsInfo.Instance.HandedExportSystem == 0)
{
node.Translation = new XGLTF.Math.Vector3(position.x, position.y, -position.z);
node.Rotation = new XGLTF.Math.Quaternion(rotation.x, rotation.y, -rotation.z, -rotation.w);
node.Scale = new XGLTF.Math.Vector3(scale.x, scale.y, scale.z);
}
else
{
node.Translation = new XGLTF.Math.Vector3(position.x, position.y, position.z);
node.Rotation = new XGLTF.Math.Quaternion(rotation.x, rotation.y, rotation.z, rotation.w);
node.Scale = new XGLTF.Math.Vector3(scale.x, scale.y, scale.z);
}
Note: HandExportSystem = 0 - Right Handed and 1 - Left Handed
Please bro… I gotta make LEFT HANDED GLTF support. Right handed is killing me 
StandandMaterial defaults to white for specularColor. Set it to black to remove it.
I think this works, but I don’t have a left-handed glTF to test with.
First off, are you saying the ONLY thing that FLIPS things is the root with negative z scaling… No other place in the GLTF loading process ALTERS the TRS values from the GLTF scene ???
Also… should scene.useRightHandSystem = false ???
And i put a TestLeft.glb were I DO NOT switch handedness in Unity… Thus leaving left handed… I think ???
try this playground with test leftt scene… still looks off and the clockwise stuff looks inverted:
https://www.babylonjs-playground.com/#RY89XI#2
This it what it should look like with CAPSULE on the left of the Remy and CYLINDER on the right:
No other place in the GLTF loading process ALTERS the TRS values from the GLTF scene ???
Yes. This is accurate. We want to load the asset as quickly as possible.
still looks off and the clockwise stuff looks inverted
Ah, yes, because of the negative scale that is added to change handedness, the loader also flips the sideOrientation (winding order) which also needs to be flipped back.
Also, just to reiterate, I highly recommend that you add a required extension to this asset so that it will fail to load in conformant implementations.
Can you clarify this… Is this something im doing in the unity side… I thought i took out all the switchhandess stuff when serializing the gltf scene file.
What did you do to offset this ???
BTW… the latest scene looks good LEFT HANDED
Do you see any problems with loading this as LEFT HANDED ???
Yo @bghgary … On another topic… I am trying to Async load some required javascript BEFORE the loader.loadSceneAsyn promise.
this is what i got so far:
public loadSceneAsync(context: string, scene: BABYLON.GLTF2.Loader.IScene): BABYLON.Nullable<Promise<void>> {
console.warn("CVTOOLS: LoadSceneAsync: " + scene.name);
const promises = new Array<Promise<any>>();
let delayscene:boolean = false;
if (document != null) {
if (scene.extras != null && (<any>scene.extras).metadata != null) {
const metadata:any = (<any>scene.extras).metadata;
if (metadata.hasOwnProperty("script") && metadata.script != null && metadata.script !== "" && metadata.hasOwnProperty("project") && metadata.project != null && metadata.project !== "") {
const scriptid:string = metadata.script;
const projectjs:string = metadata.project;
const hasscript:boolean = (document.getElementById(scriptid) != null);
if (hasscript === false) {
promises.push(this._loadSceneLibraries(context, scene, scriptid, projectjs));
}
}
}
}
promises.push(this._loadSceneProperties(context, scene));
promises.push(this._loader.loadSceneAsync(context, scene));
return Promise.all(promises).then(() => { });
}
private _loadSceneLibraries(context: string, scene: BABYLON.GLTF2.Loader.IScene, tag:string, script:string): BABYLON.Nullable<Promise<void>> {
console.warn("CVTOOLS: LoadSceneLibraries: " + scene.name);
const promises = new Array<Promise<any>>();
console.log("===> Load project name: " + tag);
console.log("===> Load project script: " + script);
return Promise.all(promises).then(() => { });
}
In my new _loadSceneLibraries function i need to load some javascript async in the promise returning pattern. But i dont know how to do that.
Does babylon support some kind of LoadScript utilities function or can you show me how to load script in the pine promise pattern so my script loads and COMPLETES BEFORE the load.loadSceneAsync function starts running…
I have some custom material classes that i need to be loaded before it starts parsing nodes and calls the load.createMaterial. So those custom material class exists at that point…
I really appreciate all your help thus far 
Is this something im doing in the unity side
No. The loader does two main things when it “converts” the data from glTF right-handed to left-handed.
- Adds a root transform with a negative scale.
- Inverts the winding order on the materials.
The playground I sent undoes both of these.
Do you see any problems with loading this as LEFT HANDED ???
No. I think this should be good.
Yo @bghgary … thanks dude… you are ‘Da Shit’ 
(That a good thing BTW)
See Promise.prototype.then() - JavaScript | MDN which has some good examples.
So you just mean i dont have to do stuff like Math.PI rotations… Which is what you had on the camera.alpha … That and the side orentation was the problem when using LEFT HANDED gltf files … Right ???




