はじめに
この記事では、Blender 4.0でPython APIを使用して文字を表示し、レンダリングする手順を説明します。このプロセスは、コマンドラインからBlenderを操作し、自動化タスクを実行する際に役立ちます。
こちらの記事もおすすめ
必要なツール
- Blender 4.0
- 基本的なPythonの知識
クリプトの準備
まず、Blenderをバックグラウンドで実行し、テキストオブジェクト、カメラ、ライトを作成してレンダリングするスクリプトを準備します。以下のスクリプトをテキストエディタにコピーし、background_job.py
という名前で保存します。
# This script is an example of how you can run blender from the command line
# (in background mode with no interface) to automate tasks, in this example it
# creates a text object, camera and light, then renders and/or saves it.
# This example also shows how you can parse command line options to scripts.
#
# Example usage for this test.
# blender --background --factory-startup --python $HOME/background_job.py -- \
# --text="Hello World" \
# --render="/tmp/hello" \
# --save="/tmp/hello.blend"
#
# Notice:
# '--factory-startup' is used to avoid the user default settings from
# interfering with automated scene generation.
#
# '--' causes blender to ignore all following arguments so python can use them.
#
# See blender --help for details.
import bpy
def example_function(text, save_path, render_path):
# Clear existing objects.
bpy.ops.wm.read_factory_settings(use_empty=True)
scene = bpy.context.scene
# Set the render engine to Eevee
bpy.context.scene.render.engine = 'BLENDER_EEVEE'
bpy.context.scene.eevee.use_bloom = True
# Text Object
txt_data = bpy.data.curves.new(name="MyText", type='FONT')
txt_ob = bpy.data.objects.new(name="MyText", object_data=txt_data)
scene.collection.objects.link(txt_ob)
txt_data.body = text
txt_data.align_x = 'CENTER'
# Text Material (Emission)
mat = bpy.data.materials.new(name="EmissionMaterial")
mat.use_nodes = True
nodes = mat.node_tree.nodes
nodes.clear() # clear all the nodes
emission = nodes.new(type='ShaderNodeEmission')
emission.inputs[0].default_value = (1, 1, 1, 1) # white color
emission.inputs[1].default_value = 5.0 # strength
output = nodes.new(type='ShaderNodeOutputMaterial')
links = mat.node_tree.links
link = links.new(emission.outputs[0], output.inputs[0])
txt_ob.data.materials.append(mat)
# Camera
cam_data = bpy.data.cameras.new("MyCam")
cam_ob = bpy.data.objects.new(name="MyCam", object_data=cam_data)
scene.collection.objects.link(cam_ob)
scene.camera = cam_ob
cam_ob.location = 0.0, 0.0, 10.0
# Sun Light
light_data = bpy.data.lights.new("MyLight", 'SUN')
light_ob = bpy.data.objects.new(name="MyLight", object_data=light_data)
scene.collection.objects.link(light_ob)
light_ob.location = 2.0, 2.0, 5.0
light_ob.data.energy = 5.0 # adjust the energy for desired brightness
bpy.context.view_layer.update()
if save_path:
bpy.ops.wm.save_as_mainfile(filepath=save_path)
if render_path:
render = scene.render
render.use_file_extension = True
render.filepath = render_path
bpy.ops.render.render(write_still=True)
def create_simple_scene(save_path, render_path):
# Clear existing objects
bpy.ops.wm.read_factory_settings(use_empty=True)
scene = bpy.context.scene
# Create a simple cube
bpy.ops.mesh.primitive_cube_add(size=2)
cube = bpy.context.object
# Camera
cam_data = bpy.data.cameras.new("Camera")
cam_ob = bpy.data.objects.new("Camera", cam_data)
scene.collection.objects.link(cam_ob)
scene.camera = cam_ob
cam_ob.location = (5, -5, 5)
cam_ob.rotation_euler = (0.785398, 0, 0.785398)
# Light
light_data = bpy.data.lights.new(name="Light", type='POINT')
light_ob = bpy.data.objects.new("Light", light_data)
scene.collection.objects.link(light_ob)
light_ob.location = (0, 0, 5)
# Update the scene
bpy.context.view_layer.update()
# Save and Render
if save_path:
bpy.ops.wm.save_as_mainfile(filepath=save_path)
if render_path:
render = scene.render
render.use_file_extension = True
render.filepath = render_path
bpy.ops.render.render(write_still=True)
def main():
import sys # to get command line args
import argparse # to parse options for us and print a nice help message
# get the args passed to blender after "--", all of which are ignored by
# blender so scripts may receive their own arguments
argv = sys.argv
if "--" not in argv:
argv = [] # as if no args are passed
else:
argv = argv[argv.index("--") + 1:] # get all args after "--"
# When --help or no args are given, print this help
usage_text = (
"Run blender in background mode with this script:"
" blender --background --python " + __file__ + " -- [options]"
)
parser = argparse.ArgumentParser(description=usage_text)
# Example utility, add some text and renders or saves it (with options)
# Possible types are: string, int, long, choice, float and complex.
parser.add_argument(
"-t", "--text", dest="text", type=str, default="Hello World",
help="This text will be used to render an image",
)
parser.add_argument(
"-s", "--save", dest="save_path", metavar='FILE', default="/tmp/hello.blend",
help="Save the generated file to the specified path",
)
parser.add_argument(
"-r", "--render", dest="render_path", metavar='FILE', default="/tmp/hello2",
help="Render an image to the specified path",
)
print(">>> args")
args = parser.parse_args(argv) # In this example we won't use the args
print(args)
if not args.text:
print("Error: --text=\"some string\" argument not given, aborting.")
parser.print_help()
print("see you...")
return
# Run the example function
example_function(args.text, args.save_path, args.render_path)
#create_simple_scene(args.save_path, args.render_path)
print("Batch job finished, exiting")
print("batch job finished, exiting")
if __name__ == "__main__":
main()
スクリプトの解説
スクリプトは大きく分けて3つの部分から構成されます。
example_function
この関数は、テキストオブジェクトを作成し、EeveeレンダーエンジンでBloom効果を有効にして、シーンをレンダリングします。
- テキストオブジェクトの作成
- エミッションマテリアルの追加
- カメラとサンライトの設定
- レンダリングと保存の設定
main
この関数は、コマンドライン引数を解析し、上記のexample_function
を実行します。
- 引数解析
-
example_function
の呼び出し
スクリプトの実行部
最後に、スクリプトが直接実行された場合にmain
関数を呼び出します。
コマンドラインからの実行
Blenderをインストールしたディレクトリに移動し、以下のコマンドを実行します。
blender --background --factory-startup --python /path/to/background_job.py -- --text="Your Text" --render="/path/to/render.png" --save="/path/to/save.blend"
-
--background
はBlenderをバックグラウンドモードで起動します。 -
--factory-startup
はユーザー設定を無視して、デフォルト設定でBlenderを開始します。 -
--python
はPythonスクリプトを指定します。 -
--text
,--render
,--save
はスクリプトに渡す引数です。
結果の確認
コマンドを実行した後、指定したレンダーパスに画像ファイルが、保存パスにBlenderファイルが生成されていることを確認します。
まとめ
この記事では、BlenderのPython APIを使用して、テキストを含むシンプルな3Dシーンを自動的に作成し、レンダリングする方法を紹介しました。この技術は、3Dグラフィックスの自動化やバッチ処理に非常に有効です。今後は、Twitter用に作成した動画をインスタグラムやTiktok用に変換するスクリプトを作成していきます。
リポジトリ
参考サイト