#!/usr/bin/env python3 import hashlib import json import pathlib import sys import bpy from mathutils import Vector WASM_SHA256 = "25bc1e286fd3b72c2c7c082b85a29b2d0bb109588a6dc0de5be94fcdc37cc88c" def digest(value): if isinstance(value, bytes): payload = value else: payload = value.encode("utf-8") return hashlib.sha256(payload).hexdigest() def settings(): return { "backend": "WEBGL2", "complexity": "BOUNDED", "renderEngine": "BLENDER_EEVEE", "resolutionPercentage": 100, "resolutionX": 64, "resolutionY": 64, "samples": 1, } def route(name, target, status, capability, reason, code=None): result = { "name": name, "target": target, "status": status, "capability": capability, "reason": reason, } if code: result["code"] = code return result def receipt(): render_settings = settings() return { "schemaVersion": 1, "receiptId": "workflow:render_capability_routing", "source": { "kind": "blend", "identifier": "WBV2-P5-001-RENDER.ROUTING", "sha256": digest("blend:WBV2-P5-001-RENDER.ROUTING"), }, "settings": { **render_settings, "sha256": digest(json.dumps(render_settings, sort_keys=True, separators=(",", ":"))), }, "build": {"version": "5.2.0", "buildSha256": WASM_SHA256}, "routes": [ route("boundedEevee", "WEB_LOCAL_BOUNDED", "READY", "WEB_REALTIME_BOUNDED", "BOUNDED_EEVEE"), route("cycles", "SERVER_JOB", "BLOCKED", "CYCLES_SERVER_RENDER", "CYCLES_REQUIRES_SERVER", "SERVER_JOB_UNAVAILABLE"), route("complexEevee", "SERVER_JOB", "BLOCKED", "COMPLEX_EEVEE_SERVER_RENDER", "COMPLEX_EEVEE_REQUIRES_SERVER", "SERVER_JOB_UNAVAILABLE"), route("hardware", "SERVER_JOB", "BLOCKED", "HARDWARE_SERVER_RENDER", "HARDWARE_BACKEND_REQUIRES_SERVER", "SERVER_JOB_UNAVAILABLE"), route("webgpu", "WEB_LOCAL_BOUNDED", "BLOCKED", "WEB_REALTIME_BOUNDED", "WEBGPU_UNAVAILABLE", "WEBGPU_RENDERER_UNAVAILABLE"), route("unknownEngine", "SERVER_JOB", "BLOCKED", "UNSUPPORTED_RENDER_ENGINE", "UNSUPPORTED_ENGINE", "PLATFORM_CAPABILITY_UNAVAILABLE"), ], "recovery": { "cancellation": "OPEN_CANCELLED", "deviceLoss": "RELEASED", "temporaryResourcesAfter": 0, "publishedResults": 0, }, } def make_fixture(output): bpy.ops.wm.read_factory_settings(use_empty=True) scene = bpy.context.scene scene.name = "WBV2P5001RenderRoutingScene" scene.render.engine = "BLENDER_EEVEE" scene.render.resolution_x = 64 scene.render.resolution_y = 64 scene.render.resolution_percentage = 100 scene.render.image_settings.file_format = "PNG" scene.render.image_settings.color_mode = "RGBA" scene.render.image_settings.color_depth = "8" scene.render.film_transparent = False scene.render.dither_intensity = 0 scene.eevee.taa_render_samples = 1 scene.view_settings.look = "None" scene.view_settings.exposure = 0 scene.view_settings.gamma = 1 world = bpy.data.worlds.new("WBV2P5001RenderWorld") world.use_nodes = True world.node_tree.nodes["Background"].inputs["Color"].default_value = (0.03, 0.04, 0.06, 1) world.node_tree.nodes["Background"].inputs["Strength"].default_value = 0.5 scene.world = world bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 0)) cube = bpy.context.object cube.name = "WBV2P5001RenderCube" cube.data.name = "WBV2P5001RenderMesh" material = bpy.data.materials.new("WBV2P5001RenderMaterial") material.use_nodes = True principled = material.node_tree.nodes.get("Principled BSDF") principled.inputs["Base Color"].default_value = (0.12, 0.42, 0.8, 1) principled.inputs["Roughness"].default_value = 0.6 cube.data.materials.append(material) camera_data = bpy.data.cameras.new("WBV2P5001RenderCamera") camera = bpy.data.objects.new("WBV2P5001RenderCamera", camera_data) scene.collection.objects.link(camera) camera.location = (4.5, -4.5, 3.2) camera.rotation_euler = (Vector((0, 0, 0)) - camera.location).to_track_quat("-Z", "Y").to_euler() camera_data.lens = 52 scene.camera = camera text = bpy.data.texts.new("WBV2-P5-001-RenderRoutingReceipt") text.write(json.dumps(receipt(), sort_keys=True, separators=(",", ":"))) bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(output).resolve()), check_existing=False, compress=True) if __name__ == "__main__": arguments = sys.argv[sys.argv.index("--") + 1 :] if len(arguments) != 1: raise SystemExit("usage: blender -b --factory-startup --python WBV2-P5-001.py -- OUTPUT") make_fixture(arguments[0])