本日はBlenderPython枠です。
Blenderではビューポート上でオブジェクトを非表示にすることができますが、別の設定としてレンダリング対象から外すものがあり、例えばビューポート上では非表示で見えなくてもレンダリング時にレンダリング対象としてレンダリングさせるということができます。
これは筆者だけかもしれないのですが、オブジェクトを非表示にしてレンダリング対象になったままレンダリングしてしまうことでレンダリング後に想定していないオブジェクトが表示されてしまうということがありました。
レンダリングには一定の時間がかかるため、朝起きて発狂しかけたことがあります。
そこで今回はレンダリング時に非表示になっているオブジェクトをすべて一時的にレンダリング対象外にするPythonスクリプトを書いていきます。
〇Pythonを使用したレンダリングの処理
レンダリングを行う際に自動的に処理を開始してほしいのでまずはレンダリングボタンを押した際にレンダリング前にイベントを取得できるか調べていきます
結論から書くとデフォルトのレンダリング方法で処理を途中に挟むのはBlender自体をオーバラップする形になり難しいです。
そのため今回は独自のアドオンとしてレンダリングボタンを作る手法で行っていきます。
pythonコードでBlenderのレンダリングを行う処理は次のようになります。
import bpy # レンダリングの実行 bpy.ops.render.render(write_still=True)
コードを実行すると通常のレンダリング同様にウィンドウが開きます。
つまりこの処理が実行された際にbpy.ops.render.render()を実行する前に処理を挟むことで非表示になっているオブジェクトをすべてレンダリング対象外にすることはできそうです。
例えば次のように実装することでレンダリング直前にログを出力できます。
import bpy def my_callback(scene): # レンダリングが始まる前に実行されるコードをここに書く print("レンダリングが始まる前のイベントです") # コールバックを登録 bpy.app.handlers.render_pre.append(my_callback) # レンダリングの実行 bpy.ops.render.render(write_still=True) # コールバックを削除 bpy.app.handlers.render_pre.remove(my_callback)
〇すべてのオブジェクトから非表示になっているオブジェクトを取得する
次にすべてのオブジェクトから非表示になっているオブジェクトを一覧取得する実装を行います。
コードは次のようになります。
import bpy def log_hidden_render_objects(): # 現在のアクティブなシーンを取得 scene = bpy.context.scene # シーン内のすべてのコレクションを取得 collections = bpy.data.collections # 非表示かつレンダリング対象のオブジェクトを格納するリスト hidden_render_objects = [] # 各コレクション内の非表示かつレンダリング対象のオブジェクトを取得 for collection in collections: for obj in collection.all_objects: if not obj.visible_get() and obj.hide_render: hidden_render_objects.append(obj.name) # ログに非表示かつレンダリング対象のオブジェクトを出力 if hidden_render_objects: print("非表示かつレンダリング対象のオブジェクト:") for obj_name in hidden_render_objects: print(obj_name) else: print("非表示かつレンダリング対象のオブジェクトはありません。") # ログに非表示かつレンダリング対象のオブジェクトを出力 log_hidden_render_objects()
if not obj.visible_get():
によって現在searchしているオブジェクトが非表示であるかどうかを調べることができます。
また'not obj.hide_render:'を条件に追加しこれによって非表示勝レンダリング対象のオブジェクトを含めています。
obj.hide_render
でレンダリング対象外のオブジェクトを検索します。
以上で条件が整いました。
〇Blenderでレンダリング時に非表示になっているオブジェクトをすべてレンダリング対象外にする
割き二つの実装を組み合わせると次のようになります。
import bpy def hidden_render_objects(): # 現在のアクティブなシーンを取得 scene = bpy.context.scene # シーン内のすべてのコレクションを取得 collections = bpy.data.collections # 非表示かつレンダリング対象のオブジェクトを格納するリスト hidden_render_objects = [] for collection in collections: for obj in collection.all_objects: if not obj.visible_get() and not obj.hide_render: hidden_render_objects.append(obj) if hidden_render_objects: for obj in hidden_render_objects: # レンダリング対象外に設定 obj.hide_render = True print(f"{obj.name} をレンダリング対象外に設定しました。") else: print("非表示かつレンダリング対象のオブジェクトはありません。") # ログに非表示かつレンダリング対象のオブジェクトを出力 hidden_render_objects() # レンダリングの実行 bpy.ops.render.render(write_still=True)
〇動作確認
今回は次のようにキューブを二つ配置しました。
当然ですがこのままレンダリングすると次のように2つのキューブが発生します。
次に今回作成したコードベースで実行すると次のようにキューブが1つになりBlenderのビューポート同様にレンダリングが行われていることを確認できました。
本日は以上です。