blender-syntax-materials

Installation
SKILL.md

blender-syntax-materials

Quick Reference

Critical Warnings

NEVER use Blender 3.x Principled BSDF socket names in 4.0+ code. Sockets were renamed in 4.0 (e.g., "Subsurface" -> "Subsurface Weight"). Using old names raises KeyError.

NEVER use mat.blend_method in Blender 4.2+. This property was removed. Use mat.surface_render_method instead.

NEVER access UV data per-vertex. UV coordinates are stored per-loop (per face corner). Access via uv_layers.data[loop_index].

NEVER call bpy.data.images.load() without check_existing=True. Omitting it creates duplicate image data blocks on repeated loads.

NEVER set colorspace_settings.name incorrectly. Use 'sRGB' for color/diffuse textures and 'Non-Color' for normal maps, roughness, metallic, and other data textures.

ALWAYS set mat.use_nodes = True before accessing mat.node_tree. Without this, node_tree is None.

ALWAYS store the reference returned by bpy.data.materials.new(). Blender may append .001 if the name already exists.

Version Decision Tree

Creating material code?
├── Target Blender 4.0+ ONLY?
│   ├── YES → Use 4.0+ Principled BSDF socket names directly
│   └── NO → Use version-safe helper (see Pattern 3)
Setting transparency/alpha blending?
├── Blender 4.2+?
│   ├── YES → mat.surface_render_method = 'BLENDED'
│   └── NO (3.x / 4.0-4.1) → mat.blend_method = 'BLEND'
Connecting texture to Principled BSDF?
├── Color texture (diffuse, base color)?
│   └── Connect to "Base Color" input (all versions)
├── Normal map?
│   └── Connect via ShaderNodeNormalMap → "Normal" input
└── Data texture (roughness, metallic, AO)?
    └── Set image colorspace to 'Non-Color'

Essential Patterns

Pattern 1: Create and Assign a Material

# Blender 3.x/4.x/5.x — create material and assign to object
import bpy

mat = bpy.data.materials.new(name="MyMaterial")
mat.use_nodes = True  # REQUIRED before accessing node_tree

obj = bpy.context.active_object
if obj.data.materials:
    obj.data.materials[0] = mat   # Replace first slot
else:
    obj.data.materials.append(mat)  # Add new slot

Pattern 2: Build a Complete Node Tree

# Blender 3.x/4.x/5.x — node tree from scratch
mat = bpy.data.materials.new("NodeMaterial")
mat.use_nodes = True
tree = mat.node_tree

# Clear defaults
tree.nodes.clear()

# Create nodes
principled = tree.nodes.new('ShaderNodeBsdfPrincipled')
principled.location = (0, 0)

output = tree.nodes.new('ShaderNodeOutputMaterial')
output.location = (400, 0)

# Link BSDF to output
tree.links.new(principled.outputs["BSDF"], output.inputs["Surface"])

Pattern 3: Version-Safe Principled BSDF Input Access

# Blender 3.x/4.0+ — handle renamed sockets
import bpy

def set_principled_value(node, socket_3x, socket_4x, value):
    """Set Principled BSDF input with version-safe socket name."""
    if bpy.app.version >= (4, 0, 0):
        socket_name = socket_4x
    else:
        socket_name = socket_3x
    if socket_name in node.inputs:
        node.inputs[socket_name].default_value = value

# Usage
set_principled_value(principled, "Subsurface", "Subsurface Weight", 0.1)
set_principled_value(principled, "Specular", "Specular IOR Level", 0.5)
set_principled_value(principled, "Transmission", "Transmission Weight", 1.0)
set_principled_value(principled, "Coat", "Coat Weight", 0.3)
set_principled_value(principled, "Sheen", "Sheen Weight", 0.1)
set_principled_value(principled, "Emission", "Emission Color", (1, 1, 1, 1))

Pattern 4: Texture Node with UV Mapping

# Blender 3.x/4.x/5.x — image texture with UV coordinates
tree = mat.node_tree

tex_coord = tree.nodes.new('ShaderNodeTexCoord')
tex_coord.location = (-800, 0)

mapping = tree.nodes.new('ShaderNodeMapping')
mapping.location = (-600, 0)

tex_node = tree.nodes.new('ShaderNodeTexImage')
tex_node.location = (-400, 0)
img = bpy.data.images.load("/path/to/texture.png", check_existing=True)
tex_node.image = img

# Link: TexCoord → Mapping → Image Texture → Principled BSDF
tree.links.new(tex_coord.outputs["UV"], mapping.inputs["Vector"])
tree.links.new(mapping.outputs["Vector"], tex_node.inputs["Vector"])
tree.links.new(tex_node.outputs["Color"], principled.inputs["Base Color"])

Pattern 5: Alpha/Transparency Setup (Version-Dependent)

# Blender 4.2+ — EEVEE transparency
mat.surface_render_method = 'BLENDED'  # 4.2+ ONLY

# Blender 3.x / 4.0-4.1 — EEVEE transparency
# mat.blend_method = 'BLEND'  # REMOVED in 4.2

# Version-safe pattern
if bpy.app.version >= (4, 2, 0):
    mat.surface_render_method = 'BLENDED'
else:
    mat.blend_method = 'BLEND'

Principled BSDF Socket Rename Table (3.x -> 4.0+)

Blender 3.x Name Blender 4.0+ Name Notes
Base Color Base Color Unchanged
Subsurface Subsurface Weight Renamed
Subsurface Color REMOVED Use Base Color instead
Specular Specular IOR Level Renamed
Specular Tint Specular Tint Type changed: Float -> Color
Transmission Transmission Weight Renamed
Coat Coat Weight Renamed
Sheen Sheen Weight Renamed
Emission Emission Color Renamed
Metallic Metallic Unchanged
Roughness Roughness Unchanged
IOR IOR Unchanged
Alpha Alpha Unchanged
Normal Normal Unchanged

Common Operations

Assign Material to Specific Faces

# Blender 3.x/4.x/5.x — multi-material assignment
import bpy

obj = bpy.context.active_object

# Add two materials to object
mat_a = bpy.data.materials.new("Material_A")
mat_b = bpy.data.materials.new("Material_B")
obj.data.materials.append(mat_a)
obj.data.materials.append(mat_b)

# Assign material index per polygon
for polygon in obj.data.polygons:
    if polygon.center.z > 0:
        polygon.material_index = 1  # Material_B
    else:
        polygon.material_index = 0  # Material_A

Add Material Slot via Operator

# Blender 3.x/4.x/5.x — operator-based slot management
import bpy

obj = bpy.context.active_object
bpy.context.view_layer.objects.active = obj

# Add empty slot
bpy.ops.object.material_slot_add()

# Assign material to active slot
obj.material_slots[obj.active_material_index].material = mat

# Remove active slot
bpy.ops.object.material_slot_remove()

Access Default Principled BSDF

When use_nodes = True is set on a new material, Blender creates a default Principled BSDF and Material Output automatically.

# Blender 3.x/4.x/5.x — access default nodes without clearing
mat = bpy.data.materials.new("QuickMaterial")
mat.use_nodes = True
principled = mat.node_tree.nodes.get("Principled BSDF")
# principled is the auto-created ShaderNodeBsdfPrincipled

UV Layer Management

# Blender 3.x/4.x/5.x — UV layer access
mesh = obj.data

# List UV layers
for uv_layer in mesh.uv_layers:
    print(uv_layer.name)

# Get active UV layer
active_uv = mesh.uv_layers.active

# Create new UV layer
new_uv = mesh.uv_layers.new(name="ProjectionUV")

# Read UV coordinates (per-loop, NOT per-vertex)
for loop_idx in range(len(mesh.loops)):
    uv = active_uv.data[loop_idx].uv
    # uv.x, uv.y are the coordinates

# Modify UV coordinates
for loop_idx in range(len(mesh.loops)):
    active_uv.data[loop_idx].uv.x *= 2.0
    active_uv.data[loop_idx].uv.y *= 2.0

Load and Configure Image Textures

# Blender 3.x/4.x/5.x — image loading
import bpy

# Load from file (reuse existing if already loaded)
img = bpy.data.images.load("/path/to/texture.png", check_existing=True)

# Create new blank image (for baking)
img = bpy.data.images.new("BakeTarget", width=2048, height=2048)

# Configure texture node
tex_node = tree.nodes.new('ShaderNodeTexImage')
tex_node.image = img
tex_node.interpolation = 'Linear'   # 'Linear', 'Closest', 'Cubic', 'Smart'
tex_node.projection = 'FLAT'        # 'FLAT', 'BOX', 'SPHERE', 'TUBE'
tex_node.extension = 'REPEAT'       # 'REPEAT', 'EXTEND', 'CLIP'

# Set color space
img.colorspace_settings.name = 'sRGB'       # For diffuse/color textures
# img.colorspace_settings.name = 'Non-Color' # For normal, roughness, metallic

Normal Map Setup

# Blender 3.x/4.x/5.x — normal map node chain
tree = mat.node_tree

normal_tex = tree.nodes.new('ShaderNodeTexImage')
normal_tex.image = bpy.data.images.load("/path/to/normal.png", check_existing=True)
normal_tex.image.colorspace_settings.name = 'Non-Color'  # REQUIRED for normal maps

normal_map = tree.nodes.new('ShaderNodeNormalMap')

tree.links.new(normal_tex.outputs["Color"], normal_map.inputs["Color"])
tree.links.new(normal_map.outputs["Normal"], principled.inputs["Normal"])

Remove All Materials from Object

# Blender 3.x/4.x/5.x — clear all material slots
obj.data.materials.clear()

Common Shader Node Types

Node Type String Class Purpose
'ShaderNodeBsdfPrincipled' Principled BSDF Main PBR shader
'ShaderNodeOutputMaterial' Material Output Final output
'ShaderNodeTexImage' Image Texture Load image files
'ShaderNodeTexCoord' Texture Coordinate UV, Object, Generated coords
'ShaderNodeMapping' Mapping Transform texture coordinates
'ShaderNodeNormalMap' Normal Map Convert image to normal vector
'ShaderNodeMixShader' Mix Shader Blend two shaders
'ShaderNodeBsdfTransparent' Transparent BSDF Transparency shader
'ShaderNodeBsdfGlass' Glass BSDF Glass shader
'ShaderNodeMath' Math Scalar math operations
'ShaderNodeMixRGB' Mix (Color) Blend colors (3.x name)
'ShaderNodeMix' Mix Blend colors/vectors (4.0+)
'ShaderNodeValToRGB' Color Ramp Map value to color gradient
'ShaderNodeBump' Bump Generate bump from height
'ShaderNodeSeparateXYZ' Separate XYZ Split vector components
'ShaderNodeCombineXYZ' Combine XYZ Merge components to vector
'ShaderNodeTexNoise' Noise Texture Procedural noise
'ShaderNodeTexVoronoi' Voronoi Texture Procedural voronoi
'ShaderNodeGroup' Node Group Reusable node group instance

EEVEE vs Cycles Material Differences

Property EEVEE Cycles Notes
Transparency Requires surface_render_method (4.2+) or blend_method (3.x-4.1) Automatic from Alpha EEVEE needs explicit config
Screen Space Refraction mat.use_screen_refraction = True Not needed EEVEE-specific
Backface Culling mat.use_backface_culling mat.use_backface_culling Same API
Displacement mat.cycles.displacement_method mat.cycles.displacement_method Cycles-only
Shadow Mode mat.shadow_method (3.x-4.1) Automatic EEVEE-specific

Version-Specific Migration Rules

Feature Blender 3.x Blender 4.0+ Blender 4.2+
Principled BSDF sockets Old names New names (see table) Same as 4.0
Alpha blending (EEVEE) mat.blend_method = 'BLEND' mat.blend_method = 'BLEND' mat.surface_render_method = 'BLENDED'
Shadow method (EEVEE) mat.shadow_method mat.shadow_method Property restructured
Mix node 'ShaderNodeMixRGB' 'ShaderNodeMix' (preferred) 'ShaderNodeMix'
Specular Tint type Float (0.0-1.0) Color (RGBA) Color (RGBA)

Reference Links

Official Sources

Related skills

More from openaec-foundation/computational-design-day-delft-march-2026

Installs
1
GitHub Stars
1
First Seen
Mar 24, 2026