Skip to content

Instantly share code, notes, and snippets.

@yunho-c
Created May 22, 2026 02:41
Show Gist options
  • Select an option

  • Save yunho-c/18e1324c4be9ef0f3c23190a2fb38b3c to your computer and use it in GitHub Desktop.

Select an option

Save yunho-c/18e1324c4be9ef0f3c23190a2fb38b3c to your computer and use it in GitHub Desktop.
Blender: create toon shader
import bpy
def create_toon_shader():
mat_name = "Toon_3_Tone"
# Create a new material and enable use of nodes
mat = bpy.data.materials.new(name=mat_name)
mat.use_nodes = True
# Get the node tree
nodes = mat.node_tree.nodes
links = mat.node_tree.links
# Clear out the default Principled BSDF node setup
nodes.clear()
# --- Create Nodes ---
# 1. Diffuse BSDF
node_diffuse = nodes.new(type='ShaderNodeBsdfDiffuse')
node_diffuse.location = (-400, 0)
# 2. Shader to RGB
# Note: This node only functions in Eevee
node_shader2rgb = nodes.new(type='ShaderNodeShaderToRGB')
node_shader2rgb.location = (-200, 0)
# 3. ColorRamp
node_ramp = nodes.new(type='ShaderNodeValToRGB')
node_ramp.location = (0, 0)
# Set interpolation to 'CONSTANT' to crush the gradients into flat colors
node_ramp.color_ramp.interpolation = 'CONSTANT'
# 4. Material Output
node_output = nodes.new(type='ShaderNodeOutputMaterial')
node_output.location = (300, 0)
# --- Configure ColorRamp (3 Tones) ---
ramp = node_ramp.color_ramp
# A ColorRamp comes with 2 elements by default. Add a 3rd for the mid-tone.
ramp.elements.new(position=0.5)
# Set the threshold positions for where the light cuts off
ramp.elements[0].position = 0.00 # Shadow
ramp.elements[1].position = 0.25 # Mid-tone
ramp.elements[2].position = 0.65 # Highlight
# Set the colors (RGBA format). Currently set to a technical blue/grey.
ramp.elements[0].color = (0.2, 0.25, 0.3, 1.0) # Dark Shadow
ramp.elements[1].color = (0.4, 0.5, 0.6, 1.0) # Mid-tone
ramp.elements[2].color = (0.7, 0.8, 0.9, 1.0) # Bright Highlight
# --- Link the Nodes ---
links.new(node_diffuse.outputs['BSDF'], node_shader2rgb.inputs['Shader'])
links.new(node_shader2rgb.outputs['Color'], node_ramp.inputs['Fac'])
links.new(node_ramp.outputs['Color'], node_output.inputs['Surface'])
# --- Assign to Active Object ---
obj = bpy.context.active_object
if obj and obj.type == 'MESH':
# If the object already has materials, replace the first one, otherwise append
if len(obj.data.materials) > 0:
obj.data.materials[0] = mat
else:
obj.data.materials.append(mat)
print(f"Success: Assigned '{mat_name}' to {obj.name}")
else:
print(f"Notice: Created material '{mat_name}', but no valid active mesh object was selected.")
# Execute the function
create_toon_shader()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment