Unstable order of p3d_TextureN slots when loading a glTF model – did I miss a cleaner fix?

Hi all,

I just spent a few evenings chasing a tricky bug and wanted to share what I found – maybe someone has a smarter way.

What I saw

  • Engine: Panda3D 1.10.15, Python 3.13, macOS (Apple M-series).
  • I load glTF files with the usual loader.loadModel(“scene.gltf”).
  • Panda automatically loads every image in the file and exposes them in the shader as sampler2D p3d_Texture0, p3d_Texture1, p3d_Texture2, …
  • Problem: the index of each texture changes from run to run .
    • I think if the images have very different sizes the order is constant (small file finishes first, so it becomes Texture0, etc.).
    • When the files are similar in size, the loader threads finish in a random order, so in one launch my diffuse map is Texture0, in the next launch it is Texture1, sometimes even Texture3.
  • I could not find any reliable API to ask “which slot is the base-color map?” - at least not in 1.10.15.

The result was a completely random look: sometimes the model was correct, sometimes the normal map appeared where the base color should be.

My workaround

  1. After loading the model then load the same image files myself (by name) and pass them as explicit shader inputs:
model.setShaderInput("u_BaseColorTex", loader.loadTexture(path_to_basecolor))
model.setShaderInput("u_NormalTex",   loader.loadTexture(path_to_normal))
...  
  1. In GLSL I read my own uniforms instead of p3d_TextureN, so the mapping is now 100% deterministic.

It works, but it feels a bit brute-force and wastes a little memory (the images are loaded twice, at least for a moment).

Question

  • Is there a built-in way to keep the automatic p3d_TextureN list but still know which index belongs to which glTF channel?
  • Or a flag that tells Panda not to load textures at all when I call loadModel?
  • Any other approaches that avoid the double load and keep things tidy?

Thanks in advance for any ideas!

— Miklesz

There is probably a quirk in data transformations .gltf of the loader. Perhaps this was missed due to the switch to named input parameters of maps.

uniform sampler2D p3d_TextureModulate;
uniform sampler2D p3d_TextureNormal;
uniform sampler2D p3d_TextureSelector;
...

Where p3d_TextureModulate contains color data. p3d_TextureSelector contains data in channels.

1 Like