Prepara una mappa di texture con Python

Aug 15 2020

Uso Blender 2.83. Per un addon (accessibile dalla vista 3D) voglio creare mappe di texture. Sono perfettamente in grado di farlo senza script. Ma con Python non ho avuto successo sinora.

Per ridurre il mio problema al minimo indispensabile, inizio con un oggetto selezionato con UV valido. Quindi eseguo il seguente script 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)

Penso che quello che mi manca sia il corretto collegamento dell'immagine al nodo della trama. Ho consultato domande simili come

Imposta il nodo dell'immagine attivo con Python

ma le loro risposte non hanno aiutato (il codice per Blender 2.7 che non è più compatibile, immagino).

Risposte

3 NoobCat Aug 22 2020 at 01:23

Penso di darti alcuni passaggi di base, cioè aggiungere un nodo di tipo "TEX_IMAGE", assegnargli la tua immagine. perciò:

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)

Evita il più possibile di usare bpy.ops, in questo caso, come puoi vedere, è facile creare un'immagine con i metodi bpy.data.images.new () Qualsiasi oggetto blender può essere creato con quel metodo.

bpy.data.objects.new()
bpy.data.materials.new()
bpy.data.scenes.new()
...
...

bpy.ops è bene usarlo solo quando non si hanno alternative, come in questo caso con il bpy.ops.object.bake()

questo ti permette di creare qualcosa e assegnarlo direttamente a una variabile, come nell'esempio di img = bpy.data.images.new()Quindi non devi impazzire per accedervi.