blender/blender python

다이아몬드 쉐이더 Add-On

monstro 2025. 7. 2. 12:20
728x90
반응형

- 개요

메쉬에 대해 다이아몬드와 비슷한 시각적 효과를 줄 수 있는 쉐이더 Add-On을 만들어본다

다이아몬드 효과를 주기 위해 사용하는 노드는 다음과 같다

  • 4개의 GlassBSDF 노드
  • 2개의 Add 노드
  • 1개의 MixShader 노드
  • 최종 결과물을 반환하는 Material Output 노드

 

- Add-On 스크립트의 구성

1) bl_info 구조체 정의

bl_info = {
    "name": "Shader Library",
    "author": "Monstro",
    "version": (1, 0),
    "blender": (4, 1, 0),
    "location": "View3D > ToolShelf",
    "description": "Adds a new Shader to your object",
    "warning": "",
    "doc_url": "",
    "category": "Add Shader",
}

 

bl_info 변수를 정의하여 해당 스크립트를 Add-On으로 전환할 수 있도록 한다

 

2) 메인 패널 정의

...

import bpy

class ShaderMainPanel(bpy.types.Panel):
    bl_label = "Shader Library"
    bl_idname = "SHADER_PT_MAINPANEL"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Shader Library'

    def draw(self, context):
        layout = self.layout

        row = layout.row()
        row.label(text = "Select a Shader to be added.")
        row.operator('shader.diamond_operator')
        
...

 

쉐이더를 적용하기 위한 메인 패널의 클래스를 정의하였다

3D 뷰포트에서 UI 형식의 패널로 사용할 수 있으며

operator 연산자를 사용하여 쉐이더를 오브젝트에 적용한다

 

3) 쉐이더 클래스 정의

class SHADER_OF_DIAMOND(bpy.types.Operator):
    bl_label = "Diamond"
    bl_idname = 'shader.diamond_operator'
    
    def execute(self, context):
        # Creating a New Diamond material
        material_diamond = bpy.data.materials.new(name = "Diamond")
        
        # Enable Use Nodes
        material_diamond.use_nodes = True
        
        # Find Principled BSDF Node and Remove it
        material_diamond.node_tree.nodes.remove(material_diamond.node_tree.nodes.get('Principled BSDF'))
        
        # Find Material Output Node and place it
        material_output = material_diamond.node_tree.nodes.get('Material Output')
        material_output.location = (400, 0)
        
        
        # Add GlassBsdf Node 1
        glass1_node = material_diamond.node_tree.nodes.new('ShaderNodeBsdfGlass')
        glass1_node.location = (-600, 0)
        # Find First Input of GlassBsdf Node, Setting Default Color
        glass1_node.inputs[0].default_value = (1, 0, 0, 1)
        # Find Third Input of GlassBsdf Node, Setting IOR 
        glass1_node.inputs[2].default_value = 1.446
        
        
        # Add GlassBsdf Node 2
        glass2_node = material_diamond.node_tree.nodes.new('ShaderNodeBsdfGlass')
        glass2_node.location = (-600, -150)
        # Find First Input of GlassBsdf Node, Setting Default Color
        glass2_node.inputs[0].default_value = (0, 1, 0, 1)
        # Find Third Input of GlassBsdf Node, Setting IOR 
        glass2_node.inputs[2].default_value = 1.450


        # Add GlassBsdf Node 3
        glass3_node = material_diamond.node_tree.nodes.new('ShaderNodeBsdfGlass')
        glass3_node.location = (-600, -300)
        # Find First Input of GlassBsdf Node, Setting Default Color
        glass3_node.inputs[0].default_value = (0, 0, 1, 1)
        # Find Third Input of GlassBsdf Node, Setting IOR 
        glass3_node.inputs[2].default_value = 1.450


        # Create Add Shader Node
        add1_node = material_diamond.node_tree.nodes.new('ShaderNodeAddShader')
        add1_node.location = (-400, -50)
        add1_node.label = "Add 1"
        # Minimize the Node
        add1_node.hide = True
        # Deselect the Node
        add1_node.select = False

        
        # Create Add Shader Node 2
        add2_node = material_diamond.node_tree.nodes.new('ShaderNodeAddShader')
        add2_node.location = (-100, 0)
        add2_node.label = "Add 1"
        # Minimize the Node
        add2_node.hide = True
        # Deselect the Node
        add2_node.select = False
        
        
        # Add GlassBsdf Node 4
        glass4_node = material_diamond.node_tree.nodes.new('ShaderNodeBsdfGlass')
        glass4_node.location = (-150, -150)
        # Find First Input of GlassBsdf Node, Setting Default Color
        glass4_node.inputs[0].default_value = (1, 1, 1, 1)
        # Find Third Input of GlassBsdf Node, Setting IOR 
        glass4_node.inputs[2].default_value = 1.450
        # Deslect the Node
        glass4_node.select = False
        
        
        # Create Mix Shader Node
        mix1_node = material_diamond.node_tree.nodes.new('ShaderNodeMixShader')
        mix1_node.location = (200, 0)
        # Deselect the Node
        mix1_node.select = False
        
        
        # Link the Nodes
        material_diamond.node_tree.links.new(glass1_node.outputs[0], add1_node.inputs[0])
        material_diamond.node_tree.links.new(glass2_node.outputs[0], add1_node.inputs[1])
        
        material_diamond.node_tree.links.new(add1_node.outputs[0], add2_node.inputs[0])
        material_diamond.node_tree.links.new(glass3_node.outputs[0], add2_node.inputs[1])
        
        material_diamond.node_tree.links.new(add2_node.outputs[0], mix1_node.inputs[1])
        material_diamond.node_tree.links.new(glass4_node.outputs[0], mix1_node.inputs[2])
        
        material_diamond.node_tree.links.new(mix1_node.outputs[0], material_output.inputs[0])
          
        
        # Apply Material to Object
        bpy.context.object.active_material = material_diamond
        return {'FINISHED'}

 

쉐이더 연산을 수행하는 SHADER_OF_DIAMOND 클래스를 생성하였다

연산을 수행하기 위해 부모 클래스 bpy.types.Operator를 상속받고

bl_idname을 정의하여 해당 클래스를 사용한다

 

연산 클래스의 동작을 정의하는 execute 함수에서는 다음의 절차에 따라 코드를 구성하였다

  • 새로운 Diamond 머티리얼 생성 + 해당 머티리얼에서 node 사용 설정
  • 머티리얼에서 기본 제공되는 Principled BSDF 노드 제거
  • 기본 제공되는 Material Output 노드 위치 설정
  • 첫번째 GlassBSDF 노드의 input과 위치 설정
  • 두번째 GlassBSDF 노드의 input과 위치 설정
  • 세번째 GlassBSDF 노드의 input과 위치 설정
  • 첫번째 Add Shader 노드 추가하고 위치 및 노드 크기 설정
  • 두번째 Add Shader 노드 추가하고 위치 및 노드 크기 설정
  • 네번째 GlassBSDF 노드의 input위치 설정
  • Mix Shader 노드 추가하고 위치 설정
  • 추가한 모든 노드들간의 링크 설정
  • 노드간의 결합으로 완성된 머티리얼을 선택한 뷰포트의 오브젝트에 적용

 

최종적으로 register 함수unregister 함수를 정의하여 해당 BPY 스크립트의 

활성화 / 비활성화를 수행하고 main 함수에서 활성화한다

 

눈여겨볼 부분은 머티리얼bpy.data.materials에 저장되었다는 점이고,

머티리얼에 대한 노드의 연산 머티리얼명.node_tree.nodes에서 이뤄진다는 점이다

 

 

노드의 구성에서 빨간색으로 표시된 부분이 노드간의 링크를 의미하고 

파란색으로 표시된 부분노드의 연산값에 영향을 주는 input을 의미한다

두 구성요소 모두 0부터 시작한다

 

- 최종 실행 결과

 

728x90
반응형

'blender > blender python' 카테고리의 다른 글

텍스트 Add-On  (0) 2025.07.09
대화 상자  (0) 2025.07.09
BPY를 이용한 키프레임 모디파이어 추가  (0) 2025.07.02
BPY 스크립트를 Add-On으로 완성  (0) 2025.06.25
BPY 스크립트로 Blender에 기능 추가  (0) 2025.06.25