Запекать текстурную карту с питоном

Aug 15 2020

Я использую Blender 2.83. Для надстройки (доступной из 3D-View) я хочу запечь текстурные карты. Я прекрасно умею это делать без скриптов. Но с python у меня не получилось.

Чтобы свести мою проблему к минимуму, я начинаю с выбранного объекта с допустимым UV. Затем я выполняю следующий скрипт на 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)

Я думаю, что мне не хватает правильной привязки изображения к узлу текстуры. Я консультировался с аналогичными вопросами, такими как

Установите активный узел изображения с помощью Python

но их ответы не помогли (я полагаю, код для Blender 2.7 больше не совместим).

Ответы

3 NoobCat Aug 22 2020 at 01:23

Думаю, я дам вам несколько основных шагов, то есть добавлю узел типа «TEX_IMAGE», назначу ему свое изображение. следовательно:

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)

По возможности избегайте использования bpy.ops, в этом случае, как видите, легко создать изображение с помощью методов bpy.data.images.new () С помощью этого метода можно создать любой объект блендера.

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

bpy.ops его хорошо использовать только тогда, когда у вас нет альтернатив, как в этом случае с bpy.ops.object.bake()

это позволяет вам создавать что-то и напрямую присваивать это переменной, как в примере img = bpy.data.images.new()Итак, вам не нужно сходить с ума, чтобы получить к нему доступ.