MRが楽しい

MRやVRについて学習したことを書き残す

Blender2.8で利用可能なpythonスクリプトを作る その49(ノードタイプの判定とノード特有の情報)

本日は Blender の技術調査枠です。
Blender2.8で利用可能なpythonスクリプトを作ります。

ノードタイプの判定とノード特有の情報

マテリアルの有効な出力ノードを取得して、サーフェス入力に接続されているノードがプリンシプルBSDFか判定します。
・Script_check_surface_bsdf.py

# bpyインポート
import bpy

# アクティブな出力ノードに接続されたノードがプリンシプルBSDFかチェックする
# (オブジェクト名指定)
def check_surface_bsdf_checker(arg_objectname="Default",
  arg_materialname:str="BakeTexture") -> bool:
    """アクティブな出力ノードに接続されたノードがプリンシプルBSDFかチェックする

    Args:
        arg_objectname (str, optional): 指定オブジェクト名. Defaults to "Default".
        arg_materialname (str, optional): 指定マテリアル名. Defaults to "BakeTexture".

    Returns:
        bool: 実行正否
    """

    # 指定オブジェクトを取得する
    # (get関数は対象が存在しない場合 None が返る)
    selectob = bpy.data.objects.get(arg_objectname)

    # 指定オブジェクトが存在するか確認する
    if selectob == None:
        # 指定オブジェクトが存在しない場合は処理しない
        return False
    
    # 指定オブジェクトがメッシュオブジェクトか確認する
    if selectob.type != 'MESH':
        # メッシュオブジェクトでない場合は処理しない
        return False

    # 指定マテリアルスロットを取得する
    selectmatslot = selectob.material_slots.get(arg_materialname)

    # 指定マテリアルスロットが存在するか確認する
    if selectmatslot == None:
        # 指定オブジェクトが存在しない場合は処理しない
        return False
    
    # 指定マテリアルを取得する
    selectmat = selectmatslot.material

    # 指定マテリアルが存在するか確認する
    if selectmat == None:
        # 指定オブジェクトが存在しない場合は処理しない
        return False
    
    result = check_surface_bsdf(arg_material=selectmat)

    # 結果を標準出力表示する
    print("active surface is BSDF : " + str(result))

    return True


# 指定マテリアルのアクティブな出力ノードに接続されたノードがプリンシプルBSDFかチェックする
def check_surface_bsdf(arg_material:bpy.types.Material) -> bool:
    """指定マテリアルのアクティブな出力ノードに接続されたノードがプリンシプルBSDFかチェックする

    Args:
        arg_material (bpy.types.Material): 指定マテリアル

    Returns:
        bool: プリンシプルBSDFが接続されているか
    """

    # マテリアルのノードを有効化する
    use_material_node(arg_material=arg_material)

    # アクティブな出力ノードに接続されたノードを取得する
    get_node = get_node_linkoutput(arg_material=arg_material)

    # ノードが取得できたか確認する
    if get_node == None:
        # サーフェスノードが存在しない場合はFalseを返す
        return False

    # ノードの種類がプリンシプルBSDFかチェックして結果を返す
    isBSDF = check_isnode_bsdf(get_node)

    return isBSDF


# アクティブな出力ノードに接続されたノードを取得する
def get_node_linkoutput(arg_material:bpy.types.Material) -> bpy.types.Node:
    """アクティブな出力ノードに接続されたノードを取得する

    Args:
        arg_material (bpy.types.Material): 指定マテリアル

    Returns:
        bpy.types.Node: アクティブな出力ノードに接続されたノード
    """

    # 参照の保存用変数
    name_mapping = {}

    # ノード操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Node.html)
    # ノードリスト操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Nodes.html)
    # ノードツリー操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.NodeTree.html)

    # ターゲットマテリアルのノード参照を取得する
    mat_nodes = arg_material.node_tree.nodes

    # 出力ノードを取得する変数
    output_node = None

    # 出力ノードの操作マニュアル
    # (https://docs.blender.org/api/current/bpy.types.ShaderNodeOutputMaterial.html)

    # 全ノードを走査する
    for check_node in mat_nodes:
        # ノードタイプを取得する
        node_idname = check_node.bl_idname

        # ノードタイプが出力ノードか確認する
        if node_idname == 'ShaderNodeOutputMaterial':
            # アクティブな出力ノードのフラグを取得する
            is_activeoutput = check_node.is_active_output

            # アクティブな出力ノードかチェックする
            if is_activeoutput == True:
                # アクティブな出力ノードなら保持する
                output_node = check_node

    # 出力ノードが取得できたか確認する
    if output_node == None:
        # 出力ノードが存在しない場合は処理しない
        return None
    
    # ノードソケット操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.NodeSocket.html)

    # 出力ノードのサーフェス入力(1番目の入力)のリンクを確認する
    surface_input = output_node.inputs[0]

    # リンクが接続されているか確認する
    if surface_input.is_linked == False:
        # 出力ノードにサーフェスノードが接続されていない場合は処理しない
        return None

    # リンク操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.NodeLink.html#bpy.types.NodeLink)

    # リンクの一覧を取得する
    mat_links = arg_material.node_tree.links

    # 接続元ノードを取得する変数
    surface_node = None

    # リンクを走査する
    for check_link in mat_links:
        # 接続先が出力ノードのサーフェス入力か確認する
        if check_link.to_socket == surface_input:
            # リンクの接続元ノードを取得する
            surface_node = check_link.from_node
    
    # 接続元ノードが取得できたか確認する
    if surface_node == None:
        # 接続元ノードが存在しない場合は処理しない
        return None
    
    # 接続元となっているサーフェスノードを返却する
    return_node = surface_node

    return return_node


# 対象マテリアルのノードを有効化する
def use_material_node(arg_material:bpy.types.Material):
    """対象マテリアルのノードを有効化する

    Args:
        arg_material (bpy.types.Material): 対象マテリアル
    """

    # マテリアル操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Material.html)

    # ノードが無効な場合、有効化する
    if arg_material.use_nodes == False:
        arg_material.use_nodes = True

    return


# 指定ノードがプリンシプルBSDFかチェックする
def check_isnode_bsdf(arg_node:bpy.types.Node) -> bool:
    """指定ノードがプリンシプルBSDFかチェックする

    Args:
        arg_node (bpy.types.Node): 指定ノード

    Returns:
        bool: プリンシプルBSDFか否か
    """

    # チェック結果
    isBSDF = False

    # ノードタイプを取得する
    node_idname = arg_node.bl_idname

    # ノードタイプがプリンシプルBSDFノードか確認する
    if node_idname == 'ShaderNodeBsdfPrincipled':
        # プリンシプルBSDFならTrueを返す
        isBSDF = True

    return isBSDF


# 関数の実行例
check_surface_bsdf_checker(
    arg_objectname="Cube",
    arg_materialname="Material"
)

・プリンシプルBSDFノード接続の出力ノード有効時
f:id:bluebirdofoz:20200714211200j:plain

・値ノード接続の出力ノード有効時
f:id:bluebirdofoz:20200714211210j:plain

Blender2.8で利用可能なpythonスクリプトを作る その48(マテリアルカラーのテクスチャベイク)

本日は Blender の技術調査枠です。
Blender2.8で利用可能なpythonスクリプトを作ります。

マテリアルカラーのテクスチャベイク

指定オブジェクトの全てのマテリアルカラーを1つの画像テクスチャにベイクします。
作成した画像には自動で削除されないようにフェイクユーザを設定します。
・Script_bake_materialcolor_texture.py

# bpyインポート
import bpy

# 指定オブジェクトの全てのマテリアルカラーを画像テクスチャにベイクする
# (オブジェクト名指定)
def bake_materialcolor_texture_checker(arg_objectname="Default",
  arg_texturename:str="BakeTexture",
  arg_texturesize:int=2048,
  arg_bakemargin:int=0) -> bool:
    """指定オブジェクトの全てのマテリアルカラーを画像テクスチャにベイクする(オブジェクト名指定)

    Args:
        arg_objectname (str, optional): 指定オブジェクト名. Defaults to "Default".
        arg_texturename (str, optional): 作成テクスチャ名. Defaults to "BakeTexture".
        arg_texturesize (int, optional): 作成テクスチャサイズ(px). Defaults to 2048.
        arg_bakemargin (int, optional): ベイク余白(px). Defaults to 0.

    Returns:
        bool: 実行正否
    """


    # 指定オブジェクトを取得する
    # (get関数は対象が存在しない場合 None が返る)
    selectob = bpy.data.objects.get(arg_objectname)

    # 指定オブジェクトが存在するか確認する
    if selectob == None:
        # 指定オブジェクトが存在しない場合は処理しない
        return False
    
    # 指定オブジェクトがメッシュオブジェクトか確認する
    if selectob.type != 'MESH':
        # メッシュオブジェクトでない場合は処理しない
        return False

    bake_materialcolor_texture(
        arg_object=selectob,
        arg_texturename=arg_texturename,
        arg_texturesize=arg_texturesize,
        arg_bakemargin=arg_bakemargin
    )

    return True


# 指定オブジェクトの全てのマテリアルカラーを画像テクスチャにベイクする
def bake_materialcolor_texture(arg_object:bpy.types.Object,
  arg_texturename:str="BakeTexture",
  arg_texturesize:int=2048,
  arg_bakemargin:int=0) -> bool:
    """指定オブジェクトの全てのマテリアルカラーを画像テクスチャにベイクする

    Args:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_texturename (str, optional): 作成テクスチャ名. Defaults to "BakeTexture".
        arg_texturesize (int, optional): 作成テクスチャサイズ(px). Defaults to 2048.
        arg_bakemargin (int, optional): ベイク余白(px). Defaults to 0.

    Returns:
        bool: 実行正否
    """

    # 参照の保存用変数
    name_mapping = {}

    # 追加する画像ノード名を定義する
    texturenode_name = "ForBakeTextureNode"

    # 新規テクスチャを作成して参照を取得する
    bake_image = make_new_image(
        arg_texturename=arg_texturename,
        arg_texturesize=arg_texturesize
    )

    # 指定オブジェクトのマテリアルリストを取得する
    for material_slot in arg_object.material_slots:
        # スロットのマテリアルを取得する
        target_material = material_slot.material

        # マテリアルが割り当てられているか
        if target_material == None:
            continue

        # 参照マテリアルをノード使用に変更する
        use_material_node(target_material)

        # 新規テクスチャを参照する画像ノードを追加する
        add_node = add_node_image(
            arg_material=target_material,
            arg_image=bake_image
        )

        # 作成ノードの参照を保存する
        name_mapping[texturenode_name + target_material.name] = add_node

        # 指定の画像ノードを選択状態に設定する
        select_node_target(
            arg_material=target_material,
            arg_node=name_mapping[texturenode_name + target_material.name]
        )

    # 指定オブジェクトの「カラー」をベイクする
    bake_diffuse_coloronly(
        arg_object=arg_object,
        arg_bakemargin=arg_bakemargin,
        arg_GPUuse=True
    )

    # 作成したテクスチャにフェイクユーザを設定する
    bake_image.use_fake_user = True

    # 指定オブジェクトのマテリアルリストを取得する
    for material_slot in arg_object.material_slots:
        # スロットのマテリアルを取得する
        target_material = material_slot.material

        # マテリアルが割り当てられているか
        if target_material == None:
            continue

        # 追加した画像ノードを削除する
        delete_node_target(
            arg_material=target_material,
            arg_node=name_mapping[texturenode_name + target_material.name]
        )
    
    return True


# 新規画像を作成する
def make_new_image(arg_texturename:str="BakeTexture",
  arg_texturesize:int=2048) -> bpy.types.Image:
    """新規画像を作成する

    Args:
        arg_texturename (str, optional): 作成テクスチャ名. Defaults to "BakeTexture".
        arg_texturesize (int, optional): 作成テクスチャサイズ. Defaults to 2048.

    Returns:
        bpy.types.Image: 作成画像の参照
    """

    # 新規画像を作成する
    newimage = bpy.data.images.new(
        name=arg_texturename,
        width=arg_texturesize,
        height=arg_texturesize,
        alpha=True
    )

    return newimage


# 対象マテリアルのノードを有効化する
def use_material_node(arg_material:bpy.types.Material):
    """対象マテリアルのノードを有効化する

    Args:
        arg_material (bpy.types.Material): 対象マテリアル
    """

    # マテリアル操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Material.html)

    # ノードが無効な場合、有効化する
    if arg_material.use_nodes == False:
        arg_material.use_nodes = True

    return


# 対象マテリアルに指定テクスチャを参照する画像ノードを追加する
def add_node_image(arg_material:bpy.types.Material,
  arg_image:bpy.types.Image) -> bpy.types.Node:
    """対象マテリアルに指定テクスチャを参照する画像ノードを追加する

    Args:
        arg_material (bpy.types.Material): 対象マテリアル
        arg_image (bpy.types.Image): 指定テクスチャ

    Returns:
        bpy.types.Node: 作成ノードの参照
    """

    # ノード操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Node.html)

    # ターゲットマテリアルのノード参照を取得
    mat_nodes = arg_material.node_tree.nodes

    # テクスチャノードの追加
    texture_node = mat_nodes.new(type="ShaderNodeTexImage")

    # テクスチャノードに指定画像を設定する
    texture_node.image = arg_image

    return texture_node


# 対象マテリアルの指定ノードのみを選択状態する
def select_node_target(arg_material:bpy.types.Material, arg_node:bpy.types.Node):
    """対象マテリアルの指定ノードのみを選択状態する

    Args:
        arg_material (bpy.types.Material): 対象マテリアル
        arg_node (bpy.types.Node): 指定ノード
    """

    # ノード操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Node.html)
    # ノードリスト操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Nodes.html)

    # ターゲットマテリアルのノード参照を取得
    mat_nodes = arg_material.node_tree.nodes

    # 全てのノードの選択状態を解除する
    for mat_node in mat_nodes:
        # 選択状態を解除する
        mat_node.select = False

    # 指定ノードを選択状態にする
    arg_node.select = True

    # 指定ノードをアクティブにする
    mat_nodes.active = arg_node

    return


# 指定オブジェクトのカラー情報のみをベイクする
def bake_diffuse_coloronly(arg_object:bpy.types.Object,
  arg_bakemargin:int=0, arg_GPUuse:bool=False):
    """指定オブジェクトのカラー情報のみをベイクする

    Args:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_bakemargin (int, optional): ベイク余白. Defaults to 0.
        arg_GPUuse (bool, optional): GPU利用指定. Defaults to False.
    """

    # 全てのオブジェクトを非選択状態にする
    for obj in bpy.context.scene.objects:
        # 選択状態を解除する
        obj.select_set(False)

    # 指定オブジェクトを選択状態にする
    arg_object.select_set(True)

    # 指定オブジェクトをアクティブにする
    bpy.context.view_layer.objects.active = arg_object

    # レンダリングエンジンを CYCLES に切り替える
    bpy.context.scene.render.engine = 'CYCLES'

    # GPUの利用有無を確認する
    if arg_GPUuse == True:
        # 利用設定ならGPUの設定を行う
        bpy.data.scenes["Scene"].cycles.device = 'GPU'
        # CUDAを選択する
        bpy.context.preferences.addons['cycles'].preferences.compute_device_type = 'CUDA'
        # デバイスの一覧を取得する
        for devices in bpy.context.preferences.addons['cycles'].preferences.get_devices():
            for device in devices:
                # デバイスタイプがCUDAならば利用対象とする
                if device.type == 'CUDA':
                    print("利用可能なGPUを検出しました:" + device.name)
                    device.use = True

    # render.bake の設定項目を予め設定する
    bake_setting = bpy.context.scene.render.bake

    # ベイクの影響から直接照明を無効化する
    bake_setting.use_pass_direct = False

    # ベイクの影響から間接照明を無効化する
    bake_setting.use_pass_indirect = False

    # ベイクの影響からカラーを有効化する
    bake_setting.use_pass_color = True

    # ディフューズタイプのベイクを実行する
    # ベイクの種類
    # ('COMBINED', 'AO', 'SHADOW', 'NORMAL', 'UV', 'ROUGHNESS',
    # 'EMIT', 'ENVIRONMENT', 'DIFFUSE', 'GLOSSY', 'TRANSMISSION')
    # (render.bake 以外の設定は引数で指定する必要あり)
    bpy.ops.object.bake(type='DIFFUSE', margin=arg_bakemargin)

    return


# 対象マテリアルの指定ノードを削除する
def delete_node_target(arg_material:bpy.types.Material, arg_node:bpy.types.Node):
    """対象マテリアルの指定ノードを削除する

    Args:
        arg_material (bpy.types.Material): 対象マテリアル
        arg_node (bpy.types.Node): 指定ノード
    """

    # ノード操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Node.html)

    # ターゲットマテリアルのノード参照を取得
    mat_nodes = arg_material.node_tree.nodes

    # ノードを削除する
    mat_nodes.remove(arg_node)

    return



# 関数の実行例
bake_materialcolor_texture_checker(
    arg_objectname="Cube",
    arg_texturename="BakeTexture",
    arg_texturesize=1024,
    arg_bakemargin=2
)

f:id:bluebirdofoz:20200713033858j:plain

アドオンバージョン

上記スクリプトをアドオン化したものです。
追加されるパネルから以下の項目を設定して[MATERIAL COLOR BAKE]ボタンをクリックで実行します。

Select Object:ベイクの実行対象オブジェクト
Texture Name :作成テクスチャ名
Texture Size :作成テクスチャサイズ(指定辺長の正方形)
Bake Margin  :ベイク実行時の余白(px)

・Addon_bake_materialcolor_texture.py

# bl_infoでプラグインに関する情報の定義を行う
bl_info = {
    "name": "HoloMon Material Color Bake Addon",     # プラグイン名
    "author": "HoloMon",                             # 制作者名
    "version": (1, 0),                               # バージョン
    "blender": (2, 80, 0),                           # 動作可能なBlenderバージョン
    "support": "TESTING",                            # サポートレベル
    "category": "3D View",                           # カテゴリ名
    "location": "View3D > Sidebar > HoloMon",        # ロケーション
    "description": "Addon Material Color Bake",      # 説明文
    "location": "",                                  # 機能の位置付け
    "warning": "",                                   # 注意点やバグ情報
    "doc_url": "",                                   # ドキュメントURL
}

# 利用するタイプやメソッドのインポート
import bpy
from bpy.types import Operator, Panel, PropertyGroup
from bpy.props import PointerProperty, IntProperty, StringProperty

# 継承するクラスの命名規則は以下の通り
# [A-Z][A-Z0-9_]*_(継承クラスごとの識別子)_[A-Za-z0-9_]+
# クラスごとの識別子は以下の通り
#   bpy.types.Operator  OT
#   bpy.types.Panel     PT
#   bpy.types.Header    HT
#   bpy.types.MENU      MT
#   bpy.types.UIList    UL

# Panelクラスの作成
# 参考URL:https://docs.blender.org/api/current/bpy.types.Panel.html
class HOLOMON_PT_addon_material_color_bake(Panel):
    # パネルのラベル名を定義する
    # パネルを折りたたむパネルヘッダーに表示される
    bl_label = "Material Color Bake"
    # クラスのIDを定義する
    # 命名規則は CATEGORY_PT_name
    bl_idname = "HOLOMON_PT_addon_material_color_bake"
    # パネルを使用する領域を定義する
    # 利用可能な識別子は以下の通り
    #   EMPTY:無し
    #   VIEW_3D:3Dビューポート
    #   IMAGE_EDITOR:UV/画像エディター
    #   NODE_EDITOR:ノードエディター
    #   SEQUENCE_EDITOR:ビデオシーケンサー
    #   CLIP_EDITOR:ムービークリップエディター
    #   DOPESHEET_EDITOR:ドープシート
    #   GRAPH_EDITOR:グラフエディター
    #   NLA_EDITOR:非線形アニメーション
    #   TEXT_EDITOR:テキストエディター
    #   CONSOLE:Pythonコンソール
    #   INFO:情報、操作のログ、警告、エラーメッセージ
    #   TOPBAR:トップバー
    #   STATUSBAR:ステータスバー
    #   OUTLINER:アウトライナ
    #   PROPERTIES:プロパティ
    #   FILE_BROWSER:ファイルブラウザ
    #   PREFERENCES:設定
    bl_space_type = 'VIEW_3D'
    # パネルが使用される領域を定義する
    # 利用可能な識別子は以下の通り
    # ['WINDOW'、 'HEADER'、 'CHANNELS'、 'TEMPORARY'、 'UI'、
    #  'TOOLS'、 'TOOL_PROPS'、 'PREVIEW'、 'HUD'、 'NAVIGATION_BAR'、
    #  'EXECUTE'、 'FOOTER'の列挙型、 'TOOL_HEADER']
    bl_region_type = 'UI'
    # パネルタイプのオプションを定義する
    # DEFAULT_CLOSED:作成時にパネルを開くか折りたたむ必要があるかを定義する。
    # HIDE_HEADER:ヘッダーを非表示するかを定義する。Falseに設定するとパネルにはヘッダーが表示される。
    # デフォルトは {'DEFAULT_CLOSED'}
    bl_options = {'DEFAULT_CLOSED'}
    # パネルの表示順番を定義する
    # 小さい番号のパネルは、大きい番号のパネルの前にデフォルトで順序付けられる
    # デフォルトは 0
    bl_order = 0
    # パネルのカテゴリ名称を定義する
    # 3Dビューポートの場合、サイドバーの名称になる
    # デフォルトは名称無し
    bl_category = "HoloMon"
 
    # 描画の定義
    def draw(self, context):
        # Operatorをボタンとして配置する
        draw_layout = self.layout
        # 要素行を作成する
        select_row = draw_layout.row()
        # オブジェクト選択用のカスタムプロパティを配置する
        select_row.prop(context.scene.holomon_material_color_bake, "prop_objectslect", text='')
        # 要素行を作成する
        length_row = draw_layout.row()
        # テクスチャ名指定用のカスタムプロパティを配置する
        length_row.prop(context.scene.holomon_material_color_bake, "prop_texturename")
        # 要素行を作成する
        length_row = draw_layout.row()
        # テクスチャサイズ指定用のカスタムプロパティを配置する
        length_row.prop(context.scene.holomon_material_color_bake, "prop_texturesize")
        # 要素行を作成する
        length_row = draw_layout.row()
        # ベイク余白指定用のカスタムプロパティを配置する
        length_row.prop(context.scene.holomon_material_color_bake, "prop_bakemargin")
        # 要素行を作成する
        button_row = draw_layout.row()
        # オブジェクト指定のサイズ縮小を実行するボタンを配置する
        button_row.operator("holomon.material_color_bake")

# Operatorクラスの作成
# 参考URL:https://docs.blender.org/api/current/bpy.types.Operator.html
class HOLOMON_OT_addon_material_color_bake(Operator):
    # クラスのIDを定義する
    # (Blender内部で参照する際のIDに利用)
    bl_idname = "holomon.material_color_bake"
    # クラスのラベルを定義する
    # (デフォルトのテキスト表示などに利用)
    bl_label = "MATERIAL COLOR BAKE"
    # クラスの説明文
    # (マウスオーバー時に表示)
    dl_description = "Material Color Bake Addon Description"
    # クラスの属性
    # 以下の属性を設定できる
    #   REGISTER      : Operatorを情報ウィンドウに表示し、やり直しツールバーパネルをサポートする
    #   UNDO          : 元に戻すイベントをプッシュする(Operatorのやり直しに必要)
    #   UNDO_GROUPED  : Operatorの繰り返しインスタンスに対して単一の取り消しイベントをプッシュする
    #   BLOCKING      : 他の操作がマウスポインタ―を使用できないようにブロックする
    #   MACRO         : Operatorがマクロであるかどうかを確認するために使用する
    #   GRAB_CURSOR   : 継続的な操作が有効な場合にオペレーターがマウスポインターの動きを参照して、操作を有効にする
    #   GRAB_CURSOR_X : マウスポインターのX軸の動きのみを参照する
    #   GRAB_CURSOR_Y : マウスポインターのY軸の動きのみを参照する
    #   PRESET        : Operator設定を含むプリセットボタンを表示する
    #   INTERNAL      : 検索結果からOperatorを削除する
    # 参考URL:https://docs.blender.org/api/current/bpy.types.Operator.html#bpy.types.Operator.bl_options
    bl_options = {'REGISTER', 'UNDO'}


    # Operator実行時の処理
    def execute(self, context):
        # カスタムプロパティから指定中のオブジェクトを取得する
        target_object = context.scene.holomon_material_color_bake.prop_objectslect

        # 指定中のオブジェクトを確認する
        if target_object == None:
            # オブジェクトが指定されていない場合はエラーメッセージを表示する
            self.report({'ERROR'}, "Nothing : target object.")
            return {'CANCELLED'}

        # カスタムプロパティから指定中のテクスチャ名を取得する
        texture_name = context.scene.holomon_material_color_bake.prop_texturename

        # 指定中のテクスチャ名を確認する
        if texture_name == None:
            # テクスチャ名が指定されていない場合はエラーメッセージを表示する
            self.report({'ERROR'}, "Nothing : texture name.")
            return {'CANCELLED'}

        # カスタムプロパティから指定中のテクスチャサイズを取得する
        texture_size = context.scene.holomon_material_color_bake.prop_texturesize

        # 指定中のテクスチャサイズを確認する
        if texture_size < 1:
            # 適切なテクスチャサイズが指定されていない場合はエラーメッセージを表示する
            self.report({'ERROR'}, "Nothing : texture size.")
            return {'CANCELLED'}

        # カスタムプロパティから指定中のベイク余白を取得する
        bake_margin = context.scene.holomon_material_color_bake.prop_bakemargin

        # 指定中のテクスチャサイズを確認する
        if bake_margin < 0:
            # 適切なテクスチャサイズが指定されていない場合はエラーメッセージを表示する
            self.report({'ERROR'}, "Nothing : bake margin.")
            return {'CANCELLED'}

        # 指定オブジェクトの全てのマテリアルカラーを画像テクスチャにベイクする
        bake_materialcolor_texture(
            arg_object=target_object,
            arg_texturename=texture_name,
            arg_texturesize=texture_size,
            arg_bakemargin=bake_margin
        )

        return {'FINISHED'}

# PropertyGroupクラスの作成
# 参考URL:https://docs.blender.org/api/current/bpy.types.PropertyGroup.html
class HOLOMON_addon_material_color_bake_properties(PropertyGroup):
    # オブジェクト選択時のチェック関数を定義する
    def prop_object_select_poll(self, context, ):
        # メッシュオブジェクトのみ選択可能
        if(context and context.type in ('MESH', )):
            return True
        return False

    # シーン上のパネルに表示するオブジェクト選択用のカスタムプロパティを定義する
    prop_objectslect: PointerProperty(
        name = "Select Object",         # プロパティ名
        type = bpy.types.Object,        # タイプ
        description = "",               # 説明文
        poll = prop_object_select_poll, # チェック関数
    )


    # シーン上のパネルに表示するテクスチャ名指定用のカスタムプロパティを定義する
    prop_texturename: StringProperty(
        name="Texture Name",     # プロパティ名
        default="BakeTexture",   # デフォルト値
        maxlen=1024,             # 最大文字列長
        description="",          # 説明文
    )

    # シーン上のパネルに表示するテクスチャサイズ指定用のカスタムプロパティを定義する
    prop_texturesize: IntProperty(
        name = "Texture Size",   # プロパティ名
        default=2048,            # デフォルト値
        description = "",        # 説明文
    )

    # シーン上のパネルに表示するベイク余白用のカスタムプロパティを定義する
    prop_bakemargin: IntProperty(
        name = "Bake Margin",    # プロパティ名
        default=16,              # デフォルト値
        description = "",        # 説明文
    )


# 登録に関する処理
# 登録対象のクラス名
regist_classes = (
    HOLOMON_PT_addon_material_color_bake,
    HOLOMON_OT_addon_material_color_bake,
    HOLOMON_addon_material_color_bake_properties,
)

# 作成クラスと定義の登録メソッド
def register():
    # カスタムクラスを登録する
    for regist_cls in regist_classes:
        bpy.utils.register_class(regist_cls)
    # シーン情報にカスタムプロパティを登録する
    bpy.types.Scene.holomon_material_color_bake = PointerProperty(type=HOLOMON_addon_material_color_bake_properties)

# 作成クラスと定義の登録解除メソッド
def unregister():
    # シーン情報のカスタムプロパティを削除する
    del bpy.types.Scene.holomon_material_color_bake
    # カスタムクラスを解除する
    for regist_cls in regist_classes:
        bpy.utils.unregister_class(regist_cls)



# 指定オブジェクトの全てのマテリアルカラーを画像テクスチャにベイクする
def bake_materialcolor_texture(arg_object:bpy.types.Object,
  arg_texturename:str="BakeTexture",
  arg_texturesize:int=2048,
  arg_bakemargin:int=0) -> bool:
    """指定オブジェクトの全てのマテリアルカラーを画像テクスチャにベイクする

    Args:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_texturename (str, optional): 作成テクスチャ名. Defaults to "BakeTexture".
        arg_texturesize (int, optional): 作成テクスチャサイズ(px). Defaults to 2048.
        arg_bakemargin (int, optional): ベイク余白(px). Defaults to 0.

    Returns:
        bool: 実行正否
    """

    # 参照の保存用変数
    name_mapping = {}

    # 追加する画像ノード名を定義する
    texturenode_name = "ForBakeTextureNode"

    # 新規テクスチャを作成して参照を取得する
    bake_image = make_new_image(
        arg_texturename=arg_texturename,
        arg_texturesize=arg_texturesize
    )

    # 指定オブジェクトのマテリアルリストを取得する
    for material_slot in arg_object.material_slots:
        # スロットのマテリアルを取得する
        target_material = material_slot.material

        # マテリアルが割り当てられているか
        if target_material == None:
            continue

        # 参照マテリアルをノード使用に変更する
        use_material_node(target_material)

        # 新規テクスチャを参照する画像ノードを追加する
        add_node = add_node_image(
            arg_material=target_material,
            arg_image=bake_image
        )

        # 作成ノードの参照を保存する
        name_mapping[texturenode_name + target_material.name] = add_node

        # 指定の画像ノードを選択状態に設定する
        select_node_target(
            arg_material=target_material,
            arg_node=name_mapping[texturenode_name + target_material.name]
        )

    # 指定オブジェクトの「カラー」をベイクする
    bake_diffuse_coloronly(
        arg_object=arg_object,
        arg_bakemargin=arg_bakemargin,
        arg_GPUuse=True
    )

    # 作成したテクスチャにフェイクユーザを設定する
    bake_image.use_fake_user = True

    # 指定オブジェクトのマテリアルリストを取得する
    for material_slot in arg_object.material_slots:
        # スロットのマテリアルを取得する
        target_material = material_slot.material

        # マテリアルが割り当てられているか
        if target_material == None:
            continue

        # 追加した画像ノードを削除する
        delete_node_target(
            arg_material=target_material,
            arg_node=name_mapping[texturenode_name + target_material.name]
        )
    
    return True


# 新規画像を作成する
def make_new_image(arg_texturename:str="BakeTexture",
  arg_texturesize:int=2048) -> bpy.types.Image:
    """新規画像を作成する

    Args:
        arg_texturename (str, optional): 作成テクスチャ名. Defaults to "BakeTexture".
        arg_texturesize (int, optional): 作成テクスチャサイズ. Defaults to 2048.

    Returns:
        bpy.types.Image: 作成画像の参照
    """

    # 新規画像を作成する
    newimage = bpy.data.images.new(
        name=arg_texturename,
        width=arg_texturesize,
        height=arg_texturesize,
        alpha=True
    )

    return newimage


# 対象マテリアルのノードを有効化する
def use_material_node(arg_material:bpy.types.Material):
    """対象マテリアルのノードを有効化する

    Args:
        arg_material (bpy.types.Material): 対象マテリアル
    """

    # マテリアル操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Material.html)

    # ノードが無効な場合、有効化する
    if arg_material.use_nodes == False:
        arg_material.use_nodes = True

    return


# 対象マテリアルに指定テクスチャを参照する画像ノードを追加する
def add_node_image(arg_material:bpy.types.Material,
  arg_image:bpy.types.Image) -> bpy.types.Node:
    """対象マテリアルに指定テクスチャを参照する画像ノードを追加する

    Args:
        arg_material (bpy.types.Material): 対象マテリアル
        arg_image (bpy.types.Image): 指定テクスチャ

    Returns:
        bpy.types.Node: 作成ノードの参照
    """

    # ノード操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Node.html)

    # ターゲットマテリアルのノード参照を取得
    mat_nodes = arg_material.node_tree.nodes

    # テクスチャノードの追加
    texture_node = mat_nodes.new(type="ShaderNodeTexImage")

    # テクスチャノードに指定画像を設定する
    texture_node.image = arg_image

    return texture_node


# 対象マテリアルの指定ノードのみを選択状態する
def select_node_target(arg_material:bpy.types.Material, arg_node:bpy.types.Node):
    """対象マテリアルの指定ノードのみを選択状態する

    Args:
        arg_material (bpy.types.Material): 対象マテリアル
        arg_node (bpy.types.Node): 指定ノード
    """

    # ノード操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Node.html)
    # ノードリスト操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Nodes.html)

    # ターゲットマテリアルのノード参照を取得
    mat_nodes = arg_material.node_tree.nodes

    # 全てのノードの選択状態を解除する
    for mat_node in mat_nodes:
        # 選択状態を解除する
        mat_node.select = False

    # 指定ノードを選択状態にする
    arg_node.select = True

    # 指定ノードをアクティブにする
    mat_nodes.active = arg_node

    return


# 指定オブジェクトのカラー情報のみをベイクする
def bake_diffuse_coloronly(arg_object:bpy.types.Object,
  arg_bakemargin:int=0, arg_GPUuse:bool=False):
    """指定オブジェクトのカラー情報のみをベイクする

    Args:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_bakemargin (int, optional): ベイク余白. Defaults to 0.
        arg_GPUuse (bool, optional): GPU利用指定. Defaults to False.
    """

    # 全てのオブジェクトを非選択状態にする
    for obj in bpy.context.scene.objects:
        # 選択状態を解除する
        obj.select_set(False)

    # 指定オブジェクトを選択状態にする
    arg_object.select_set(True)

    # 指定オブジェクトをアクティブにする
    bpy.context.view_layer.objects.active = arg_object

    # レンダリングエンジンを CYCLES に切り替える
    bpy.context.scene.render.engine = 'CYCLES'

    # GPUの利用有無を確認する
    if arg_GPUuse == True:
        # 利用設定ならGPUの設定を行う
        bpy.data.scenes["Scene"].cycles.device = 'GPU'
        # CUDAを選択する
        bpy.context.preferences.addons['cycles'].preferences.compute_device_type = 'CUDA'
        # デバイスの一覧を取得する
        for devices in bpy.context.preferences.addons['cycles'].preferences.get_devices():
            for device in devices:
                # デバイスタイプがCUDAならば利用対象とする
                if device.type == 'CUDA':
                    print("利用可能なGPUを検出しました:" + device.name)
                    device.use = True

    # render.bake の設定項目を予め設定する
    bake_setting = bpy.context.scene.render.bake

    # ベイクの影響から直接照明を無効化する
    bake_setting.use_pass_direct = False

    # ベイクの影響から間接照明を無効化する
    bake_setting.use_pass_indirect = False

    # ベイクの影響からカラーを有効化する
    bake_setting.use_pass_color = True

    # ディフューズタイプのベイクを実行する
    # ベイクの種類
    # ('COMBINED', 'AO', 'SHADOW', 'NORMAL', 'UV', 'ROUGHNESS',
    # 'EMIT', 'ENVIRONMENT', 'DIFFUSE', 'GLOSSY', 'TRANSMISSION')
    # (render.bake 以外の設定は引数で指定する必要あり)
    bpy.ops.object.bake(type='DIFFUSE', margin=arg_bakemargin)

    return


# 対象マテリアルの指定ノードを削除する
def delete_node_target(arg_material:bpy.types.Material, arg_node:bpy.types.Node):
    """対象マテリアルの指定ノードを削除する

    Args:
        arg_material (bpy.types.Material): 対象マテリアル
        arg_node (bpy.types.Node): 指定ノード
    """

    # ノード操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Node.html)

    # ターゲットマテリアルのノード参照を取得
    mat_nodes = arg_material.node_tree.nodes

    # ノードを削除する
    mat_nodes.remove(arg_node)

    return



# 実行時の処理
if __name__ == "__main__":
    # 作成クラスと定義を登録する
    register()

f:id:bluebirdofoz:20200713033913j:plain

VisualStudioCodeでPython開発支援のPylanceを利用する

本日は VSCode の環境構築枠です。
VisualStudioCode で Python 開発支援の Pylance を利用する手順を記事にします。
f:id:bluebirdofoz:20200712030025j:plain

Pylanceとは

Python のコーディング作業を支援するための VisualStudioCode の拡張機能です。
marketplace.visualstudio.com

入力補完や必要なモジュールの自動インポートなど、Python 開発で便利な様々な機能を提供します。
2020/07/11現在、Pylance は Preview 版となっています。

Pylanceのインストール

Visual Studio Code を起動し、[Extensions]ボタンをクリックして[Pylance]で検索を行います。
トップに表示される[Pylance]を開きます
f:id:bluebirdofoz:20200712030045j:plain

Pylance のページが開いたら[Install]をクリックしてインストールを行います。
f:id:bluebirdofoz:20200712030055j:plain

これでインストールは完了です。

Pylanceの利用手順

拡張子が py の Python スクリプトを開くと、自動的に Pylance が利用できます。
f:id:bluebirdofoz:20200712030107j:plain

設定項目

Pylance では設定を変更することで機能をカスタマイズすることができます。

一例として、デフォルトで無効化されている Pylance の型チェック機能を有効化してみます。
以下の手順で型チェックを有効化できます。

1.[Manage]アイコンをクリックして[Settings]を選択します。
f:id:bluebirdofoz:20200712030116j:plain

2.[Settings]が開いたら[Extensions] -> [Pylance Configure...] を開きます。
f:id:bluebirdofoz:20200712030125j:plain

3.[Type Checking Mode]の設定を[off]から[basic]または[strict]に変更すると、型チェックが有効化されます。
f:id:bluebirdofoz:20200712030135j:plain

[basic]は型のアノテーションが設定している箇所のチェックのみを行います。
[strict]はより厳しい型チェックを行い、型のアノテーションを設定していない箇所もエラーを返します。
詳細は後述のマニュアルを参照ください。

Pylanceの概要(日本語翻訳)

以下のページを翻訳したものを以下に記述します。
marketplace.visualstudio.com

高速で豊富なPython言語サポート

Pylance は Visual Studio CodePython と連携して機能する言語サポートを提供する拡張機能です。
Pylance は内部では Pyright を使用しています。Pyright はMicrosoftの静的型チェックツールです。
Pyright を使うことで、Pylance は Python を豊富な型情報で強化し、優れたコードをより速く作成できるようになります。

Pylance の由来はモンティパイソンのランスロットへの小さな賛辞です。

クイックスタート

1.マーケットプレイスからPylance拡張機能をインストールします。
2.Python(.py)ファイルを開くと、Pylance拡張機能がアクティブになります。

特徴

Pylance は Python 3 に素晴らしい機能を提供します。

・関数やクラスに対する説明文(Docstrings)
・タイプ情報付きのシグネチャのヘルプ
・パラメータの提案
・コード補完
・自動インポート(およびインポートコードアクションの追加と削除)
・コードのエラーと警告(診断)の入力時のレポート
・コードの概要
・コードナビゲーション
・コードレンズ(リファレンス/実装)
・型チェックモード
・ネイティブマルチルートワークスペースのサポート
・IntelliCode の互換性
・Jupyter Notebooks の互換性

最新リリースの変更ログを参照してください。
Changelog
https://github.com/microsoft/pylance-release/blob/master/CHANGELOG.md

設定とカスタマイズ

PylanceはPython言語サポートをカスタマイズする機能をユーザーに提供します。
これらの設定はワークスペースの settings.json ファイルに配置したり、設定エディターのUIで編集できます。

python.analysis.typeCheckingMode

実行される型チェックの分析レベルを指定します。
・デフォルト: off
・利用可能な値:

off:型チェックは行われません。未解決のインポート/変数診断が作成されます。
basic:型チェックに関連しないルール(off時のチェックルール)と基本的な型チェックを行います。
strict:エラーに関する最も厳重な型チェックを実施します。off時のチェックルールとbasic時のチェックルールも行います。
python.analysis.diagnosticMode

コードを分析して問題を報告する言語サーバーに、どのファイルを指定できるか設定するために使用されます。
・デフォルト:openFilesOnly
利用可能な値:

workspace
openFilesOnly
python.analysis.stubPaths

ユーザーがカスタムタイプのスタブを含むディレクトリへのパスを指定できるか設定するために使用されます。
各パッケージの型スタブファイルは、独自のサブディレクトリにあることが望ましいです。
・デフォルト値: ./typings

python.analysis.autoSearchPaths

事前定義された名前(srcなど)に基づいて検索パスを自動的に追加するために使用されます。
・デフォルト:true
・利用可能な値:

true
false
python.analysis.extraPaths

インポート解決のための追加の検索パスを指定するために使用されます。
これにより、古い python.autoComplete.extraPaths 設定は置き換えられます。
・デフォルト値:空の配列

python.analysis.diagnosticSeverityOverrides

ユーザーが必要に応じて、個々の診断の重大度レベルを上書きするために使用されます
許容される重大度の値:

error(赤い波線)
warning(黄色の波線)
information(青い波線)
none(ルールを無効にします)

キーとして使用できるルールは以下を参照してください。
github.com

例:

{
    "python.analysis.diagnosticSeverityOverrides:" { 
        "reportUnboundVariable" : "information", 
        "reportImplicitStringConcatenation" : "warning" 
    }
} 
python.analysis.useLibraryCodeForTypes

タイプスタブが見つからない場合、パッケージのソースコードを解析するために使用されます。
・デフォルト:true
・利用可能な値:

true
false

貢献する

Pylanceは Microsoft の静的型チェックツールであるPyrightを利用して Python に高性能の言語サポートを提供します。

コードの貢献は Pyright リポジトリ経由で歓迎されます。
始め方は Contributing の手順を参照してください。
github.com

フィードバック

github.com

Blender2.8の各種ベイクタイプの出力情報と動作を確認する その2

本日は Blender2.8 の小ネタ枠です。
Blender2.8 の各種ベイクタイプの出力情報と動作を確認した結果を記事にします。

前回記事の続きです。
bluebirdofoz.hatenablog.com

粗さ

粗さ(Smoothness)の情報をベイクします。
f:id:bluebirdofoz:20200711172901j:plain

以下の事例は、黒の箇所は[粗さ]を[0.0]と[メタリック]を[0.0]を設定しています。
その他の箇所は、白の箇所に近づくほど[粗さ]を[1.0]に近づけています。
f:id:bluebirdofoz:20200711172921j:plain

粗さの情報をそのまま出力するため、ベースカラーやメタリック、照明などの影響は受けません。
・ベースカラー変更例
f:id:bluebirdofoz:20200711172935j:plain

・メタリック変更例
f:id:bluebirdofoz:20200711172948j:plain

UV

UVマップ上の座標情報をベイクします。
f:id:bluebirdofoz:20200711173246j:plain

テクスチャを反映して色情報を確認すると、UVマップ上の面の位置が分かります。
f:id:bluebirdofoz:20200711173314j:plain

ノーマル

法線情報をベイクします。
単一のオブジェクトで実行すると、面の法線が完全に一致するため、平面のノーマルマップが出力されます。
f:id:bluebirdofoz:20200711173326j:plain

異なる形状を重ね合わせて[選択物→アクティブ]のベイクを実行すると、法線の差異がノーマルマップとして出力されます。
f:id:bluebirdofoz:20200711173339j:plain

オブジェクトの影情報をベイクします。
f:id:bluebirdofoz:20200711173355j:plain

影の落ち方はマテリアルの影響を受けます。
この例は[メタリック]を[0.0]、[粗さ]を[1.0]に設定したマテリアルを用いています。
f:id:bluebirdofoz:20200711173406j:plain

例えば、光を反射するような[メタリック]を[1.0]、[粗さ]を[0.0]に設定したマテリアルだと光が映らなくなります。
f:id:bluebirdofoz:20200711173419j:plain

更に光源のカラー情報にも影響を受けます。
白色の照明から青色の照明に変更すると、青色の面に大きく光が映るようになります。
f:id:bluebirdofoz:20200711173431j:plain

アンビエントオクルージョン

環境遮蔽の影をベイクします。
f:id:bluebirdofoz:20200711173447j:plain

動作を確認し易いように以下のような凹みのあるオブジェクトを作成しました。
f:id:bluebirdofoz:20200711173459j:plain

このオブジェクトに対して[アンビエントオクルージョン]のベイクを行うと、環境遮断が発生する箇所に影が焼き込まれます。
f:id:bluebirdofoz:20200711173513j:plain

環境遮断の調整は[ワールド]タブで行います。
[アンビエントオクルージョン(AO)]のチェックを入れて、[係数]と[距離]を調整します。
f:id:bluebirdofoz:20200711173523j:plain

これで再度ベイクを行うと、以下のように影の形状が変わりました。
因みに[Cycles]ではチェックを入れなくても[係数]が設定できないのみで、アンビエントオクルージョンの出力は実行されます。
f:id:bluebirdofoz:20200711173536j:plain

アンビエントオクルージョンは照明やマテリアルのカラーの影響を受けません。
オブジェクトの形状のみの影響を受けて算出されます。
f:id:bluebirdofoz:20200711173549j:plain

統合

複数のベイクタイプを組み合わせてベイクします。
f:id:bluebirdofoz:20200711173601j:plain

組み合わせるベイクタイプと照明の種類は[影響]から選択できます。
f:id:bluebirdofoz:20200711173613j:plain

Blender2.8の各種ベイクタイプの出力情報と動作を確認する その1

本日は Blender2.8 の小ネタ枠です。
Blender2.8 の各種ベイクタイプの出力情報と動作を確認した結果を記事にします。

Blender2.8 におけるテクスチャベイクの詳細な手順は以下を参照ください。
bluebirdofoz.hatenablog.com

ベイク実行時のベイクタイプ

Blender2.8 におけるベイク実行時のベイクタイプには以下の種類があり、様々な情報を選択的にベイクすることができます。

伝播
光沢
ディフューズ
環境
放射
粗さ
UV
ノーマル
影
アンビエントオクルージョン
統合

本記事ではそれぞれのベイクタイプでベイクを実行した場合に出力される情報を確認していきます。

伝播

面を伝播(透過)する色情報をベイクします。
f:id:bluebirdofoz:20200710233530j:plain

単純に伝播(透過)の強度のみを出力したい場合は[カラー]のみを選択してベイクします。
f:id:bluebirdofoz:20200710233541j:plain

以下の例では、面ごとにベースカラーを白に設定したマテリアルの[伝播]を[1.0]から[0.0]で設定しています。
光を完全に伝播する箇所は白色で出力され、光を完全に遮断する箇所は黒色で出力されます。
f:id:bluebirdofoz:20200710233553j:plain

単純にマテリアル内の[伝播]の値を出力する訳ではなく、ベースカラーによる色変化やメタリックによる遮断も考慮されます。
・ベースカラー設定時
f:id:bluebirdofoz:20200710233609j:plain

・メタリック設定時
f:id:bluebirdofoz:20200710233624j:plain

光沢

光沢の色彩をベイクします。
f:id:bluebirdofoz:20200710233716j:plain

以下の事例は、白の箇所は[メタリック]を[1.0]と[粗さ]を[0.0]を設定しています。
その他の箇所は、黒の箇所に近づくほど[メタリック]を[0.0]に近づけています。
f:id:bluebirdofoz:20200710233731j:plain

テクスチャには反射光がベイクされるので、照明や環境光のカラーや強度の影響を受けます。
f:id:bluebirdofoz:20200710233745j:plain

同様の理由からベイクの[影響]から[直接照明]と[間接照明]を外すと光沢はベイクされません。
f:id:bluebirdofoz:20200710233800j:plain

ディフューズ

カラー情報をベイクします。
f:id:bluebirdofoz:20200710233812j:plain

6色のマテリアルの面を持つオブジェクトをベイクすると、以下のようにカラー情報が出力されます。
f:id:bluebirdofoz:20200710233826j:plain

[直接照明]や[間接照明]を有効化していると、照明のカラーの影響を受けます。
f:id:bluebirdofoz:20200710233840j:plain

マテリアルのカラー情報をそのまま出力したい場合は[影響]で[カラー]のみを選択してベイクします。
f:id:bluebirdofoz:20200710233852j:plain

環境

オブジェクトが反射する環境光の情報をベイクします。
f:id:bluebirdofoz:20200710233904j:plain

光沢と異なり、環境の詳細な情報を焼き込みます。
以下のシーンは全てのマテリアルを[メタリック]を[1.0]と[粗さ]を[0.0]に設定しています。
f:id:bluebirdofoz:20200710233916j:plain

ただし本ベイクは面に影響する環境光をそのまま焼き込むものなので、マテリアルの反射は影響しません。
以下のような光を反射しない色のついたマテリアルを設定しても、同様の環境光が出力されます。
f:id:bluebirdofoz:20200710233947j:plain

放射

オブジェクトの放射(Emision)のカラー情報をベイクします。
f:id:bluebirdofoz:20200710234001j:plain

以下の例は6色のマテリアルにそれぞれ[R:1.0,G:1.0,B:1.0]から[R:0.0,G:0.0,B:0.0]までの放射色を設定しています。
マテリアルの放射色がそのまま出力されるため、出力はベースカラーの影響を受けていません。
f:id:bluebirdofoz:20200710234013j:plain

以下のように放射のカラー情報のみが出力されます。
f:id:bluebirdofoz:20200710234027j:plain

また照明の影響も受けません。
f:id:bluebirdofoz:20200710234039j:plain

長くなったので次回に続きます。
bluebirdofoz.hatenablog.com

Blender2.8で複数マテリアルのカラー情報を1つのテクスチャにベイクする

本日は Blender2.8 の小ネタ枠です。
Blender2.8で複数マテリアルのカラー情報を1つのテクスチャにベイクする方法を記事にします。
f:id:bluebirdofoz:20200709231117j:plain

サンプルモデル

サンプルとして、6つの面に異なるカラーマテリアルを割り当てた Cube オブジェクトを準備しました。
こちらのカラー情報を1つのテクスチャにベイクします。
f:id:bluebirdofoz:20200709231132j:plain

ベイク手順

UVマップを展開する

最初に対象オブジェクトのUVマップを作成します。
[編集モード]に切り替えて、UVマップの切れ目にしたい辺を選択した状態で[シームをマーク]を実行します。
今回はUVマップをなるべく大きく使えるように全ての辺を選択しました。
f:id:bluebirdofoz:20200709231145j:plain

シームを設定したら、[UV] -> [展開] を実行してUV展開を行います。
f:id:bluebirdofoz:20200709231155j:plain

これでUVマップが作成されました。
展開されたUVマップは[UVエディター]で確認できます。
f:id:bluebirdofoz:20200709231208j:plain

ベイク先のテクスチャを作成する

カラー情報のベイク先となるテクスチャを新規作成します。
[画像エディター]を開いて、[新規]ボタンをクリックします。
f:id:bluebirdofoz:20200709231219j:plain

作成するテクスチャの情報を入力して、[OK]ボタンをクリックします。
今回は名前を変更しただけで、解像度などはそのままにしました。
f:id:bluebirdofoz:20200709231230j:plain

これでテクスチャが作成されました。
f:id:bluebirdofoz:20200709231240j:plain

各マテリアルに画像ノードを作成する

マテリアル毎に、ベイク先のテクスチャの参照を設定していきます。
[マテリアル]タブから、編集対象のマテリアルを選択した状態で[シェーダーエディター]を開きます。
f:id:bluebirdofoz:20200709231251j:plain

テクスチャを参照するための画像ノードを追加します。
[追加] -> [テクスチャ] -> [画像テクスチャ] を選択します。
f:id:bluebirdofoz:20200709231300j:plain

[画像テクスチャ]ノードが追加されるので、適当な位置に配置します。
ノードを繋いだりする必要はありません。
f:id:bluebirdofoz:20200709231310j:plain

テクスチャの参照を設定します。
画像アイコンのプルダウンを開き、先ほど作成したテクスチャを指定します。
f:id:bluebirdofoz:20200709231321j:plain

これでテクスチャの参照を設定できました。
他のマテリアルにも同じ設定を行うため、[ノード] -> [コピー] で[画像テクスチャ]ノードをコピーします。
f:id:bluebirdofoz:20200709231332j:plain

他のマテリアルを選択して、[シェーダーエディター]の対象マテリアルを切り替えます。
[ノード] -> [貼り付け] で[画像テクスチャ]ノードを貼り付けします。
f:id:bluebirdofoz:20200709231346j:plain

これでテクスチャを参照する[画像テクスチャ]ノードを設定できます。
同様の手順を繰り返して、全てのマテリアルにノードを設定します。
f:id:bluebirdofoz:20200709231358j:plain

テクスチャにカラー情報をベイクする

最後にカラー情報をテクスチャにベイクします。
全てのマテリアルについて、[画像テクスチャ]ノードが選択状態(白枠)であることを確認してください。
選択中の[画像テクスチャ]ノードがベイク先になります。
f:id:bluebirdofoz:20200709231411j:plain

[レンダー]タブを開き、[レンダーエンジン]で[Cycles]を選択します。
f:id:bluebirdofoz:20200709231426j:plain

[ベイク]パネルが表示されるので開きます。
[ベイクタイプ]を[ディフューズ]に設定します。
f:id:bluebirdofoz:20200709231440j:plain

[影響]を[カラー]のみに設定します。
更に不要なマージンなどが発生しないように[余白]の設定を[0 px]に変更しました。
f:id:bluebirdofoz:20200709231451j:plain

ベイクの結果が確認できるように[画像エディター]を開きます。
f:id:bluebirdofoz:20200709231502j:plain

[ベイク]ボタンをクリックしてベイクを開始します。
f:id:bluebirdofoz:20200709231512j:plain

ベイクが完了するまで待機します。
モデルやマシンスペックによって時間がかかることがあります。
f:id:bluebirdofoz:20200709231522j:plain

ベイクが完了すると、カラー情報が焼き込まれたテクスチャが生成されました。
f:id:bluebirdofoz:20200709231532j:plain

生成したテクスチャを出力保存する場合は [画像] -> [名前をつけて保存] で保存します。
f:id:bluebirdofoz:20200709231608j:plain

BlenderからUnityへ引き継げるマテリアルの情報を確認する

本日は Blender と Unity の小ネタ枠です。
BlenderからUnityへ引き継げるマテリアルの情報を確認します。

BlenderからUnityへ引き継げるマテリアルの情報

ベースカラー

Blenderでのマテリアルの[ベースカラー]は Unity での Albedo のカラーとして取り込まれます。

Blenderでの設定
f:id:bluebirdofoz:20200708225334j:plain

・Unityでの取り込み結果
f:id:bluebirdofoz:20200708225347j:plain

ただし、カラーのアルファ値については引き継げません。
また[メタリック]、[スペキュラー]、[粗さ]の値も引き継ぐことはできません。

Blenderでの設定
f:id:bluebirdofoz:20200708225359j:plain

・Unityでの取り込み結果
f:id:bluebirdofoz:20200708225411j:plain

テクスチャの参照

ベースカラーとノーマルマップのテクスチャ参照については Unity に引き継ぐことができます。
参照を設定するため、マテリアルのノードを有効化して[サーフェス]を[プリンシプルBSDF]に変更します。
ベースカラーに[画像テクスチャ]の参照を設定しました。

Blenderでの設定
f:id:bluebirdofoz:20200708225423j:plain

・Unityでの取り込み結果
f:id:bluebirdofoz:20200708225434j:plain

テクスチャ読み込み時の注意事項

fbx ファイルに含まれるのはテクスチャの参照のみで、テクスチャファイル自体は含まれません。
このため、fbx ファイルの取り込み前にテクスチャファイルを Unity プロジェクトに取り込んでおく必要があります。
テクスチャのファイル名が一致していれば、参照ディレクトリの構成に関係なく参照されます。
f:id:bluebirdofoz:20200708225445j:plain

テクスチャ参照を設定していてもベースカラーの設定は引き継がれます。
f:id:bluebirdofoz:20200708225458j:plain

ベースカラーとテクスチャの色情報が乗算されてしまうので、テクスチャの色合いをそのまま出力したい場合は、必ず[ベースカラー]を白(R:255,G:255,B:255)にしておく必要があります。
f:id:bluebirdofoz:20200708225508j:plain

ノーマルマップの参照

テクスチャのノーマルマップの参照を引き継ぐ場合は、[ノーマル]の項目に[ノーマルマップ]を設定します。
ノーマルマップの[カラー]として[画像テクスチャ]の参照を追加します。

Blenderでの設定
f:id:bluebirdofoz:20200708225519j:plain

・Unityでの取り込み結果
f:id:bluebirdofoz:20200708225530j:plain

ノーマルマップのテクスチャもベースカラーと同様に予めインポートしておく必要があります。