2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Blenderのシェーダーでオブジェクトの座標を出力するノードを作成

Posted at

Blenderのシェーダーでは特定のオブジェクトの座標を取得するノードが用意されていません
似たようなノードに、オブジェクトからの座標を出力するノードはありますが
ターゲットのオブジェクトを回転させてしまうと欲しい動作とは違ってきてしまいます。
212031202.gif
Blenderにはドライバという 他のオブジェクトの情報から動的に値を設定する機能があって
ノードの値の入力にもドライバを設定することができるので
面倒な設定を自動化するアドオンを作成してみました

y_add_LocationNode.py
bl_info = {
    "name" : "Add location node",
    "author" : "Yukimituki",
    "description" : "",
    "blender" : (2, 80, 0),
    "version" : (0, 0, 1),
    "location" : "",
    "warning" : "",
    "category" : "Node"
}
import bpy
class NodeLocationNoePanel(bpy.types.Panel):
    bl_idname = "NODE_PT_LocationNode"
    bl_space_type = 'NODE_EDITOR'
    bl_label = "Add Location Node"
    bl_region_type = "UI"
    bl_category = "Tool"
    def draw(self, context):
        material = context.material
        if hasattr(material, 'node_tree'):
            node_tree = material.node_tree
            layout = self.layout
            row = layout.row()
            row.prop_search(node_tree, "target_name", context.scene, "objects")
            row = layout.row()
            row.operator("nodetree.locationnode")

class NODE_OT_Locationbnode(bpy.types.Operator):
    bl_idname = "nodetree.locationnode"
    bl_label = "Add object location node"
    def execute(self, context):
        node_tree = context.material.node_tree
        target_name = node_tree.target_name
        # ノードの作成
        drive_node = node_tree.nodes.new( 'ShaderNodeCombineXYZ' )
        drive_node.name = "LocationNode"
        drive_node.label = target_name + ".location"
        target_obj = bpy.data.objects[target_name]
        for i in range(3):
            # ノードの値をドライバで設定
            prop = drive_node.inputs[i].driver_add('default_value')
            #スクリプトタイプのドライバ
            prop.driver.type =  'SCRIPTED'
            #ドライバ変数の作成
            var = prop.driver.variables.new()
            var.name = 'location'
            var.type = 'SINGLE_PROP'
            # ドライバのターゲットの設定
            var.targets[0].id = target_obj
            var.targets[0].data_path = 'location[%s]' % i
            #式の入力
            prop.driver.expression = 'location'
        return {'FINISHED'}

classes = (
    NodeLocationNoePanel,
    NODE_OT_Locationbnode,
    )
def register():
    bpy.types.NodeTree.target_name = bpy.props.StringProperty(name = "Objact")
    #classes
    for cls in classes:
        bpy.utils.register_class(cls)
def unregister():
    del bpy.types.NodeTree.target_name
    #classes
    for cls in classes:
        bpy.utils.unregister_class(cls)
if __name__ == "__main__":
    register()

アドオンを有効にするとシェーダーエディターのツールタブに
”Add Location Node” という項目が追加します
image.png
Object:の項目で座標を取得したいオブジェクトを選択して
Add object location node のボタンを押すと 目的のオブジェクトの座標を取得するノードが作成されます

例えば冒頭のようにマテリアルのついたオブジェクトと目的のオブジェクトの座標から方向ベクトルを取得して
法線との内積をとれば ライティングのようなことができるようになります
212031201.gif
このスクリプト単体では使いどころが少ないかもしれませんが

例えば既存のトゥーンシェーダーマテリアルだと オブジェクトを一緒に頒布することになっているものが
これをうまく利用すれば スクリプトだけで設定できるようになるかもしれません

2
2
0

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
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?