{"id":20850416,"url":"https://github.com/noteed/blending","last_synced_at":"2025-06-20T18:11:24.628Z","repository":{"id":152851527,"uuid":"619991912","full_name":"noteed/blending","owner":"noteed","description":"Notes about scripting Blender from the command-line","archived":false,"fork":false,"pushed_at":"2024-04-09T08:12:48.000Z","size":114,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-12T12:33:10.389Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/noteed.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-03-27T20:19:13.000Z","updated_at":"2023-03-27T20:19:44.000Z","dependencies_parsed_at":"2024-03-30T23:32:13.984Z","dependency_job_id":null,"html_url":"https://github.com/noteed/blending","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/noteed/blending","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noteed%2Fblending","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noteed%2Fblending/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noteed%2Fblending/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noteed%2Fblending/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/noteed","download_url":"https://codeload.github.com/noteed/blending/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noteed%2Fblending/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260993957,"owners_count":23094275,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T03:09:20.937Z","updated_at":"2025-06-20T18:11:19.617Z","avatar_url":"https://github.com/noteed.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Scripting Blender from the command-line\n\nThis repository contains notes and exploratory scripts about using Python to\nscript Blender from the command-line.\n\nI'm using Blender on NixOS, with the following shell:\n\n```\n$ nix-shell -p blender -I nixpkgs=channel:nixos-unstable\n```\n\nBlender has plenty of command line options:\n\n```\n$ blender --version\nBlender 3.3.1\n$ blender --help\n...\n```\n\n# Rendering\n\nRender frame 0:\n\n```\n$ blender --background --engine CYCLES --render-frame 0\n```\n\nThe image is saved in `/tmp/`, e.g. as `/tmp/0000.png`. This renders the\ndefault scene. Often you'll want to give a specific `.blend` as an argument.\n\n# Python\n\nIt is possible to use Blender to run scripts (written in Python) from the\ncommand-line, and without showing its graphical user interface.\n\n```\n$ blender --background --python-console\n$ blender --background --python list-objects.py\n```\n\n`--python` can be given multiple times to chain scripts.\n\n# empty.blend\n\nBlender, even when called from the command-line to run a script as above, loads\na default scene before doing anything else. This means for instance that the\n`list-objects.py` script will indeed show some content: the default scene\ncontains a cube mesh, a lamp, and a camera. This is also the scene being\nrendered by the `--engine CYCLES --render-frame 0` line above.\n\nIt is possible to supply a specific `.blend` file as the initial scene to load,\nand the script will run \"on top\" of it.\n\nIn some cases, such as scripts that generate a scene content, it's useful to\nstart with nothing. For that reason, this directory includes an `empty.blend`\nfile.\n\nAs an example, contrast the output of these two lines:\n\n```\n$ blender --background --python src/list-objects.py\n$ blender empty.blend --background --python src/list-objects.py\n```\n\n# Command-line arguments\n\nTo have an idea of how scripts are called, here is `sys.argv`:\n\n```\nBlender 3.3.1\nRead prefs: /home/thu/.config/blender/3.3/config/userpref.blend\n/run/user/1000/gvfs/ non-existent directory\nArguments: ['/nix/store/d9y485naqfandxmwkf8603606wzjmmxm-blender-3.3.1/bin/blender', '--python-use-system-env', '--background', '--python', 'src/list-args.py', '--', 'dummy']\n\nBlender quit\n```\n\nNote that a `--python-use-system-env` argument has been given. This is probably\ncaused by how Blender is packaged for NixOS. This is useful because it allows\nus to set the `PYTHONPATH` environment variable to modularize our scripts and\nload separate code as modules.\n\n# Script organization\n\nScripts can setup a scene or modify an existing one (and save a `.blend` file\nbefore exiting), and they can generate images. But as shown above, it is also\npossible to render a scene without calling a script.\n\nIn practice I prefer to either generate an image and not save any `.blend`\nfile, or save a `.blend` file and leave the rendering a separate call to\nBlender.\n\n# Blender as a library\n\nIt is possible to build Blender to be a Python module and have the Python code\ndrive Blender instead of the other way around. I haven't tried yet.  See [this\npage](https://wiki.blender.org/wiki/Building_Blender/Other/BlenderAsPyModule).\n\n# Creating a simple scene\n\nThe script `src/create-scene.py` almost recreates the default Blender scene: a\ncube, a lamp, and a camera.\n\nThe main difference is that a red material is defined and applied to the cube.\n\nThe lamp and the camera are positioned similarly to the original scene; opening\nthe file and hitting F12 should render the cube centered (and red).\n\nThe material is defined in a separate file, `src/materials.py`, so that it can\npotentially be reused across multiple scripts. To allow `import`ing that module\nin the script, we have to set the `PYTHONPATH` environment variable.\n\nNote that allowing the usage of that environment variable seems to be done\nthrough the `--python-use-system-env` option of Blender, which is done for us\nautomatically on NixOS.\n\nSee the comment in the script for how it can be run.\n\n# Rendering 2D shaders\n\nInpired by this [Adam Morse\npost](https://components.ai/files/pub/ntYEnMsFEpobrsSoSabY), I wanted to setup\na scene to generate images from shaders. The `.blend` file given with the post\nuses a perspective camera pointed at a square plane, and a \"sun\" lamp is used\nto uniformely light the scene.\n\nThis repository contains two alternative ways to generate images from a shader:\n`src/render-checkerboard.py` and `src/bake-checkerboard.py`.\n\n```\n$ PYTHONPATH=src/ blender empty.blend --background --python src/render-checkerboard.py\n$ PYTHONPATH=src/ blender empty.blend --background --python src/bake-checkerboard.py\n```\n\nThose scripts are better run \"on top\" of an `empty.blend` scene: they will each\nconstruct a scene containing a plane with an attached shader and convert it to\nan image.\n\nThe first script, the `render-` one, uses a similar setup to Adam's with two\ndifferences (in addition that it is done by a script, instead of manually): the\nplane is not a square but is created to match the output aspect ratio, and the\ncamera is an orthographic one.\n\nI don't know if this would actually affect the \"quality\" (this is subjective\nanyway) of the output, but I want the ability to \"zoom back\" from the plane in\nthe case the shader is using e.g. bump maps or normal maps, or to showcase\nreflections, and still see a (non-square) rectangle.\n\nThe second script, the `bake-` one, is not using a camera, nor a lamp. Instead\nit bakes the shader to an image.\n\nThe resulting images are almost the same but not exactly. Although the\ncheckerboard patterns are placed in the same way, the \"rendered\" version has it\nblack square corners not exactly touching each others.\n\nNote: implementing both of these scripts was a bit of a trial and error process\n(I don't know much about Blender), in particular once I changed the initial\nsquare to a plane matching the output aspect ratio: suddenly, the checkerboard\ncells were no longer squares. Weirdly enough, this required to scale the plane\nusing two different ways.\n\nNote: since we can give multiple `--python` arguments to Blender, in addition\nof one of the above script, you can add `--python src/save-blend.py` on the\ncommand line to save the constructed scene and have a look at it within\nBlender (and even edit the shader).\n\n# Thinkpad\n\nOn my Thinkpad, the middle button of the trackpad doesn't work similarly to a middle mouse button (i.e. panning).\n\nThis can be solved with\n\n```\n$ xinput set-prop 'TPPS/2 IBM TrackPoint' 'libinput Scroll Method Enabled' 0 0 0\n```\n\n`TPPS/2 IBM TrackPoint` can be different on different laptops; this can be\ndiscovered with `xinput list`.\n\nThis is related to [the note\nhere](https://wayland.freedesktop.org/libinput/doc/latest/scrolling.html#on-button-scrolling).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoteed%2Fblending","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoteed%2Fblending","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoteed%2Fblending/lists"}