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 |