# PBRCustomMaterial support in GLTF loader

**URL:** <https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618>\
**Category:** Questions\
**Created:** [November 12, 2020, 8:23am UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618 "2020-11-12T08:23:34Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![breakin](https://avatars.discourse-cdn.com/v4/letter/b/df788c/32.png) [@breakin](https://forum.babylonjs.com/u/breakin)\
**Post date:** [November 12, 2020, 8:23am UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/1 "2020-11-12T08:23:34Z")

</div>

At [Babylon.js/pbrCustomMaterial.ts at master · BabylonJS/Babylon.js · GitHub](https://github.com/BabylonJS/Babylon.js/blob/master/materialsLibrary/src/custom/pbrCustomMaterial.ts) it is shown how you can make a custom pbr-material. It derives from the PBRMaterial.

I want to be able to take a gltf-file I find on the internet and load it, but have the material objects be created from my custom-pbr-material instead of the standard PBRMaterial.

I access the GLTF-loader via BABYLON.SceneLoader.LoadAssetContainerAsync.

Is this possible? If so how?

I did my own little investigation and I think that it is not possible. I can register a new extension but that is not what I am after. The choice to create a PBRMaterial seems to be done in

loaders/src/glTF/2.0/glTFLoader.ts :: \_createDefaultMaterial. (a private function)

My thinking is that a factory function that is used instead of the constructor for the PBRMaterial would solve my problem.

Any thoughts?

---

<div class="post-metadata">

**Author:** ![Cedric](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/cedric/32/2742_2.png) [@Cedric](https://forum.babylonjs.com/u/Cedric)\
**Post date:** [November 12, 2020, 9:08am UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/2 "2020-11-12T09:08:56Z")

</div>

ping @bghgary

---

<div class="post-metadata">

**Author:** ![bghgary](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/bghgary/32/48532_2.png) [@bghgary](https://forum.babylonjs.com/u/bghgary)\
**Post date:** [November 12, 2020, 5:14pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/3 "2020-11-12T17:14:21Z")

</div>

I think my blog about this has exactly what you want?

> **[Extending the glTF Loader in Babylon.js](https://babylonjs.medium.com/extending-the-gltf-loader-in-babylon-js-588e48fb692b)**
>
> If you are reading this, you probably already know about glTF 2.0. However, do you know that there are a handful of glTF extensions…

  
[https://www.babylonjs-playground.com/#20XT9A#4](https://www.babylonjs-playground.com/#20XT9A#4)

You can override `createMaterial` to create whatever material you want.

---

<div class="post-metadata">

**Author:** ![breakin](https://avatars.discourse-cdn.com/v4/letter/b/df788c/32.png) [@breakin](https://forum.babylonjs.com/u/breakin)\
**Post date:** [November 13, 2020, 8:46am UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/4 "2020-11-13T08:46:02Z")

</div>

That worked wonderfully! I had to change it into typescript but it worked (even with babylon in NPM). Beautiful.

The new material has to extend the base PBRMaterial since the loader checks the type (using instanceof) so I can’t supply my own material that has all the properties but has a separate implementation. But that is ok for me so I am super happy. Thanks!

Here is my code for reference. Note that I try to stay close to the default method whereas you wanted to do a special one so I have other attributes on the material compared to your code.

```
// See https://babylonjs.medium.com/extending-the-gltf-loader-in-babylon-js-588e48fb692b for more information
class CustomLoader implements GLTF2.IGLTFLoaderExtension, BABYLON.IDisposable {
  public name: string = 'custom'
  public enabled = true
  private loader: GLTF2.GLTFLoader

  constructor (loader: GLTF2.GLTFLoader) {
    this.loader = loader
  }

  // @ts-ignore
  // tslint:disable-next-line: naming-convention
  public createMaterial (context: string, material: IMaterial, babylonDrawMode: number): BABYLON.Material {
    this.loader.babylonScene._blockEntityCollection = true // Since we are loading into asset container
    const babylon_material = new MYPBRMaterial(material.name || 'material' + material.index, this.loader.babylonScene)
    this.loader.babylonScene._blockEntityCollection = false
    // Moved to mesh so user can change materials on gltf meshes: babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
    babylon_material.fillMode = babylonDrawMode
    babylon_material.enableSpecularAntiAliasing = true
    // babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage
    // baylonMaterial.useSpecularOverAlpha = !this._parent.transparencyAsCoverage
    babylon_material.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE
    babylon_material.metallic = 1
    babylon_material.roughness = 1
    return babylon_material
  }

  public dispose () {
    // TODO: Are we supposed to dispose this.loader? Is it ours? I think not!
  }

  public static factory_function (loader: GLTF2.GLTFLoader): GLTF2.IGLTFLoaderExtension {
    return new CustomLoader(loader)
  }
}
```

---

<div class="post-metadata">

**Author:** ![bghgary](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/bghgary/32/48532_2.png) [@bghgary](https://forum.babylonjs.com/u/bghgary)\
**Post date:** [November 13, 2020, 6:58pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/5 "2020-11-13T18:58:44Z")

</div>

> [@breakin](#):
>
> The new material has to extend the base PBRMaterial since the loader checks the type (using instanceof) so I can’t supply my own material that has all the properties but has a separate implementation

You are free to use your own material not derived from `PBRBaseMaterial` if you also override `loadMaterialPropertiesAsync`.

Glad it works though!

---

<div class="post-metadata">

**Author:** ![fy0](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/fy0/32/28864_2.png) [@fy0](https://forum.babylonjs.com/u/fy0)\
**Post date:** [December 23, 2022, 2:08am UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/6 "2022-12-23T02:08:32Z")

</div>

Source:

[Babylon.js/glTFLoader.ts at d25bc29091d47f51bd2f0f98fb0f16d25517675f · BabylonJS/Babylon.js (github.com)](https://github.com/BabylonJS/Babylon.js/blob/d25bc29091d47f51bd2f0f98fb0f16d25517675f/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts#L1881-L1914)

---

<div class="post-metadata">

**Author:** ![PichouPichou](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/pichoupichou/32/316_2.png) [@PichouPichou](https://forum.babylonjs.com/u/PichouPichou)\
**Post date:** [February 25, 2023, 6:57pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/7 "2023-02-25T18:57:21Z")

</div>

Hi @bghgary,

I am trying to do the same thing with ES6 modules but I can’t make it work.

Here is my code, model is loaded but I do not have the console message and the model is not using PBRCustomMaterial class. I tried several things but I can’t find what I am doing wrong.

```auto
import { SceneLoader } from '@babylonjs/core/Loading/sceneLoader';
import { GLTFLoader } from '@babylonjs/loaders/glTF/2.0/glTFLoader';
import { PBRCustomMaterial } from '@babylonjs/materials/';

//* Replace material loader
function Custom(loader) {
    this.name = 'custom';
    this.enabled = true;

    this.createMaterial = function (context, material, babylonDrawMode) {
        console.log('use custom');

        const custom = new PBRCustomMaterial(`custom${material.index}`, loader.babylonScene);
        return custom;
    };
}

GLTFLoader.RegisterExtension('custom', (loader) => {
    return new Custom(loader);
});

SceneLoader.ImportMesh('', folder, file, scene, (meshes) => {
        console.log(meshes[1].material);
    }, null, (scene, message) => {
        console.error(`Error loading model: ${url}`, message);
    });

```

Thanks a lot for your help 😉

---

<div class="post-metadata">

**Author:** ![MarianG](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/mariang/32/138_2.png) [@MarianG](https://forum.babylonjs.com/u/MarianG)\
**Post date:** [February 26, 2023, 7:36am UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/8 "2023-02-26T07:36:47Z")

</div>

This may help

> **[Babylon.js Playground](https://playground.babylonjs.com/#6T8SBT%230)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

---

<div class="post-metadata">

**Author:** ![PichouPichou](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/pichoupichou/32/316_2.png) [@PichouPichou](https://forum.babylonjs.com/u/PichouPichou)\
**Post date:** [February 26, 2023, 8:25am UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/9 "2023-02-26T08:25:44Z")

</div>

Hello @MarianG, thanks for your answer and this playground.  
This is a good idea to put the `Fragment_Before_FragColor` function directly in createMaterial!

My issue is not in using these functions but to make it work with ES6 modules which is not replicable in the playground, unfortunately.

---

<div class="post-metadata">

**Author:** ![MarianG](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/mariang/32/138_2.png) [@MarianG](https://forum.babylonjs.com/u/MarianG)\
**Post date:** [February 26, 2023, 2:05pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/10 "2023-02-26T14:05:42Z")

</div>

> **[ES6 Playground (forked) - CodeSandbox](https://codesandbox.io/s/es6-playground-forked-upmr0z?file=%2Fsrc%2Findex.js)**
>
> ES6 Playground (forked) using @babylonjs/core, @babylonjs/loaders, @babylonjs/materials

es-6 💪

---

<div class="post-metadata">

**Author:** ![PichouPichou](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/pichoupichou/32/316_2.png) [@PichouPichou](https://forum.babylonjs.com/u/PichouPichou)\
**Post date:** [February 27, 2023, 8:58pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/11 "2023-02-27T20:58:40Z")

</div>

Ok, I finally understood what was happening.

The model I was loading had no material 😅

Thanks a lot @MarianG for helping me!

---

<div class="post-metadata">

**Author:** ![PichouPichou](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/pichoupichou/32/316_2.png) [@PichouPichou](https://forum.babylonjs.com/u/PichouPichou)\
**Post date:** [April 25, 2023, 1:57pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/12 "2023-04-25T13:57:03Z")

</div>

Hello I am re-opening this topic because I need your help in order to go further.

I am trying to play with the material alpha of an imported model using PBRCustomMaterial.  
I manage to do it on a simple plane as you can see in this playground:

> **[Babylon.js Playground](https://www.babylonjs-playground.com/#0GG6MR%2370)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

But when I do the same thing with a model imported I can’t use the varying vAlbedoUV or vUV even if my model does have UVMapping: [https://playground.babylonjs.com/#6T8SBT#1](https://playground.babylonjs.com/#6T8SBT#1)

Can’t you enlighten me on how to correctly use UV in PBRCustomMaterial?

---

<div class="post-metadata">

**Author:** ![bghgary](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/bghgary/32/48532_2.png) [@bghgary](https://forum.babylonjs.com/u/bghgary)\
**Post date:** [April 25, 2023, 4:23pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/13 "2023-04-25T16:23:00Z")

</div>

I’m not totally sure what you are trying to do because you put some invalid shader code in the second PG link, but I think this is what you want?

PG: [https://playground.babylonjs.com/debug.html#6T8SBT#4](https://playground.babylonjs.com/debug.html#6T8SBT#4)

---

<div class="post-metadata">

**Author:** ![PichouPichou](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/pichoupichou/32/316_2.png) [@PichouPichou](https://forum.babylonjs.com/u/PichouPichou)\
**Post date:** [April 27, 2023, 3:16pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/14 "2023-04-27T15:16:51Z")

</div>

Yes, this was exactly what I was looking for @bghgary!

Now to go forward, I then need to clone the material in order to be able to change it on each mesh independently. But after cloning, the onBind function is not called anymore as you can see in this playground:

> **[Babylon.js Playground debug endpoint](https://playground.babylonjs.com/debug.html#6T8SBT%236)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

Is it a bug or what should I do to fix that? 🙏 🙏 🙏

---

<div class="post-metadata">

**Author:** ![bghgary](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/bghgary/32/48532_2.png) [@bghgary](https://forum.babylonjs.com/u/bghgary)\
**Post date:** [April 27, 2023, 3:49pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/15 "2023-04-27T15:49:46Z")

</div>

Not sure. @Evgeni_Popov Any ideas?

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [April 27, 2023, 5:35pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/16 "2023-04-27T17:35:36Z")

</div>

`clone` is not implemented on `CustomMaterial` / `PBRCustomMaterial`, see:

> [@CustomMaterial.clone() Not Currently Working](https://forum.babylonjs.com/t/custommaterial-clone-not-currently-working/12743):
>
> Hey crew, It looks like CustomMaterial is probably inheriting StandardMaterial’s clone() function, which doesn’t include its custom shader bits and bobs. Here’s a demo: [https://www.babylonjs-playground.com/#UXCB15#115](https://www.babylonjs-playground.com/#UXCB15#115) Cheers, Matt

There’s a workaround in a PG linked by @nasimiasl in this thread.

Also, there’s is an error in your PG, `m.material` can be `null`, so you should test for it.

---

<div class="post-metadata">

**Author:** ![PichouPichou](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/pichoupichou/32/316_2.png) [@PichouPichou](https://forum.babylonjs.com/u/PichouPichou)\
**Post date:** [April 28, 2023, 4:47pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/17 "2023-04-28T16:47:03Z")

</div>

Thanks @Evgeni_Popov, updating the clone function is indeed one way to get `PBRCustomMaterial` working in my use case!

> **[Babylon.js Playground debug endpoint](https://playground.babylonjs.com/debug.html#6T8SBT%238)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

Eventually, I need to see meshes behind the one with the alpha effect like in this playground where I see the HDR behind the plane: [https://www.babylonjs-playground.com/#0GG6MR#72](https://www.babylonjs-playground.com/#0GG6MR#72)

But with this custom code, I only get white color: [https://playground.babylonjs.com/debug.html#6T8SBT#12](https://playground.babylonjs.com/debug.html#6T8SBT#12)  
I tried to add `needAlphaBlending` or `needDepthPrePass` and also tried to use `Fragment_Before_FragColor` instead of `Fragment_Custom_Alpha` but none have worked.

What should I do? 🤗

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [April 28, 2023, 6:23pm UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/18 "2023-04-28T18:23:06Z")

</div>

You must override `needAlphaBlendingForMesh` instead of `needAlphaBlending`:

> **[Babylon.js Playground debug endpoint](https://playground.babylonjs.com/debug.html#6T8SBT%2314)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

Note that you won’t see the hdr background because you have other meshes under the mesh you create line 57.

---

<div class="post-metadata">

**Author:** ![PichouPichou](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/pichoupichou/32/316_2.png) [@PichouPichou](https://forum.babylonjs.com/u/PichouPichou)\
**Post date:** [May 2, 2023, 10:23am UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/19 "2023-05-02T10:23:45Z")

</div>

Awesome! Thanks a lot, @Evgeni_Popov!

Have a great day 🤗

---

<div class="post-metadata">

**Author:** ![PichouPichou](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/pichoupichou/32/316_2.png) [@PichouPichou](https://forum.babylonjs.com/u/PichouPichou)\
**Post date:** [May 30, 2023, 10:05am UTC](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618/20 "2023-05-30T10:05:41Z")

</div>

Hello, I’m back with new questions about using PBRCustomMaterial.

There’s a problem because of the use of the shader variable `vAlbedoUV`. As you can see in [this playground](https://playground.babylonjs.com/debug.html#6T8SBT#16), if I remove the albedoTexture from the material, I get the following shader error `'vAlbedoUV': undeclared identifier`.  
**First question** : What other variable could I use to make the effect work even without an albedoTexture? I’m used to seeing `vUV` used in most BabylonJS shader examples, but it seems we can’t use it with PBRCustomMaterial.  
**Second question** : Is there somewhere in the documentation a list of BJS Shader variables created ? So that we know how to add glsl cutom code more easily?

Thanks guys!

[Next page](https://forum.babylonjs.com/t/pbrcustommaterial-support-in-gltf-loader/15618.md?page=2)
