見出し画像

blender,pythonでミックスシェーダーを使用して4種類の色(例: 赤、青、緑、黄色)を順番に切り替える

"""
タイトル: マテリアル4色切り替えアニメーションスクリプト
説明:
Blender内でミックスシェーダーを使用して、4種類の色(例: 赤、青、緑、黄色)を順番に切り替える
球体のマテリアル色をアニメーション化するシーンを作成します。
色の切り替え順と間隔はメイン関数で設定可能で、4色以上に拡張する際にも対応可能です。

作成日時: 2024年11月14日
バージョン: 2.1.0
"""

import bpy
import random


def clear_scene():
    """既存のオブジェクトとマテリアルを削除し、カメラとライトを作成"""
    for obj in bpy.data.objects:
        bpy.data.objects.remove(obj, do_unlink=True)
    for mat in bpy.data.materials:
        bpy.data.materials.remove(mat, do_unlink=True)

    if not any(obj.type == 'CAMERA' for obj in bpy.data.objects):
        bpy.ops.object.camera_add(location=(0, -10, 5), rotation=(1.1, 0, 0))
    if not any(obj.type == 'LIGHT' for obj in bpy.data.objects):
        bpy.ops.object.light_add(type='POINT', location=(5, -5, 10))


def create_mixed_material(name, colors):
    """
    任意の4色を切り替えるミックスマテリアルを作成します。

    Args:
        name (str): マテリアル名。
        colors (list): 色リスト [(R, G, B, A), ...]。

    Returns:
        bpy.types.Material: 作成したマテリアル。
    """
    mat = bpy.data.materials.get(name)
    if mat is None:
        mat = bpy.data.materials.new(name=name)
        mat.use_nodes = True

        nodes = mat.node_tree.nodes
        links = mat.node_tree.links

        # ノードのクリア
        for node in nodes:
            nodes.remove(node)

        # ノードの追加
        output_node = nodes.new(type="ShaderNodeOutputMaterial")
        mix_shader_1 = nodes.new(type="ShaderNodeMixShader")
        mix_shader_2 = nodes.new(type="ShaderNodeMixShader")
        mix_shader_3 = nodes.new(type="ShaderNodeMixShader")
        diffuse_nodes = []

        # 各色用のDiffuseノードを作成
        for i, color in enumerate(colors):
            diffuse = nodes.new(type="ShaderNodeBsdfDiffuse")
            diffuse.inputs["Color"].default_value = color
            diffuse_nodes.append(diffuse)

        # ミックスシェーダーを接続
        links.new(diffuse_nodes[0].outputs["BSDF"], mix_shader_1.inputs[1])
        links.new(diffuse_nodes[1].outputs["BSDF"], mix_shader_1.inputs[2])
        links.new(mix_shader_1.outputs["Shader"], mix_shader_2.inputs[1])
        links.new(diffuse_nodes[2].outputs["BSDF"], mix_shader_2.inputs[2])
        links.new(mix_shader_2.outputs["Shader"], mix_shader_3.inputs[1])
        links.new(diffuse_nodes[3].outputs["BSDF"], mix_shader_3.inputs[2])
        links.new(mix_shader_3.outputs["Shader"], output_node.inputs["Surface"])

        # ファクター用ノードを追加
        factor_node_1 = nodes.new(type="ShaderNodeValue")
        factor_node_2 = nodes.new(type="ShaderNodeValue")
        factor_node_3 = nodes.new(type="ShaderNodeValue")

        factor_node_1.outputs[0].default_value = 0.0
        factor_node_2.outputs[0].default_value = 0.0
        factor_node_3.outputs[0].default_value = 0.0

        links.new(factor_node_1.outputs[0], mix_shader_1.inputs["Fac"])
        links.new(factor_node_2.outputs[0], mix_shader_2.inputs["Fac"])
        links.new(factor_node_3.outputs[0], mix_shader_3.inputs["Fac"])

        # ノード名を保持
        mat["factor_nodes"] = [factor_node_1.name, factor_node_2.name, factor_node_3.name]

    return mat


def animate_mixed_material(mat, frame, color_index):
    """
    ミックスマテリアルの色を4色のうち1色に切り替える。

    Args:
        mat (bpy.types.Material): ミックスマテリアル。
        frame (int): 色を切り替えるフレーム。
        color_index (int): 切り替える色のインデックス (0: 赤, 1: 青, 2: 緑, 3: 黄)。
    """
    factor_nodes = mat.get("factor_nodes")
    if not factor_nodes:
        print("Factor nodes not found in material.")
        return

    for i, node_name in enumerate(factor_nodes):
        factor_node = mat.node_tree.nodes.get(node_name)
        if not factor_node:
            print(f"Factor node {node_name} not found.")
            continue

        # 指定された色のインデックスに応じてファクターを設定
        factor_value = 1.0 if color_index == i else 0.0
        factor_node.outputs[0].default_value = factor_value
        factor_node.outputs[0].keyframe_insert(data_path="default_value", frame=frame)


def main():
    # シーンを初期化
    clear_scene()

    # 球体を作成
    bpy.ops.mesh.primitive_uv_sphere_add(radius=1, location=(0, 0, 1))
    sphere = bpy.context.object
    bpy.ops.object.shade_smooth()
    sphere.name = "Sphere"

    # 4色ミックスマテリアルを作成
    colors = [
        (1.0, 0.0, 0.0, 1.0),  # 赤
        (0.0, 0.0, 1.0, 1.0),  # 青
        (0.0, 1.0, 0.0, 1.0),  # 緑
        (1.0, 1.0, 0.0, 1.0)   # 黄
    ]
    mixed_material = create_mixed_material("FourColorMix", colors)
    sphere.data.materials.append(mixed_material)

    # 色切り替えアニメーションを設定
    frame_start = 1
    frame_interval = 60  # 色が切り替わる間隔(フレーム数)
    total_switches = 8  # 切り替え回数

    for i in range(total_switches):
        color_index = i % 4  # 色インデックスを順番に切り替え
        frame = frame_start + i * frame_interval
        animate_mixed_material(mixed_material, frame, color_index)

    # 初期フレームを設定
    bpy.context.scene.frame_set(1)


# 実行
main()

いいなと思ったら応援しよう!