Cuire une carte de texture avec python

Aug 15 2020

J'utilise Blender 2.83. Pour un addon (accessible depuis la vue 3D), je souhaite créer des textures. Je suis parfaitement capable de le faire sans script. Mais avec python je n'ai pas réussi sofar.

Pour réduire mon problème au minimum, je commence par un objet sélectionné avec des UV valides. J'exécute ensuite le script python suivant:

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)

Je pense que ce qui me manque, c'est la liaison correcte de l'image au nœud de texture. J'ai consulté des questions similaires telles que

Définir le nœud d'image actif avec python

mais leurs réponses n'ont pas aidé (code pour Blender 2.7 qui n'est plus compatible, je suppose).

Réponses

3 NoobCat Aug 22 2020 at 01:23

Je pense que je vais vous donner quelques étapes de base, c'est-à-dire ajouter un nœud de type "TEX_IMAGE", lui attribuer votre image. donc:

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)

Évitez autant que possible d'utiliser bpy.ops, dans ce cas, comme vous pouvez le voir, il est facile de créer une image avec les méthodes bpy.data.images.new () Tout objet Blender peut être créé avec cette méthode.

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

bpy.ops il est bon de ne l'utiliser que si vous n'avez pas d'alternative, comme dans ce cas avec le bpy.ops.object.bake()

cela vous permet de créer quelque chose et de l'affecter directement à une variable, comme dans l'exemple de img = bpy.data.images.new()Donc, vous n'avez pas à devenir fou pour y avoir accès.