2024年01月21日

Blenderコンポジットノードの素材出力スクリプト

 複雑な合成をする場合、素材をレンダリングし直したいと言う事が頻繁にあります。blenderでのレンダリングは シーンのビューレイヤープロパティの"☑レンダリングに使用する" をアニメートさせる事で制御できます。


図1.コンポジットノードでファイル出力設定
"☑レンダリングに使用する" で不要なレンダリングを回避


 しかし、アニメーションレンダリングで一部の修正を反映させたい時に不便がでます。"☑単一レイヤーのみをレンダリング" で一つのレイヤーでのレンダリングが可能ですが、"☑レンダリングに使用する" のアニメート情報が反映されないなどの特別な不都合が起こります。



★素材出力スクリプト
 "☑レンダリングに使用する"を利用して、アニメート内容を破壊せずに必要ビューレイヤーの必要フレームのみをレンダリングするスクリプトを作成しました。ビューレイヤーを全くレンダリングせず、コンポジット動画のみを出力すると言う事もできます。


★導入方法
⓪図1のようにコンポジットノードでファイル出力先の設定は済ませて置く。"☑レンダリングに使用する"のキーフレームアニメートをすませておく。
@scriptタブのウィンドウ配置でテキストエディタに "下記スクリプト" を貼り付ける。
Aスクリプト名を例えば"render_selectLayer-node"と設定。
Bスクリプト内のレンダリングビューレイヤー名やフレームを書き換え。
CPythonコンソールで bpy.data.texts["render_selectLayer-node"].as_module() を実行。


図2.scriptタブのウィンドウ配置

※"☑レンダリングに使用する"のキーフレームがないとエラーが起こるので"☑レンダリングに使用する"のドライバーと併用できない仕様。

スクリプト名 render_selectLayer-node

import bpy

#####ここを記述(レンダリング用の一時的な設定)#####
#レンダリングレイヤー名リスト入力
SelectLayerNames=["Layer01","Layer02"]#"Layer01","Layer02"をレンダリング
#SelectLayerNames=["Layer01"] #"Layer01"をレンダリング
#SelectLayerNames=["Layer02"]#"Layer02"をレンダリング
#SelectLayerNames=[]#ビューレイヤーはレンダリングせずコンポジット結果だけ出力
#レンダリングフレーム範囲を設定
fr_start=1
fr_end=30
#レンダリング解像度
resol_percent=50
##############################################
#コンソールでの実行コマンド
#bpy.data.texts["render_selectLayer-node"].as_module()
##############################################

def backup_keyframes(s1: str):
# 対象のfcurveを探す
fcurve = bpy.context.scene.animation_data.action.fcurves.find(f'view_layers["{s1}"].use')

# fcurveが見つからない場合はエラーメッセージを表示して終了
if fcurve is None:
print(f"Error: fcurve not found for view_layer {s1}")
return []

# キーフレーム情報をbackup
keyframes_backup = [(keyframe.co.x, keyframe.co.y) for keyframe in fcurve.keyframe_points]
return keyframes_backup


def clear_keyframes(s1: str):
# キーフレーム情報を取得
fcurve = bpy.context.scene.animation_data.action.fcurves.find(f'view_layers["{s1}"].use')

# fcurveが見つからない場合はエラーメッセージを表示して終了
if fcurve is None:
print(f"Error: fcurve not found for view_layer {s1}")
return

# キーフレーム情報をclear
bpy.context.scene.animation_data.action.fcurves.remove(fcurve)

def restore_keyframes(s1: str, keyframes_backup):
# キーフレーム情報を復元
fcurve = bpy.context.scene.animation_data.action.fcurves.new(f'view_layers["{s1}"].use', index=0)
for frame, value in keyframes_backup:
keyframe = fcurve.keyframe_points.insert(frame, value)
keyframe.interpolation = 'CONSTANT'

################
# バックアップ
#b1 = backup_keyframes('Layer02')

# キーフレームをクリア
#clear_keyframes('Layer02')

# バックアップからキーフレームを復元
#restore_keyframes('Layer02', b1)
##################


# 現在のアクティブなシーンを取得
scene = bpy.context.scene

#save org
use_single_layer_org = scene.render.use_single_layer
resol_percent_org = bpy.context.scene.render.resolution_percentage
fr_start_org = bpy.context.scene.frame_start
fr_end_org = bpy.context.scene.frame_end

#set value
scene.render.use_single_layer = False
if 'fr_start' in locals() or 'fr_start' in globals():
bpy.context.scene.frame_start = fr_start
print("fr_start:ok")

if 'fr_end' in locals() or 'fr_end' in globals():
bpy.context.scene.frame_end = fr_end
print("fr_end:ok")

if 'resol_percent' in locals() or 'resol_percent' in globals():
bpy.context.scene.render.resolution_percentage = resol_percent
print("percent:ok")

#backup dates
bu_name=[]
bu_keys=[]

# 共通するビューレイヤーを取得
common_layers = []
for layer_name in SelectLayerNames:
if layer_name in bpy.context.scene.view_layers:
common_layers.append(layer_name)

# 共通するビューレイヤーの名前を表示
for layer_name in common_layers:
print("Render Layer:", layer_name)

for render_layer in scene.view_layers:
if render_layer.name not in SelectLayerNames:
# バックアップ
bu_name.append(render_layer.name)
bu_keys.append(backup_keyframes(render_layer.name))
# キーフレームをクリア
clear_keyframes(render_layer.name)
render_layer.use = False


bpy.ops.render.render(animation=True)

for name , keys in zip( bu_name , bu_keys ):
restore_keyframes(name, keys)

# 元を復元
scene.render.use_single_layer = use_single_layer_org
bpy.context.scene.render.resolution_percentage = resol_percent_org
bpy.context.scene.frame_start = fr_start_org
bpy.context.scene.frame_end = fr_end_org




 ドライパでも "レンダリングに使用する" のアニメート内容を破壊せずに必要ビューレイヤーの必要フレームのみをレンダリングするコントローラを作成したりもしたのですがセッティングがやや大変で、またblender3.6以前ではアクティブでないビューレイヤーの"レンダリングに使用する"のドライバは無効化されるというバグがありそうです。
ラベル:Blender
烏野の箱庭ページ烏野の箱庭 …動画・絵・漫画・脚本などの作品紹介
烏野のyoutubeページ烏野博史動画 …広告・実験・講習用映像のyoutubeチャンネル
烏野のyoutubeページうのひろし日々描描 …作画配信のyoutubeチャンネル
UNOUNOのPixiv …絵、デザイン資料、漫画、実験画像
karasuno10をフォローしましょうkarsauno10のTwitter …考え、宣伝
posted by karasuno10 at 17:25 | Comment(0) | TrackBack(0) | 動画>Blender | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:


この記事へのトラックバック