Faça um mapa de textura com python
Eu uso o Blender 2.83. Para um addon (acessível a partir da visualização 3D) eu quero preparar mapas de textura. Sou perfeitamente capaz de fazer isso sem scripts. Mas com python eu não tive sucesso sofar.
Para reduzir meu problema ao mínimo, começo com um objeto selecionado com UV válido. Em seguida, executo o seguinte 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)
Acho que o que está faltando é a vinculação correta da imagem ao nó de textura. Consultei questões semelhantes, como
Definir nó de imagem ativa com python
mas suas respostas não ajudaram (código para Blender 2.7 que não é mais compatível, eu acho).
Respostas
Acho que vou dar alguns passos básicos, ou seja, adicionar um nó do tipo "TEX_IMAGE", atribuir sua imagem a ele. Portanto:
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 ao máximo usar bpy.ops, neste caso, como você pode ver, é fácil criar uma imagem com os métodos bpy.data.images.new () Qualquer objeto blender pode ser criado com esse método.
bpy.data.objects.new()
bpy.data.materials.new()
bpy.data.scenes.new()
...
...
bpy.ops é bom usá-lo somente quando você não tem alternativas, como neste caso com o bpy.ops.object.bake()
isso permite que você crie algo e atribua-o diretamente a uma variável, como no exemplo de img = bpy.data.images.new()
Então você não precisa ficar louco para ter acesso a ele.