"""Tiger: renders (headless, nothing saved). blender.exe -b Tender_Tiger.blend -t 0 --python build/tg_render.py -- TAG [samples] [what] what: "look" the picture's camera in the studio light -> previews/compare/_render.png (tg_pair.py sets it beside the picture) "views" studio views from other sides -> previews/_studio_.png "wire" the same views with the wireframe over the shading -> previews/_topo_.png "all" (default) all three """ import bpy import math import os import sys from mathutils import Vector HERE = os.path.dirname(os.path.abspath(__file__)) ROOT = os.path.dirname(HERE) args = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [] TAG = args[0] if args else "v1" SAMPLES = int(args[1]) if len(args) > 1 else 64 WHAT = args[2] if len(args) > 2 else "all" sc = bpy.context.scene sc.render.engine = 'CYCLES' sc.cycles.samples = SAMPLES sc.cycles.use_denoising = True try: prefs = bpy.context.preferences.addons['cycles'].preferences for kind in ('OPTIX', 'CUDA', 'HIP', 'ONEAPI'): try: prefs.compute_device_type = kind except Exception: continue prefs.refresh_devices() if any(d.type == kind for d in prefs.devices): for d in prefs.devices: d.use = d.type == kind sc.cycles.device = 'GPU' break except Exception as ex: print("GPU not set", ex) sc.view_settings.view_transform = 'Standard' sc.view_settings.look = 'None' sc.render.image_settings.file_format = 'PNG' pic_cam = bpy.data.objects["TIGER | Picture camera"] if WHAT in ("look", "all"): sc.camera = pic_cam sc.render.resolution_x, sc.render.resolution_y = 827, 803 sc.render.filepath = os.path.join(ROOT, "previews", "compare", TAG + "_render.png") bpy.ops.render.render(write_still=True) cd = bpy.data.cameras.new("_views") cam = bpy.data.objects.new("_views", cd) sc.collection.objects.link(cam) C = Vector((0.0, 1.1, -0.05)) SHOTS = {"hero": ((7.6, -7.2, 2.6), 50), "front": ((0.6, -11.0, 0.6), 50), "side": ((12.0, 1.3, 0.4), 45), "top": ((0.01, 1.1, 13.0), 45), "rear": ((-7.0, 10.0, 2.2), 50), "under": ((5.5, -3.0, -7.5), 50), "cockpit": ((1.6, -3.4, 0.9), 35), "clips": ((2.3, -2.5, 2.7), 35), "stern": ((3.6, 7.6, 1.0), 40)} AT = {"cockpit": Vector((0.0, -1.0, 0.15)), "clips": Vector((0.0, -0.12, 1.05)), "stern": Vector((0.0, 4.55, 0.0))} def frame(name): loc, lens = SHOTS[name] cam.location = loc tgt = AT.get(name, C) cam.rotation_euler = (tgt - Vector(loc)).to_track_quat('-Z', 'Y').to_euler() cd.lens = lens if WHAT in ("views", "all"): sc.camera = cam sc.render.resolution_x, sc.render.resolution_y = 1400, 900 for name in SHOTS: frame(name) sc.render.filepath = os.path.join(ROOT, "previews", "%s_studio_%s.png" % (TAG, name)) bpy.ops.render.render(write_still=True) # the tool arm folded down, as docked root = bpy.data.objects.get("Tiger_Root") if root is not None: keep = root["tool_arm_down_deg"] root["tool_arm_down_deg"] = 90.0 for ob in bpy.data.objects: if ob.animation_data: for fc in ob.animation_data.drivers: fc.driver.expression = fc.driver.expression ob.update_tag() bpy.context.view_layer.update() frame("stern") sc.render.filepath = os.path.join(ROOT, "previews", "%s_studio_stern_folded.png" % TAG) bpy.ops.render.render(write_still=True) root["tool_arm_down_deg"] = keep for ob in bpy.data.objects: ob.update_tag() bpy.context.view_layer.update() if WHAT in ("wire", "all"): # the wireframe over a plain grey shading: a Wireframe modifier copy of each mesh, black, beside the solid sc.camera = cam sc.render.resolution_x, sc.render.resolution_y = 1400, 900 wm = bpy.data.materials.new("_wire") wm.use_nodes = True wm.node_tree.nodes["Principled BSDF"].inputs["Base Color"].default_value = (0.0, 0.0, 0.0, 1) gm = bpy.data.materials.new("_grey") gm.use_nodes = True gm.node_tree.nodes["Principled BSDF"].inputs["Base Color"].default_value = (0.55, 0.57, 0.6, 1) for o in [o for o in bpy.data.objects if o.type == 'MESH' and o.name.startswith("SM_Tiger")]: w = o.copy() w.data = o.data.copy() sc.collection.objects.link(w) w.data.materials.clear() w.data.materials.append(wm) mod = w.modifiers.new("wire", 'WIREFRAME') mod.thickness = 0.006 mod.use_replace = True o.data.materials.clear() if False else None for i in range(len(o.material_slots)): o.material_slots[i].material = gm for name in ("hero", "front", "side", "rear"): frame(name) sc.render.filepath = os.path.join(ROOT, "previews", "%s_topo_%s.png" % (TAG, name)) bpy.ops.render.render(write_still=True) print("TIGER RENDERS OK")