Blender to GLTF/GLB -- Where are the textures?

Hi,

I have a few newbie questions about loading GLB / GLTF files created in Blender…

Our Blender guy exported an object to GLB (a “room”), which I’m trying to load into BabylonJS:

SceneLoader.Append("/sites/docs/environment/", "foo.gltf", scene)

The geometry is loading and rendering fine, but there are no textures, just bare colors. I can see in the GLTF data that some materials are defined (such as “wood floor”).

Are texture images part of the GLB / BIN file, or do they need to be loaded separately? The GLB file is quite large (4.5MB), but the textures I’m using are actually quite a bit larger, so I suspect the GLB file doesn’t include textures images.

I tried creating a StandardMaterial registered with the same name referenced in the GLTF file and using the JPEG texture for the floor, but that didn’t help. Chrome reports the JPEG is loaded successfully, so it’s not a 404 issue:

const woodFloorMat = new StandardMaterial("WoodFlooringWhiteOak003_3K", scene)
woodFloorMat.diffuseTexture = new Texture("/my-path/WoodFlooringWhiteOak003_COL_3K.jpg", scene)

I’m still just getting a gray floor.

There are some other issues with the GLB, including a few meshes that aren’t rendering at all (or are doing so transparently). I suspect they may just not have a base color defined.

I also installed Blender and tried using the Blender exporter, but it just hung up Blender (I’m using Blender 2.92 on Windows).

Would an exported BabylonJS file from Blender be significantly smaller than GLTF? I.e., might it just contain shape primitives rather than all of the pre-defined vertex information I assume is making up the majority of the BIN/GLB file?

I’ve read the various docs for the GLTF loader, but I’m not finding answers there to these (basic?) questions, so I hope some of you gurus and ninjas can help! :slight_smile:

Adding @PirateJC

I am not the Blender GLFT exporter guy, and do not really fix people’s scenes, even if they used the .babylon / JSON exporter. If it loads into the Sandbox, my job is done.

One thing I see missing from your text is the word ‘sandbox’. Loading into the sandbox should be a well established habit as the first thing to do, post export. Otherwise, you will be playing the game of is it the file or the load code, like Ground Hog Day.

I am pretty sure GLB in lines textures right into the file though. If you referred to using the .babylon exporter on 2.92, that might be a little bit premature. The last production version of the exporter was tested on Blender 2.83 LTS. I am in the process of getting the changes done for 2.93 LTS. I do not bother with the throw away Blender releases.

Comparing the exporters based on size of output is not linear. The .babylon /JSON file is text, while GLB is a binary. If you enable gzip for the .babylon extension or just rename it to .json extension, you will actually get ~ 70 to 75% reduction in transmission from the file size. GLB cannot use gzip, but it has it’s own.

The JSON file can also inline texture via base64, but it is optional via Blender custom property. I do not recommend making format decisions, based on size comparison.

Thanks @JCPalmer!

I tried in the Sandbox – no wood floor texture (or other textures in the room, but the wood floor is the easiest to see).

However, in the Inspector for the wood floor material, if I “Add Albedo Texture” and load the JPEG, it looks correct.

So, my take-aways for now:

  1. The GLB file does not contain the textures, just the material definitions, nodes, etc.
  2. I’ll need to manually load the JPEG textures separately from loading the GLB.
  3. Pre-creating a material of the same name and loading a texture into it does not actually change the material used by meshes appended afterward. I need to find the existing material after loading the GLB and apply the texture to it instead.

The size of the GLB/BIN file (>4MB) is still surprisingly large for what is essentially a big square room and some cylinders. Certainly orders of magnitude larger than the JS needed to create the same shapes manually. That leads me to think the majority of the file is individual vertices for the cylindrical objects rather than just descriptions of the primitive shapes.

I’ll avoid the Blender export until the versions match up. I was just trying to see if it would lead to a different result.

Well, I’ll let @PirateJC take it from here. I saw about a sentence away from posting when @Deltakosh jumped in with the ping.

One thing, you are not up to full power yet with Sandbox. It has an inspector feature. You would not need to form a “take-away”, as you call it, about whether the GLB had a texture on not. If it does, you should be able to tell with inspector, not guess.

Regarding the comment about the Sandbox, I literally just said I used the Inspector to load the JPEG file as the albedo texture for that material and confirmed that it fixed the issue.

What the Sandbox does not show is the internal file format and contents of the GLB binary buffer. Thus, it doesn’t show whether BabylonJS somehow might be ignoring a texture that is embedded in the file.

The Wikipedia article on GLTF and Kronos file spec suggest texture images are stored internally. Clearly that’s either not the case, or it is optional. I didn’t create the GLB file, nor am I a Blender user, so I don’t know what export options are available or which ones were used.

You should give a link to your .glb file if you can, it would be easier for people to help.

Also, you can use this from @bghgary : GitHub - bghgary/glTF-Shell-Extensions: Microsoft Windows shell extensions that pack .gltf to .glb and unpack .glb to .gltf

When installed, you can just right click a .glb file and select the right menu entry to unpack it: you will be able to see if the textures are in the file or not.

My tool only works on Windows. If you are not on Windows, you can use vscode with the glTF Tools Extension for Visual Studio Code to unpack the glb.

Hey @richardtallent Thanks for starting up this thread.

Would it be possible for you to post the original blender file with the asset in it? I’d be happy to help debug what might be happening in the export.

Most of the time errors with textures are related to the type of Blender material that you have set up. the built in .gltf/.glb exporter really only handles the Principled BSDF shader.

I’d be happy to take a look.

1 Like

@bghgary and @Evgeni_Popov, thanks, I’m on Windows, so I’ll try that extension for future use!

I already have the VSC extension, it’s pretty cool! That’s how I tested and converted the GLB to a GLTF/BIN pair while I was trying to figure this out prior to posting. (And since all 4 preview renderers in that extension gave the same result as my code, I had not seen the need to also confirm with the Sandbox.)

@PirateJC, thanks, I may take you up on that! This is actually my first “day job” project involving BablyonJS – so far I’ve just been using it for my personal VR projects, so getting to use those skills at work is nice. I have a meeting with our Blender guy tomorrow, I’ll tell him about the Principled BSDF shader limitation. If that doesn’t work, I’ll see if he can create a minimum reproducible model that I can post.

Unless GLTF has some magical texture file compression, I think we’ll want to use external textures, since that will allow us to have control over compression parameters, use newer file formats like JPEG XR and WEBP (if BabylonJS will work with anything the browser supports?), and potentially allow us to dynamically server lower-resolution files (or even skip some minor textures and channels) based on the user’s bandwidth and screen resolution. Plus, with HTTP2, parallel loading of textures will probably be more performant than loading one huge file.

1 Like

Makes complete sense. You can absolutely assign textures to material inputs manually if you want to make sure you’re using the best compression available.

I’m not an expert in compression, but I believe the best of the best that Babylon.js supports right now is .ktx2 basis compression. @bghgary please correct my ignorance here.

The built in Blender exporter does NOT support .ktx2 yet as far as I know, but Babylon does, so hooking textures up separately apart from the export process is probably smart.

1 Like

So many things to say here :slight_smile:

Yes, glTF does have magical texture file compression that was just announced. You can find more information here: Khronos KTX 2.0 Textures Enable Compact, Visually Rich, glTF 3D Assets - The Khronos Group Inc. From there, you can get to this page: KTX Overview - The Khronos Group Inc which has a bunch of links at the top that has information about how to use KTX as well as how to create glTF asset with KTX.

Not JPEG XR since there is no glTF extension for it, but there is a glTF extension for WEBP: glTF/README.md at master · KhronosGroup/glTF (github.com) and it is supported in Babylon.js.

There is an MSFT_lod extension for glTF that may help a little. The support for this in Babylon.js is only for progressive loading. There is an issue tracking using this for runtime rendering of LODs and an issue for screen coverage. Theoretically, this extension can also be used to load LODs based on bandwidth.

If this extension doesn’t suit your needs, you can create your own custom glTF extensions and load them using custom extensions to Babylon.js glTF loader.

This can already be accomplished with glTF. You don’t have to load a glTF using a single GLB. If you load using loose glTF and its references, the Babylon.js loader will already load the references in parallel. Also, GLB doesn’t have to be a single file. You can still reference external files from a GLB. This will also be loaded in parallel with Babylon.js.

Self-contained GLB files are not typically the best way to deal with glTF on a server.

I don’t believe this is available yet, but if you look at the links I noted above, there are tools that can take the output of Blender and create KTX versions of them.

3 Likes

The GLB should have all the textures but only if has been setup correctly. When i was doing this i had to make sure my materials were setup with exporting to gltf in mind. I found this useful glTF 2.0 — Blender Manual

If your blender guy hasn’t set it up like this it probably wont work.

I’m agree with MarkM, your issue looks like a Blender material setup problem, not a gltf one.

The issue seems to be most likely related to the material node tree in blender, as other have stated.
Usually, in order to export from blender with materials correctly most tools require the node tree to end in a single Principled BSDF shader node connected to the output.
Materials like glass, or more complex stuff usually requires mixed shaders, which should probably baked down to PBR texture maps.