Can Godot bake out the albedo from a material to a texture file?

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

I’m in the process of making a base character model for a game project I am working on and I’m currently generating the textures in Blender using a series of black and white masks to blend colors together in a layered sequence. This way I can adjust the colors while reusing the detail masks to get a bunch of unique looking characters with a lot less work than it would be to paint each from scratch.

I plan to bake out the the big mess of nodes to a single texture at the end for each character I make from this base. But that got me wondering, could I do all this in Godot and turn it into a character customization editor in game?

Basically setting up a material with all those masks and hooking up some color values and other stuff to a GUI. Then allow the players to customize the colors used, maybe swap out alternate masks, and then when they are happy with the results, have Godot bake all the nodes used for the albedo down to a texture which can then be used outside of the character editor in the proper game world, to avoid the overhead of the dozens of masks used in the customization process multiplied by each additional character added to the game.

I’m sure i can set up the material and hook things up to a GUI, but what I don’t know is if there is a way to bake the albedo to a texture file and that is the crux of all of this. If that isn’t possible then I just got to shelf this idea for now and continue to do things in Blender and not have in-game customization.

:bust_in_silhouette: Reply From: aXu_AP

I think you can render a quad on a viewport with said material, get viewport texture data and use save_png function on that. Something like this:

    viewport.get_texture().get_data().save_png(path)

Hmm, not sure if I’m just not setting it up properly, but I just get a black texture when I try this. I created a Spatial scene, added a Viewport and resized it to match my texture, added a MeshInstance to that with a QuadMesh that I gave a material that just had an albedo texture on it to test this out. Then I created a script and put the given line of code in _ready(), with path replaced with “res://test.png”. I haven’t done anything with viewports before, so I’m probably missing something pretty obvious here in my test setup.

Uradamus | 2021-10-22 19:56

Here’s what happened: you tried to capture the image before first frame was drawn. Also notice that image may need to be flipped vertically.

func _ready() -> void:
	yield(VisualServer, "frame_post_draw")
	var img = get_texture().get_data()
	img.flip_y()
	img.save_png("img.png")

aXu_AP | 2021-10-22 21:44

Still just getting black output images. I’ll have a look around at the documentation and available tutorials on working with the viewports later and see if I can figure out what I’m missing. At least I have a starting point from which to explore further now.

Uradamus | 2021-10-22 23:06