Hornea un mapa de textura con python
Yo uso Blender 2.83. Para un complemento (accesible desde la Vista 3D), quiero hornear mapas de textura. Soy perfectamente capaz de hacerlo sin scripts. Pero con Python no tuve éxito hasta ahora.
Para reducir mi problema al mínimo, comienzo con un objeto seleccionado con UV válido. Luego ejecuto el siguiente script de Python:
import bpy
obj = bpy.context.active_object
# Creating a texture node, linked with a new image
mat = obj.data.materials[0]
mat.use_nodes = True
texImage = mat.node_tree.nodes.new('ShaderNodeTexImage')
img = bpy.ops.image.new(name= obj.name + '_BakedTexture')
texImage = img
# !!! No image is linked to the texture node !!!
# Baking to the newly created image
# The following part works if I create the texture node and the assigning of the image by hand
bpy.context.view_layer.objects.active = obj
bpy.ops.object.bake(type='DIFFUSE', save_mode='EXTERNAL', filepath='C:\\TEMP\\baked.png', use_automatic_name=True, width=512, height=512)
Creo que lo que me falta es la vinculación correcta de la imagen al nodo de textura. Consulté preguntas similares como
Establecer nodo de imagen activa con Python
pero sus respuestas no ayudaron (código para Blender 2.7 que ya no es compatible, supongo).
Respuestas
Creo que te daré algunos pasos básicos, es decir, agregar un nodo de tipo "TEX_IMAGE", asignarle tu imagen. por lo tanto:
obj = bpy.context.active_object
# You can choose your texture size (This will be the de bake image)
image_name = obj.name + '_BakedTexture'
img = bpy.data.images.new(image_name,1024,1024)
#Due to the presence of any multiple materials, it seems necessary to iterate on all the materials, and assign them a node + the image to bake.
for mat in obj.data.materials:
mat.use_nodes = True #Here it is assumed that the materials have been created with nodes, otherwise it would not be possible to assign a node for the Bake, so this step is a bit useless
nodes = mat.node_tree.nodes
texture_node =nodes.new('ShaderNodeTexImage')
texture_node.name = 'Bake_node'
texture_node.select = True
nodes.active = texture_node
texture_node.image = img #Assign the image to the node
bpy.context.view_layer.objects.active = obj
bpy.ops.object.bake(type='DIFFUSE', save_mode='EXTERNAL')
img.save_render(filepath='C:\\TEMP\\baked.png')
#In the last step, we are going to delete the nodes we created earlier
for mat in obj.data.materials:
for n in mat.node_tree.nodes:
if n.name == 'Bake_node':
mat.node_tree.nodes.remove(n)
Evite tanto como sea posible el uso de bpy.ops, en este caso, como puede ver, es fácil crear una imagen con los métodos bpy.data.images.new () Cualquier objeto de blender se puede crear con ese método.
bpy.data.objects.new()
bpy.data.materials.new()
bpy.data.scenes.new()
...
...
bpy.ops es bueno usarlo solo cuando no tienes alternativas, como en este caso con el bpy.ops.object.bake()
esto le permite crear algo y asignarlo directamente a una variable, como en el ejemplo de img = bpy.data.images.new()
Para que no tenga que volverse loco para tener acceso a él.