I am doing texture baking in headless mode and it works for me. Not sure what is the problem with your script but here is my script:
import bpy
import logging
import sys
console_handler = logging.StreamHandler(sys.stdout)
log = logging.getLogger(__name__)
log.addHandler(console_handler)
cuda_devices, opencl_devices = bpy.context.preferences.addons['cycles'].preferences.get_devices(
)
bpy.context.scene.render.engine = "CYCLES"
bpy.context.scene.cycles.device = "GPU"
bpy.context.preferences.addons["cycles"].preferences.compute_device_type = "CUDA"
for device in cuda_devices:
print(f'Activating {device.name}')
device.use = True
break
# need object mode for make_single_user
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.make_single_user(
type="ALL", object=False, obdata=False, material=True)
if 'dynamic' in bpy.data.collections:
bpy.data.collections['dynamic'].hide_render = True
for object in list(bpy.data.objects):
if object.active_material is None:
log.warning("Object %s doesn't have a material. Skipping.", object.name)
continue
log.info("Working on %s", object.name)
bpy.ops.object.select_all(action='DESELECT')
object.select_set(True)
bpy.context.view_layer.objects.active = object
for slot in object.material_slots:
if slot.material is None:
continue
material = slot.material
if not material.use_nodes:
log.warning(
"Active Material of object %s doesn't use nodes. Skipping.", object.name)
continue
nodes = material.node_tree.nodes
gltf = None
shadow = None
occlusion = None
for node in nodes.values():
if node.label == "Shadow":
shadow = node
elif node.label == "Occlusion":
occlusion = node
elif node.type == "GROUP" and node.node_tree and node.node_tree.name == "glTF Metallic Roughness":
gltf = node
if gltf is None:
log.warning("Skipping %s: no gltf node defined", object.name)
continue
shadow_input = None
occlusion_input = None
for input in gltf.inputs:
if input.name == "Shadow":
shadow_input = input
elif input.name == "Occlusion":
occlusion_input = input
if shadow_input is None:
log.warning(
"Skipping %s: gltf group doesn't define a shadow input", object.name)
continue
if occlusion_input is None:
log.warning(
"Skipping %s: gltf group doesn't define a occlusion input", object.name)
continue
shadow = nodes.new(type="ShaderNodeTexImage")
shadow.label = "Shadow"
occlusion = nodes.new(type="ShaderNodeTexImage")
occlusion.label = "Occlusion"
shadow_output = shadow.outputs[0]
occlusion_output = occlusion.outputs[0]
material.node_tree.links.new(shadow_input, shadow_output)
material.node_tree.links.new(occlusion_input, occlusion_output)
image = bpy.data.images.new("shadow", 256, 256)
shadow.image = image
nodes.active = shadow
shadow.select = True
bpy.ops.object.bake(type="SHADOW")
image.pack()
shadow.select = False
image = bpy.data.images.new("occlusion", 256, 256)
occlusion.image = image
nodes.active = occlusion
occlusion.select = True
bpy.ops.object.bake(type="AO")
image.pack()
occlusion.select = False
object.select_set(False)
bpy.ops.wm.save_mainfile()
You can probably delete like 70% of it or so for your usecase. I am especially unsure if the CUDA stuff in the beginning even works. Also this is highly specific to my use case (all the stuff around the glTF node in there) but maybe it helps you solve your issue.