Artist workflow for enabling KHR_Extensions such as ClearCoat, Sheen, SubsurfaceScattering, and etc

As an 3d Artist, I have been struggling to figure out a proper method/process/pipeline to enable KHR_Extensions that are supported by Babylon.js such as ClearCoat, Sheen, SubSurfaceScattering, and save them out to a shareable glTF or glB asset.

For example this Toy Car demo asset for IOR: [](IOR Demo)

How was this glTF file created? I wish it was as simple as exporting from Sandbox as a glB, but if I try to export from Sandbox, all of the KHR_Extensions get stripped.

Blender so far provides the ability to export with clearCoat, but alas Sheen does not go along with it.

The MAXtoGLTF exporter does not support these either from what I can tell/experience.

I am obviously missing something, and more than likely a total “DOH!” type of scenario, but any assistance would be greatly appreaciated.

adding our resident artist @PatrickRyan

Thanks @Deltakosh. Can’t believe you have a DevDay presentation, and you’re still here helping. The hero we all need!


@oJAHRASTAo, unfortunately we are in the “dark ages” in-between time where a spec is just becoming ratified but before all of the exporters have updated their tools to handle it. I understand the need for tooling to be built upon a spec that isn’t still in flux, but that does mean that there is a necessary lag between a spec being solidified and the tooling catching up.

What I am doing in the mean time is manually editing the glTF file to include the extensions that are needed. This is simple json, so it’s not a terrible amount of work. Basically, you need to do the following:

  • add in the needed extension to extensionsUsed and extensionsRequired
  • add in your extension parameters under extensions in the materials parameter
  • add a reference to the textures needed to drive your extension in the textures parameter
  • add the link to your textures referenced above in the images parameter


I would suggest using VS Code (which is a pretty simple editor) because they have a plugin for glTF that will give you auto-completion for the json.

I know this isn’t the easiest, artist-friendly method out there, but I will say that if you get familiar with the contents of the glTF format, you have a lot of flexibility to debug your assets and make changes without needing to round trip your files for a simple parameter change.

If you want a sample file to experiment with, you can grab this sheen asset from my github and pull it apart. Let me know if you have questions about the process while the exporters are catching up.


@PatrickRyan Also, a hero to this community! Thanks as always.

Yes, this all validates much of where our pipeline has been going to a large extent.

We have been using VSCode with the glTF viewer and etc., and it is a great tool in understanding the construct of a glTF.

Actually, its fairly easy syntax to understand, except I do get confused on texture references and how they are referenced when opening a glB file. The numbers don’t always seem to line up, or make complete sense. That being said, our hangup in editing the files manually has been related to linking textures properly. Are you defining a “Source” index number, and referencing in the material parameters with “index”? The path to the texture is only the name? This is probably just ignorance, but how do I reference a texture located in a specific folder, or must everything exist at the root?

Thanks again for all of this help. Has anyone done a tutorial or breakdown of sorts on the actual internals of the glTF to better understand its makeup and how references are made?


1 Like

@oJAHRASTAo, glad to hear that you are already comfortable in this pipeline as it really does offer you some extra flexibility. That said, I know that there are some ideas that are fairly abstract if you aren’t comfortable writing code so let me break down what I do. I am including a reference to the glTF chart on Textures which is a broad definition but lays down some basic rules.

I am also going to refer to the sheen asset glTF file from above so I can give you a clear example:

For the most part, you will likely be adding content to an already existing glTF file, so you don’t really need to worry about the samplers part of textures as you will likely want to use the same samplers as the other textures in the file. In this case, you can leave the samplers parameters alone and use the same value for sampler as set in the other textures in the file.

The next thing to do is add your texture URIs to the images array. Just so there isn’t any confusion around the format here, if you are unclear about it, bear with me while I explain what the format means. If you are already familiar with it, I apologize, but it may help someone else here. What you are looking at with "images" is an array of objects (which is also a parameter in an object). You can tell by the brackets/braces that are being used as arrays are contained in and objects are contained in { }. Each object can contain any number of key: value pairs and an array can contain any number of items which also have a key and a value (bear with me here… it will all make sense).

The array keys will start with 0 and increment by 1 for each item in the array so an array like this:

array = ["item1", "item2", "item3"]

would contain three items with the keys 0, 1, and 2. So if you can pass a key to get the value from the key position in the array:

array[1] == "item2" would evaluate as true because we start the array keys at 0.

So then an object is a single entity with one or more key:value pairs that has a string as a key instead of an integer. So this would be the above array as an object:

object = { "first": "item1", "second": "item 2", "third": "item3" }

This means that:

object.second == "item 2" would evaluate as true as we match the key string to find the value.

So now you can see where we are going with the images array above. It’s an array of four items that each hold an object with one key:value pair for the URI of the image you want to load. If you count, starting from 0, through the array to the file path that you want to reference in the textures parameter, you will enter that key in the "source" value in the "textures" array.

When it comes to the "textures" array, it does not matter which order the textures are in, since the loader will step through the array one at a time. The important thing is that you enter the correct values for "sampler" and "source" that correspond to the position of that element within each respective array. The "name" value should just match the file name of the file being used.

In terms of where you can store images, you don’t need to store them in the same directory as your glTF file, but doing so makes the files universally usable. If you store the textures in some other path, you will need to have a similar path for the storage of the files if you pass the glTF to someone else. This makes even less sense for a glb since you are placing all of the needed files (glTF, bin, and textures) into one container to share.

Hope this helps explain, but please let me know if you have other questions.

This is fantastic. Thank you @PatrickRyan for the thorough instruction and explanation. Seriously, a great help, and appreciated. Lemme put this into practice, and let you know how we faired. Progress!

1 Like