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 | このブログの読者になる | 更新情報をチェックする

2021年09月28日

blender2.9.3で頂点のカスタム法線の修正

 blenderでスムーズシェーディングの描画の崩れを直す方法、主に頂点のカスタム法線の修正方法を記述しておきます。

 3Dソフトの使用時に以下のようにオブジェクト表面が黒ずんだり、明るくなる不具合に出会った事はないでしょうか。スムーズシェーディングに失敗した時に起きる現象です。

 頂点法線はスムーズシェーディング時に使用されます。シェーディングには"フラットシェーディング"と"スムーズシェーディング"の二つがあります。フラットシェーディングは面法線を元に描画計算します。スムーズシェーディングは頂点法線も使用して滑らかに描画計算します。スムーズシェーディングを使うと少ない頂点数でも滑らかに見せる事ができます。(※1)

 頂点法線の向きは編集する事ができ、これを "カスタム法線" と呼びます。頂点が密集・折り重なっているオブジェクトほどスムーズシェーディング時にカスタム法線が崩れがちです。

例えば、頂点数の多いオブジェクトを不正確にインポートすると法線情報が崩れます。

というわけで以下頂点法線編集方法。
■■■法線情報の編集
法線の表示
  編集モード > "show overlay" > "Normals" > 必要法線を表示

頂点法線情報(カスタム法線)のリセット
 Mesh > Normals > Reset Vectors
 @法線の回転による設定
  Mesh > Normals > Rotate( "Alt + N" キー > Rotate)

 AX,Y,Zキーで軸回転をできる。

面から頂点法線を設定
  Mesh > Normals > Set From Faces( "Alt + N" キー > Set From Faces)

■■オブジェクト単位での自動スムーズシェーディングと角度指定
 @オブジェクトを右クリック > "Shade Smooth" 。
 A"Object Data Properties" タブ > "Normals" パネル > 自動スムーズを有効☑にして角度設定。設定角度以下のエッジがスムーズシェーディング。
  
カスタム法線情報のクリア方法
 カスタム法線が設定されると自動スムーズの角度設定はできない。
 "Object Data Properties"タブ  > "Geometry Data" > "Clear Custom Split Normals Data"
  →自動スムーズの角度を設定できるようになる。(※2)

■■面単位での自動でないスムーズシェーディングの設定
 Mesh > Shading > smooth Faces

■■■前のコマンドの繰り返し(回転角度こみで)
 Shift + R


【参考】
・(※1)面法線と頂点法線
・(※2)法線 (Normals / Smooth Shading) [Blender]
烏野の箱庭ページ烏野の箱庭 …動画・絵・漫画・脚本などの作品紹介
烏野のyoutubeページ烏野博史動画 …広告・実験・講習用映像のyoutubeチャンネル
烏野のyoutubeページうのひろし日々描描 …作画配信のyoutubeチャンネル
UNOUNOのPixiv …絵、デザイン資料、漫画、実験画像
karasuno10をフォローしましょうkarsauno10のTwitter …考え、宣伝
posted by karasuno10 at 20:00 | Comment(0) | 動画>Blender | このブログの読者になる | 更新情報をチェックする

2021年05月10日

blenderでフレーム毎にレンダリングするViewlayerを決めていく方法

 フレーム毎に使用するviewlayerのみをレンダリングして欲しいですよね。
 しかし、blenderのデフォルト設定では毎フレーム作成したViewlayer全てをレンダリングしてしまいます。仮に4レイヤー作成すると4倍のレンダリング時間がかかる事になります。レンダリング時間の短縮のために、フレーム毎のレンダリングするviewlayerをコントロール方法を調べました。

 結論から言うとViewLayerの Sceneプロパティ内、”Use For rendering”を アニメートするとフレーム毎の各ViewLayerのレンダリングを制御できます

順を追って説明します。まずView Layer名「1」、「2」の二つを用意します。
0〜19フレームはView Layer「2」を使用し、20フレーム以降はView Layer「1」を使用する設定で作ってみます。


 @、まず0フレーム目でコンポジットノードウィンドウの”Render Layers"ノードの"View Lalyer”を「2」に指定。右クリックでキーフレームを打ちます。この時点ではレンダリングに使用されるView Layerは2のみなのですが、内部的には「1」「2」ともレンダリングされてしまいます。

 A、次にView layers「2」のSceneプロパティ内、”Use For rendering”をチェックを入れます。同じく右クリックからキーフレームを打ちます。


 B、View layers「1」のSceneプロパティ内、”Use For rendering”をチェックを外します。同じく右クリックからキーフレームを打ちます。あえてレンダリングを外すためにはここが大事です。これで0フレーム目のセットアップは終わりです。



 同じようにして20フレーム目で使用するViewLayerを変更します。
 Cまずコンポジットノードの”Render Layers”ノードを「1」変更。
 D次にViewlayer「1」のチェックを入れます。


 E最後にViewlayer「2」のチェックを外します。


 以上で設定終了です。これでレンダリング時間を気にする事なくViewlayerを作り複雑なコンポジットができるようになります。

 注意点として”Use For rendering”の下の "Render Single Layer"のチェックは入れないでください。”Use For rendering”の設定を無視して現在編集中のViewlayersのみをレンダリングしてしまいます。
烏野の箱庭ページ烏野の箱庭 …動画・絵・漫画・脚本などの作品紹介
烏野のyoutubeページ烏野博史動画 …広告・実験・講習用映像のyoutubeチャンネル
烏野のyoutubeページうのひろし日々描描 …作画配信のyoutubeチャンネル
UNOUNOのPixiv …絵、デザイン資料、漫画、実験画像
karasuno10をフォローしましょうkarsauno10のTwitter …考え、宣伝
posted by karasuno10 at 19:48 | Comment(0) | 動画>Blender | このブログの読者になる | 更新情報をチェックする