ベイクされる側のシェーダーの設定をPythonで書いてみました。
これで面倒な一連な作業を簡略化できる😆
(あくまで自分用なので必要な設定も自分用です🌼)
Contents
やったこと
- 出力用のフォルダをパソコン上に作成する
- マテリアルを作成する
- ディフーズベイク用、ノーマルマップベイク用、AOベイク用の画像を作成する
- ディフーズベイク用、ノーマルマップベイク用、AOベイク用の画像ノードを作成する
- ノード同士をリンクさせる
コード
※ベイク先のオブジェクトが選択されていることが前提
※実行する場合は必ず一度保存を行ってから
import bpy
import os
# マテリアルが設定されていない場合はマテリアルを追加する
if len(bpy.context.object.material_slots) == 0:
material = bpy.data.materials.new(bpy.context.object.name) # マテリアルを作成(名前を指定)
bpy.ops.object.material_slot_add() # 選択しているオブジェクトにマテリアルスロットを追加
bpy.context.object.active_material = material # 選択しているオブジェクトにマテリアルを設定
bpy.context.object.active_material.use_nodes = True # マテリアルのノードを使用をオンにする
# テクスチャ保存用ディレクトリ
image_dir_path = os.path.dirname(bpy.data.filepath) + "/textures/"
# ノードツリー
node_tree = bpy.context.object.material_slots[bpy.context.object.active_material_index].material.node_tree
# 選択中のマテリアルの名前
material_name = bpy.context.object.material_slots[bpy.context.object.active_material_index].material.name
# テクスチャ保存用のディレクトリを作成
os.makedirs(os.path.dirname(image_dir_path), exist_ok=True)
# ディフューズ用画像を作成する
diffuse_image = bpy.data.images.new( name = material_name + "_diffuse", width = 1024, height = 1024, alpha = True ,float_buffer = False)
diffuse_image.file_format = "PNG" # ファイルフォーマットを指定
diffuse_image.filepath_raw = image_dir_path + material_name + "_diffuse" + ".png" # 保存先とファイル名を指定
diffuse_image.save() # 画像を保存
# ノーマルマップ用の画像を作成する
nomal_image = bpy.data.images.new( name = material_name + "_nomal", width = 1024, height = 1024, alpha = False ,float_buffer = False)
nomal_image.file_format = "PNG" # ファイルフォーマットを指定
nomal_image.filepath_raw = image_dir_path + material_name + "_nomal" + ".png" # 保存先とファイル名を指定
nomal_image.save() # 画像を保存
# AO用の画像を作成する
ao_image = bpy.data.images.new( name = material_name + "_ao", width = 1024, height = 1024, alpha = False ,float_buffer = False)
ao_image.file_format = "PNG" # ファイルフォーマットを指定
ao_image.filepath_raw = image_dir_path + material_name + "_ao" + ".png" # 保存先とファイル名を指定
ao_image.save() # 画像を保存
# ディフューズ用画像ノードを作成する
diffuse_image_node = node_tree.nodes.new(type='ShaderNodeTexImage') # 画像ノードを作成する
diffuse_image_node.name = "BakeDiffuseImage" # 名前を指定する
diffuse_image_node.label = "BakeDiffuseImage" # ラベルを指定する
diffuse_image_node.location[0] = -564 # ノードの配置場所Xを指定する
diffuse_image_node.location[1] = 426 # ノードの配置場所Yを指定する
diffuse_image_node.image = diffuse_image # 画像を指定する
# ノーマルマップ用画像ノードを作成する
nomal_image_node = node_tree.nodes.new(type='ShaderNodeTexImage') # 画像ノードを作成する
nomal_image_node.name = "BakeNomalMapImage" # 名前を指定する
nomal_image_node.label = "BakeNomalMapImage" # ラベルを指定する
nomal_image_node.location[0] = -564 # ノードの配置場所Xを指定する
nomal_image_node.location[1] = -137 # ノードの配置場所Yを指定する
nomal_image_node.image = nomal_image # 画像を指定する
# AO用画像ノードを作成する
ao_image_node = node_tree.nodes.new(type='ShaderNodeTexImage') # 画像ノードを作成する
ao_image_node.name = "BakeAOImage" # 名前を指定する
ao_image_node.label = "BakeAOImage" # ラベルを指定する
ao_image_node.location[0] = -564 # ノードの配置場所Xを指定する
ao_image_node.location[1] = 142 # ノードの配置場所Yを指定する
ao_image_node.image = ao_image # 画像を指定する
# ノーマルマップノードを作成する
nomal_map_node = node_tree.nodes.new(type='ShaderNodeNormalMap') # ノーマルマップノードを作成する
nomal_map_node.name = "BakeNomalMap" # 名前を指定する
nomal_map_node.label = "BakeNomalMap" # ラベルを指定する
nomal_map_node.location[0] = -263 # ノードの配置場所Xを指定する
nomal_map_node.location[1] = -137 # ノードの配置場所Yを指定する
# ミックスノード(乗算)を作成する
mix_node = node_tree.nodes.new(type='ShaderNodeMixRGB') # ミックスノードを作成する
mix_node.name = "BakeMixNode" # 名前を指定する
mix_node.label = "BakeMixNode" # ラベルを指定する
mix_node.location[0] = -263 # ノードの配置場所Xを指定する
mix_node.location[1] = 426 # ノードの配置場所Yを指定する
mix_node.blend_type = 'MULTIPLY' # ブレンドモードを乗算に変更する
mix_node.inputs[0].default_value = 1 # 係数を1にする
# ノードをリンクさせる
node_tree.links.new(diffuse_image_node.outputs[0],mix_node.inputs[1])
node_tree.links.new(diffuse_image_node.outputs[1],node_tree.nodes["Principled BSDF"].inputs[19])
node_tree.links.new(nomal_image_node.outputs[0],nomal_map_node.inputs[1])
node_tree.links.new(nomal_map_node.outputs[0],node_tree.nodes["Principled BSDF"].inputs[20])
node_tree.links.new(ao_image_node.outputs[0],mix_node.inputs[2])
node_tree.links.new(mix_node.outputs[0],node_tree.nodes["Principled BSDF"].inputs[0])
忘れたくないことメモ
マテリアルを作成してオブジェクトに適用する手順
material = bpy.data.materials.new(bpy.context.object.name) # マテリアルを作成(名前を指定)
bpy.ops.object.material_slot_add() # 選択しているオブジェクトにマテリアルスロットを追加
bpy.context.object.active_material = material # 選択しているオブジェクトにマテリアルを設定
bpy.context.object.active_material.use_nodes = True # マテリアルのノードを使用をオンにする
1、マテリアルを作成する
material = bpy.data.materials.new(マテリアルの名前)
- マテリアル作成時に引数で名前を指定できる
- この時点ではマテリアルを作っているだけで割り当てられてはいない
2、オブジェクトにマテリアルスロットを追加する
bpy.ops.object.material_slot_add()
- 選択したオブジェクトにマテリアルスロットを追加する
- この使いしたスロットにマテリアルを設定していく流れになる
3、オブジェクトのマテリアルスロットにマテリアルを設定する
bpy.context.object.active_material = マテリアル(サンプルコードの場合material)
4、マテリアルの「ノードを使用」をオンにする
bpy.context.object.active_material.use_nodes = True
- これをしないと、この後Pythonからノードをいじろうとしたときにエラーが発生する
画像の作成方法
# ディフューズ用画像を作成する
diffuse_image = bpy.data.images.new( name = material_name + "_diffuse", width = 1024, height = 1024, alpha = True ,float_buffer = False)
diffuse_image.file_format = "PNG" # ファイルフォーマットを指定
diffuse_image.filepath_raw = image_dir_path + material_name + "_diffuse" + ".png" # 保存先とファイル名を指定
diffuse_image.save() # 画像を保存
1、画像を作成する
image = bpy.data.images.new( name = 画像の名前, width = 幅, height = 高さ, alpha = アルファの有無(True,False) ,float_buffer = 32bit画像を使うか(True(=32bit),False(=8bit)))
- マテリアル作成時に引数で名前を指定できる
- この時点ではマテリアルを作っているだけで割り当てられてはいない
2、ファイルフォーマットを指定する
image.file_format = "PNG"
3,保存先とファイル名を指定する
image.filepath_raw = "ファイルパスを含むファイル名"
- ファイル名を含む、なので拡張子である「.png」も含める
ノードツリーの取得方法
選択中のマテリアルスロットのノードツリーを取得する
node_tree = bpy.context.object.material_slots[bpy.context.object.active_material_index].material.node_tree
- 選択中のオブジェクトの選択中のマテリアルスロットのノードツリーを取得してる
画像ノードの作成方法
# ディフューズ用画像ノードを作成する
diffuse_image_node = node_tree.nodes.new(type='ShaderNodeTexImage') # 画像ノードを作成する
diffuse_image_node.name = "BakeDiffuseImage" # 名前を指定する
diffuse_image_node.label = "BakeDiffuseImage" # ラベルを指定する
diffuse_image_node.location[0] = -564 # ノードの配置場所Xを指定する
diffuse_image_node.location[1] = 426 # ノードの配置場所Yを指定する
diffuse_image_node.image = diffuse_image # 画像を指定する
1、画像ノードを作成する
node = node_tree.nodes.new(type='ShaderNodeTexImage')
- ノードツリーは先ほど取得したものを使用する
2,名前を指定する
node.name = "名前"
- のちにアクセスする際にも必要になる
3、ラベルを指定する
node.label = "ラベル"
- ノードの上に表示されたりするラベル
- 名前と一緒でも問題ない
4、ノードエディタでのノードの表示場所を指定する
diffuse_image_node.location[0] = -564
diffuse_image_node.location[1] = 426
- ノードエディタでの表示場所のXとYを指定する
5、画像を指定する
node.image = image
- 画像の作成方法で作った画像を渡す
ノード同士をリンクさせる
# ノードをリンクさせる
node_tree.links.new(diffuse_image_node.outputs[0],mix_node.inputs[1])
node_tree.links.new(diffuse_image_node.outputs[1],node_tree.nodes["Principled BSDF"].inputs[19])
node_tree.links.new(nomal_image_node.outputs[0],nomal_map_node.inputs[1])
node_tree.links.new(nomal_map_node.outputs[0],node_tree.nodes["Principled BSDF"].inputs[20])
node_tree.links.new(ao_image_node.outputs[0],mix_node.inputs[2])
node_tree.links.new(mix_node.outputs[0],node_tree.nodes["Principled BSDF"].inputs[0])
1、ノード同士をリンクする
node_tree.links.new(アウトプット側のノード.outputs[ソケット番号],インプット側のノード.inputs[ソケット番号])
- ノードツリーを使ってノード同士をリンクさせる
おしまい
そのうち追記するかもしれませんが、今のところ忘れずに覚えておこうと思うあたりを。
これをアドオン化させてボタン一つでできるようにして使っていますけど、かなり便利です😊
私(S.Fuka)が企画、シナリオ、グラフィックを担当させていただきました、にゃっほい屋のゲームがSteamにて配信中です。
もし興味がありましたらSteamページだけでもご覧になっていただければ幸いです。