Dynamically "preloading" Textures is getting me wild results

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By nuttshell


i’m instantiating lots of Node3Ds, which consist of 6 faces ordered like a cube, pointing inwards. I would like to dynamically load albedo, normal and height map textures for them. Previously I was loading them after they were instanced, inside the script of the node itself, which was a pretty significant performance hit, as every instance loaded the textures for it self. I switched to loading them once and would like to be able to point to a directory name, for them to be loaded dynamically, so far, so good, the script is working, but I am getting very unexpected results: godot dynamically preloaded textures - Album on Imgur

This is the code, that I used to load the images:

func getOrderedTextures(path):
if path == null: return null
var textureDirs = {
	ao = null,
	diffuseOriginal = null,
	edge = null,
	height = null,
	normal = null

var dir = DirAccess.open(path)
if dir:
	var fileName = dir.get_next()
	while fileName != "":
		for key in textureDirs.keys():
			if fileName.contains(key):
				var img = Image.new()
				var texture = ImageTexture.new()
				img.load(path + fileName)
				textureDirs[key] = texture
		fileName = dir.get_next()
return textureDirs

And here where they are applied:

const nameToMaterialName = {
	ao = 'ao_texture',
	diffuseOriginal = 'albedo_texture',
	edge = 'roughness_texture',
	height = 'heightmap_texture',
	normal = 'normal_texture'

func setFaces(sideTextures, bottomTextures, topTextures):
	var sideFaces = [ left, right, front, back ]
	for key in sideTextures.keys():
		if sideTextures[key] != null:
			for face in sideFaces:
				face.get_surface_override_material(0)[nameToMaterialName[key]] = sideTextures[key]

It looks as if the ImageTexture doesn’t load the textures correctly…how would I go around that?

I don’t see anything obviously wrong with your texture loading code (although, you’re not checking for any potential errors). Maybe add a temporary TextureRect to the scene and throw your textures in it as they’re loaded to see if they look as expected? I think they probably will (?).

If that’s the case, the problem is most likely related to how you’re applying them in setFaces().

jgodfrey | 2023-04-14 22:24

Thanks for the tip. Yeah, they load just fine, when done in a normal way…the application in SetFaces is also fine, if they are passed in via a preload.

I found a workaround: Only one cell is instantiated initially, then the faces load the texture with “load()” - for this, i threw out the ImageTexture and just passed in the path string. I had to replace an added “.import” which just came out of nowhere though. Then after the instance has had all faces loaded, they are duplicated.

If someone is curious, heres the adjusted code for getting the paths:

while fileName != "":
		for key in textureDirs.keys():
			if fileName.contains(key):
				textureDirs[key] = path + fileName.replace('.import', '')
		fileName = dir.get_next()

here is the adjusted code in the cell:

for face in sideFaces:
    face.get_surface_override_material(0)[nameToMaterialName[key]] = load(sideTextures[key])

nuttshell | 2023-04-17 21:18