LoginSignup
3

More than 1 year has passed since last update.

単純な画像ベイク機能をアドオンにしてみる

Posted at

Blender Advent Calendar 2020 の23日として投稿します。
https://qiita.com/advent-calendar/2020/blender

ゲーム用モデルやVRchatアバターのテクスチャを作るのに
シェーダーで作ったテクスチャをベイクしたり UVを整理した画像にベイクしたいという用途があるのか
春頃からBlenderでのテクスチャのベイクに関する話題を見かけることが増えたように思います。

私もとある仕事で ボタン一つ操作でベイク画像を用意する必要がある案件に遭遇したので
目的のベイク画像を作成するアドオンを作成しました。

画像エディッタに表示しているイメージに、現在アクティブにしているUVを利用して
ディフューズカラーのをベイクします。

ySympleBekeImage.py
import bpy
bl_info = {
    "name": "Simple Bake Image",
    "description": "UVエディッタで表示中の画像にオブジェクトの色をベイク",
    "author": "Yukimi",
    "version": (0,9),
    "blender": (2, 80, 0),
    "location": "material",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "http://yukimi-blend.blogspot.jp/",
    "category": "material"}


# ベイク用のノードの作成
def criete_bake_terget(mat, image, uv_layer):
    node_tree = mat.node_tree
    img_node = node_tree.nodes.new("ShaderNodeTexImage")
    img_node.image = image
    uv_node = node_tree.nodes.new("ShaderNodeUVMap")
    uv_node.uv_map = uv_layer.name
    node_tree.links.new( uv_node.outputs[0], img_node.inputs[0] )
    #ベイク対象はアクティブなノード
    node_tree.nodes.active = img_node
    return(img_node, uv_node)
# ベイク用マテリアルの消去
def crean_beke_terget(beke_nodes):
    for m in beke_nodes:
        mat = m[0]
        img_node = m[1][0]
        uv_node = m[1][1]
        mat.node_tree.nodes.remove(img_node)
        mat.node_tree.nodes.remove(uv_node)
# ベイク
def Simple_bake(scene):
    # 現在のレンダリング設定の退避
    ref_engine = scene.render.engine
    scene.render.engine = 'CYCLES'
    # 現在のサンプル数の退避
    ref_sampkung = scene.cycles.samples
    scene.cycles.samples = 8
    #ベイク動作
    bpy.ops.object.bake(type='DIFFUSE', pass_filter={'COLOR',}, use_clear=False)
    # 放射ノードの出力を使う場合はこちらをコメントアウト
    #bpy.ops.object.bake(type='EMIT', use_clear=False)
    # サンプリング数を元に
    scene.cycles.samples = ref_sampkung
    # レンダリングエンジンを元に
    scene.render.engine = ref_engine

def bake_func(context):
    scene = context.scene
    obj = bpy.context.active_object
    # アクティブオブジェクトがメッシュか?
    if obj.type != "MESH": return()
    if context.space_data.mode != 'UV': return()
    # ビューで表示中の画像の取得
    image = context.space_data.image
    # UVの取得
    uv_layer = obj.data.uv_layers[obj.data.uv_layers.active_index]
    # 個々のマテリアルでループ
    # (複数マテリアルがある場合 それぞれにベイク用ノードが設定されている必要あり)  
    bake_nodes = []
    for slot in  obj.material_slots:
        mat = slot.material
        nodes = criete_bake_terget(mat, image, uv_layer)
        bake_nodes.append([mat,nodes])
    #ディフューズカラーのみベイク
    Simple_bake(scene)
    #ベイクに使用したノードをクリーンナップ
    crean_beke_terget(bake_nodes)


###################################################
class bake_OT_diffusecolor(bpy.types.Operator):
    '''bake diffuse coor to display Image'''
    bl_idname = "action.bake_diffuse"
    bl_label = "bake diffuse coor to display Image"
    def execute(self, context):
        bake_func(context)
        return {'FINISHED'}


def menu_func(self, context):
    self.layout.operator("action.bake_diffuse", 
        text="カラーを表示画像にベイク" )

def register():
    bpy.utils.register_class(bake_OT_diffusecolor)
    bpy.types.IMAGE_MT_image.prepend(menu_func)

def unregister():
    bpy.types.IMAGE_MT_image.remove(menu_func)
    bpy.utils.unregister_class(bake_OT_diffusecolor)

if __name__ == "__main__":
    register()
##########################################################

インストールすると 画像メニューに「カラーを表示画像にベイク」という項目が追加されます。
image.png

単純にベイクするだけならTexToolsにあるベイク機能等でもいいのですが
複数のオブジェクトのマテリアルの画像をまとめる といった作業の場合には使えないですし
UVの指定やベイク対象の指定等の作業は煩雑ですよね。

Simple_bake関数を書き換えることで 現場に合った画像を出力するのに使えるのではないかと思います
今回はディフューズカラーのみなので サンプリング数を下げることでベイク速度を上げています。
また、複数のオブジェクトにまたがってベイクを調整する時のために 既存の画像はクリアしない設定にしています。

何かしら役に立てば幸いです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3