Builds PBR materials with Blender's shader nodes; triggers when crafting Principled BSDF materials, procedural Noise/Voronoi textures, UV work for texturing, or choosing between normal maps and bump.
./install.sh blender-material-shadersname: "blender_material_shaders" description: "Builds PBR materials with Blender's shader nodes; triggers when crafting Principled BSDF materials, procedural Noise/Voronoi textures, UV work for texturing, or choosing between normal maps and bump." metadata: { "includeInPrompt": true }
Craft production-ready PBR materials inside Blender using the Principled BSDF and procedural texture nodes. This skill covers material and shader work only.
Not this skill: headless-blender owns headless render ops ("Render with Blender on a headless VM: background mode, Cycles CPU, robust frame output, and common gotchas."); 3d-printing-basics owns FDM print prep ("Beginner FDM 3D printing workflow: slicer settings that matter, filament choice (PLA/PETG/ABS), first-layer and bed-adhesion troubleshooting, and common print-failure diagnosis."). This skill owns material and shader craft; nothing about printers or render farms.
The deliverable is a short Blender Python script that builds the material from scratch when run headless (blender -b -P build_material.py), plus a rendered preview PNG of the material on a sphere. The script must run clean on Blender 5.1.1 (verified 2026-10-07: procedural Principled BSDF with Noise-driven roughness and Voronoi-driven color rendered a 256px thumbnail without errors).
Short reference script. Save as build_material.py, then run blender -b -P build_material.py:
python
import bpy, math
bpy.ops.wm.read_factory_settings(use_empty=True)
scene = bpy.context.scene
scene.render.engine = 'CYCLES'
scene.cycles.device = 'CPU'
scene.cycles.samples = 32
scene.render.resolution_x = 256
scene.render.resolution_y = 256
bpy.ops.mesh.primitive_uv_sphere_add(radius=1.0)
obj = bpy.context.active_object
mat = bpy.data.materials.new("ProceduralMat")
mat.use_nodes = True
nodes, links = mat.node_tree.nodes, mat.node_tree.links
nodes.clear()
out = nodes.new('ShaderNodeOutputMaterial'); out.location = (400, 0)
bsdf = nodes.new('ShaderNodeBsdfPrincipled'); bsdf.location = (100, 0)
links.new(bsdf.outputs['BSDF'], out.inputs['Surface'])
texc = nodes.new('ShaderNodeTexCoord'); texc.location = (-700, 0)
mapping = nodes.new('ShaderNodeMapping'); mapping.location = (-500, 0)
links.new(texc.outputs['UV'], mapping.inputs['Vector'])
vor = nodes.new('ShaderNodeTexVoronoi'); vor.location = (-300, 200)
vor.inputs['Scale'].default_value = 8.0
links.new(mapping.outputs['Vector'], vor.inputs['Vector'])
ramp = nodes.new('ShaderNodeValToRGB'); ramp.location = (-100, 200)
links.new(vor.outputs['Distance'], ramp.inputs['Fac'])
links.new(ramp.outputs['Color'], bsdf.inputs['Base Color'])
noise = nodes.new('ShaderNodeTexNoise'); noise.location = (-300, -200)
noise.inputs['Scale'].default_value = 5.0
links.new(mapping.outputs['Vector'], noise.inputs['Vector'])
links.new(noise.outputs['Fac'], bsdf.inputs['Roughness'])
obj.data.materials.append(mat)
bpy.ops.object.light_add(type='AREA', location=(2.5, -2.5, 3.0))
bpy.ops.object.camera_add(location=(0, -3.5, 1.2), rotation=(math.radians(78), 0, 0))
scene.camera = bpy.context.active_object
scene.render.filepath = "/tmp/material_preview.png"
bpy.ops.render.render(write_still=True)
[i.name for i in bsdf.inputs] (on 5.1.1 this returns Base Color, Metallic, Roughness, IOR, Alpha, Normal, Weight, ..., Transmission Weight, Coat Weight, and more).default_value on shader sockets are interpreted as linear, not sRGB. Convert an intended sRGB pick to linear before assigning, or the material renders washed out.blender --version before quoting behavior, since node layout shifts between releases. The script above was verified on 5.1.1.publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.