Hornea un mapa de textura con python

Aug 15 2020

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

3 NoobCat Aug 22 2020 at 01:23

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.