blender-materials
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBlender Materials
Blender材质
Apply physically-based materials to objects. Use only Principled BSDF — it's the only shader that exports cleanly to glTF and matches what other DCC tools expect.
为物体应用基于物理属性的材质。仅使用Principled BSDF——这是唯一能完美导出到glTF且符合其他DCC工具预期的着色器。
The metallic switch — never an in-between
金属开关——非黑即白
The single most-important rule: Metallic is a switch, not a slider. Set it to (dielectric: plastic, wood, glass, skin) or (metal: steel, gold, copper). Values between 0.2 and 0.8 are almost always wrong; they produce energy-non-conservative renders that look "plasticky."
0.01.0Exception: dark mirror lenses (sunglasses) use ~0.8 to combine strong reflection with slight tint — that's a stylistic choice, not strict PBR.
最重要的规则:金属度是开关,而非滑块。将其设置为(绝缘材质:塑料、木材、玻璃、皮肤)或(金属材质:钢、金、铜)。0.2至0.8之间的值几乎都是错误的,会导致渲染结果不符合能量守恒,看起来像“塑料质感”。
0.01.0例外情况:深色镜面镜片(太阳镜)会使用约0.8的金属度,以结合强反射和轻微着色——这是风格化选择,而非严格的PBR标准。
Decision tree
决策树
What is it made of?
├── Raw metal (steel, gold, copper, etc.)
│ → Metallic=1.0, Base Color = F0 reflectance from physicallybased.info
│ → Roughness controls polish (0.05 mirror → 0.4 brushed → 0.7+ weathered)
│
├── Glass / clear / refractive
│ → Metallic=0, Transmission=1.0, IOR=1.5 (glass), Roughness=0.0
│ → Add Volume Absorption for thick tinted glass
│
├── Plastic / wood / stone (dielectric, opaque)
│ → Metallic=0, IOR=1.45 (plastic) or 1.5 (most others)
│ → Roughness per finish (0.15 glossy / 0.6 matte)
│ → Coat Weight 0.5+ for varnished/lacquered surfaces
│
├── Skin / wax / marble (subsurface scattering)
│ → Metallic=0, Subsurface Weight=1.0
│ → Subsurface Radius RGB tuned per material (skin: red scatters deepest)
│
├── Cloth / fabric (sheen)
│ → Metallic=0, Sheen Weight 0.2-0.5
│ → Roughness 0.6+, Sheen Roughness 0.5
│
└── Mirror / chrome (special metal)
→ Metallic=1.0, Roughness=0.02-0.05, near-white baseWhat is it made of?
├── Raw metal (steel, gold, copper, etc.)
│ → Metallic=1.0, Base Color = F0 reflectance from physicallybased.info
│ → Roughness controls polish (0.05 mirror → 0.4 brushed → 0.7+ weathered)
│
├── Glass / clear / refractive
│ → Metallic=0, Transmission=1.0, IOR=1.5 (glass), Roughness=0.0
│ → Add Volume Absorption for thick tinted glass
│
├── Plastic / wood / stone (dielectric, opaque)
│ → Metallic=0, IOR=1.45 (plastic) or 1.5 (most others)
│ → Roughness per finish (0.15 glossy / 0.6 matte)
│ → Coat Weight 0.5+ for varnished/lacquered surfaces
│
├── Skin / wax / marble (subsurface scattering)
│ → Metallic=0, Subsurface Weight=1.0
│ → Subsurface Radius RGB tuned per material (skin: red scatters deepest)
│
├── Cloth / fabric (sheen)
│ → Metallic=0, Sheen Weight 0.2-0.5
│ → Roughness 0.6+, Sheen Roughness 0.5
│
└── Mirror / chrome (special metal)
→ Metallic=1.0, Roughness=0.02-0.05, near-white baseReference-look handoff
参考效果匹配
If the goal is to match an original/reference image rather than make a generally attractive render, chain-load . It owns measurement of hue/saturation/value, object extent, glow/aura color, and before/after look metrics. This skill should then apply the requested material/lighting/render changes within that calibrated target.
reference-look-calibration如果目标是匹配原始/参考图像,而非制作美观的渲染效果,请调用。该工具负责测量色调/饱和度/明度、物体范围、光晕颜色以及前后效果指标。之后本技能将在已校准的目标范围内应用所需的材质/光照/渲染调整。
reference-look-calibrationRecipes (the 12 to know)
常用材质方案(必学12种)
Each recipe creates the material and assigns it to a target object. Replace with your actual object name.
'GEO-target'每个方案都会创建材质并分配给目标物体。将替换为实际的物体名称。
'GEO-target'set_input
helper — required for some Blender 5.x BSDF inputs
set_inputset_input
辅助函数——Blender 5.x某些BSDF输入所需
set_inputIn Blender 5.x's Principled BSDF v2, two inputs are flagged in the data API: and . These are reachable by iteration or index but not by string-key lookup — raises even though the input exists and its value is respected at render time. This is a Blender 5.x quirk surfaced during v0.4.0 → v0.5.0 validation.
enabled=FalseWeightSubsurface IORbsdf.inputs['Subsurface IOR']KeyErrorUse this helper whenever a recipe sets an input that might be in the disabled-but-functional state. It works on every input (enabled or not) and is forward-compatible if more inputs become disabled in future Blender versions:
python
def set_input(node, name, value):
"""Set a node input by name. Works on inputs with enabled=False
that fail string-key lookup (e.g. 'Subsurface IOR' on Blender 5.x).
"""
for inp in node.inputs:
if inp.name == name:
inp.default_value = value
return True
return FalseFor inputs that are reliably enabled (Base Color, Metallic, Roughness, IOR, Transmission Weight, Sheen Weight, etc.), direct string-key assignment still works fine — the helper is only required where an input is conditionally disabled. Recipe 9 (Skin) uses it because is one of the affected inputs.
Subsurface IOR在Blender 5.x的Principled BSDF v2中,有两个输入在数据API中被标记为:和。这些输入可通过迭代或索引访问,但无法通过字符串键查找——即使输入存在且渲染时会生效,仍会抛出。这是在v0.4.0→v0.5.0版本验证中发现的Blender 5.x特性。
enabled=FalseWeightSubsurface IORbsdf.inputs['Subsurface IOR']KeyError当方案中设置可能处于禁用但仍生效状态的输入时,请使用此辅助函数。它适用于所有输入(无论是否启用),且在未来Blender版本中若有更多输入被禁用时仍能兼容:
python
def set_input(node, name, value):
"""Set a node input by name. Works on inputs with enabled=False
that fail string-key lookup (e.g. 'Subsurface IOR' on Blender 5.x).
"""
for inp in node.inputs:
if inp.name == name:
inp.default_value = value
return True
return False对于始终处于启用状态的输入(Base Color、Metallic、Roughness、IOR、Transmission Weight、Sheen Weight等),直接使用字符串键赋值即可——仅当输入可能被禁用时才需要使用辅助函数。方案9(皮肤材质)会用到它,因为是受影响的输入之一。
Subsurface IORRecipe 1 — Brushed steel
方案1——拉丝钢
python
import bpy
mat = bpy.data.materials.new('MAT-steel_brushed')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.56, 0.57, 0.58, 1.0)
bsdf.inputs['Metallic'].default_value = 1.0
bsdf.inputs['Roughness'].default_value = 0.25
obj = bpy.data.objects['GEO-target']
if obj.data.materials:
obj.data.materials[0] = mat
else:
obj.data.materials.append(mat)
print(f"material:MAT-steel_brushed→{obj.name}")python
import bpy
mat = bpy.data.materials.new('MAT-steel_brushed')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.56, 0.57, 0.58, 1.0)
bsdf.inputs['Metallic'].default_value = 1.0
bsdf.inputs['Roughness'].default_value = 0.25
obj = bpy.data.objects['GEO-target']
if obj.data.materials:
obj.data.materials[0] = mat
else:
obj.data.materials.append(mat)
print(f"material:MAT-steel_brushed→{obj.name}")Recipe 2 — Polished gold
方案2——抛光金
python
import bpy
mat = bpy.data.materials.new('MAT-gold_polished')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (1.022, 0.782, 0.344, 1.0)
bsdf.inputs['Metallic'].default_value = 1.0
bsdf.inputs['Roughness'].default_value = 0.05
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:gold_polished')python
import bpy
mat = bpy.data.materials.new('MAT-gold_polished')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (1.022, 0.782, 0.344, 1.0)
bsdf.inputs['Metallic'].default_value = 1.0
bsdf.inputs['Roughness'].default_value = 0.05
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:gold_polished')Recipe 3 — Polished copper
方案3——抛光铜
python
import bpy
mat = bpy.data.materials.new('MAT-copper_polished')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.926, 0.721, 0.504, 1.0)
bsdf.inputs['Metallic'].default_value = 1.0
bsdf.inputs['Roughness'].default_value = 0.05
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:copper_polished')python
import bpy
mat = bpy.data.materials.new('MAT-copper_polished')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.926, 0.721, 0.504, 1.0)
bsdf.inputs['Metallic'].default_value = 1.0
bsdf.inputs['Roughness'].default_value = 0.05
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:copper_polished')Recipe 4 — Mirror chrome
方案4——镜面铬
python
import bpy
mat = bpy.data.materials.new('MAT-chrome')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.55, 0.56, 0.55, 1.0)
bsdf.inputs['Metallic'].default_value = 1.0
bsdf.inputs['Roughness'].default_value = 0.02
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:chrome')python
import bpy
mat = bpy.data.materials.new('MAT-chrome')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.55, 0.56, 0.55, 1.0)
bsdf.inputs['Metallic'].default_value = 1.0
bsdf.inputs['Roughness'].default_value = 0.02
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:chrome')Recipe 5 — Clear glass
方案5——透明玻璃
python
import bpy
mat = bpy.data.materials.new('MAT-glass_clear')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (1.0, 1.0, 1.0, 1.0)
bsdf.inputs['Metallic'].default_value = 0.0
bsdf.inputs['Roughness'].default_value = 0.0
bsdf.inputs['Transmission Weight'].default_value = 1.0
bsdf.inputs['IOR'].default_value = 1.5
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:glass_clear')python
import bpy
mat = bpy.data.materials.new('MAT-glass_clear')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (1.0, 1.0, 1.0, 1.0)
bsdf.inputs['Metallic'].default_value = 0.0
bsdf.inputs['Roughness'].default_value = 0.0
bsdf.inputs['Transmission Weight'].default_value = 1.0
bsdf.inputs['IOR'].default_value = 1.5
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:glass_clear')Recipe 6 — Frosted glass
方案6——磨砂玻璃
python
import bpy
mat = bpy.data.materials.new('MAT-glass_frosted')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (1.0, 1.0, 1.0, 1.0)
bsdf.inputs['Transmission Weight'].default_value = 1.0
bsdf.inputs['IOR'].default_value = 1.5
bsdf.inputs['Roughness'].default_value = 0.3
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:glass_frosted')python
import bpy
mat = bpy.data.materials.new('MAT-glass_frosted')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (1.0, 1.0, 1.0, 1.0)
bsdf.inputs['Transmission Weight'].default_value = 1.0
bsdf.inputs['IOR'].default_value = 1.5
bsdf.inputs['Roughness'].default_value = 0.3
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:glass_frosted')Recipe 6b — Coloured glass (wine bottle, tinted vials, decorative glass)
方案6b——有色玻璃(酒瓶、染色小瓶、装饰玻璃)
Using only to tint Principled BSDF makes coloured glass look flat or metallic. Real coloured glass has volume absorption: light passing through gets tinted by the distance it travels, so thick parts look darker and thin parts look lighter. This is the depth-based richness that makes glass read as glass.
Base ColorPattern: keep the surface near-white with slight roughness, attach a shader to the Material Output's input.
Volume AbsorptionVolumepython
import bpy
def set_input(node, name, value):
for inp in node.inputs:
if inp.name == name:
inp.default_value = value
return True
return False
mat = bpy.data.materials.new('MAT-glass_wine')
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
bsdf = nodes['Principled BSDF']
output = nodes['Material Output']仅通过为Principled BSDF着色会让有色玻璃看起来平淡或带有金属质感。真实的有色玻璃具有体积吸收特性:光线穿过玻璃时会因传播距离而被着色,因此厚的部分颜色更深,薄的部分颜色更浅。这种基于深度的层次感是玻璃呈现真实效果的关键。
Base Color制作模式:保持表面接近白色并带有轻微粗糙度,将着色器连接到Material Output的输入。
Volume AbsorptionVolumepython
import bpy
def set_input(node, name, value):
for inp in node.inputs:
if inp.name == name:
inp.default_value = value
return True
return False
mat = bpy.data.materials.new('MAT-glass_wine')
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
bsdf = nodes['Principled BSDF']
output = nodes['Material Output']Surface: near-white with tiny roughness (breaks mirror-finish look)
Surface: near-white with tiny roughness (breaks mirror-finish look)
set_input(bsdf, 'Base Color', (0.85, 0.95, 0.85, 1.0)) # near-white
set_input(bsdf, 'Metallic', 0.0)
set_input(bsdf, 'Roughness', 0.025) # critical: not 0.0; that looks metallic
set_input(bsdf, 'Transmission Weight', 1.0)
set_input(bsdf, 'IOR', 1.52) # bottle glass
set_input(bsdf, 'Base Color', (0.85, 0.95, 0.85, 1.0)) # near-white
set_input(bsdf, 'Metallic', 0.0)
set_input(bsdf, 'Roughness', 0.025) # critical: not 0.0; that looks metallic
set_input(bsdf, 'Transmission Weight', 1.0)
set_input(bsdf, 'IOR', 1.52) # bottle glass
Volume Absorption — depth-based tint
Volume Absorption — depth-based tint
volume = nodes.new('ShaderNodeVolumeAbsorption')
set_input(volume, 'Color', (0.10, 0.45, 0.18, 1.0)) # saturated wine-bottle green
set_input(volume, 'Density', 30.0) # higher = more colour over short distance
links.new(volume.outputs['Volume'], output.inputs['Volume'])
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:glass_wine_volume_absorption')
**Tuning Density**: 0–10 = very subtle tint (clear bottle); 20–40 = clear bottle-green or amber; 60–100+ = nearly opaque (cobalt-blue medicine bottle).
**Tuning Color**: invert intuition — the volume Color is what gets *removed* from passing light, so for "wine green" use saturated green; for "amber" use saturated yellow-orange.
**Other coloured-glass examples** (density values updated v0.9.0 after subject-class lighting fix):
| Name | Volume Color | Density | Surface tint |
|------|-------------|---------|---------------|
| Wine bottle (deep green) | (0.05, 0.32, 0.10) | 80 | near-white |
| Pale tinted (clear vial) | (0.10, 0.45, 0.18) | 15 | near-white |
| Champagne / pale gold | (0.85, 0.65, 0.30) | 25 | near-white |
| Cobalt blue (medicine bottle) | (0.10, 0.20, 0.85) | 80 | near-white |
| Amber / brown beer bottle | (0.80, 0.40, 0.10) | 70 | near-white |
| Ruby red | (0.85, 0.10, 0.15) | 100 | near-white |
**Density tuning rule of thumb under neutral/glass-class lighting**:
- Density 5–15 = subtle hint of colour (clear + tinted)
- Density 30–50 = medium tint visible at thin sections
- **Density 60–100 = proper wine/beer/cobalt bottle look** (recommended for hero shots)
- Density 100+ = nearly opaque (artistic / decorative)
If under standard 4:1:2 metal-class lighting the volume tint washes out (v0.7.0 issue), don't crank density to compensate — switch to `subject_class='glass'` lighting in `blender-lighting` Recipe 0a, which uses softer rim that preserves the volume colour.
**Critical**: Cycles `transmission_bounces` must be ≥ 16 (default 12) for thick or layered colour glass; otherwise rays terminate and the glass renders black on the inside.
```python
scene.cycles.transmission_bounces = 24Pitfall: don't set to the tint colour AND attach a Volume — you get double-tinting that looks wrong. Surface near-white, volume does the colour work.
Base Colorvolume = nodes.new('ShaderNodeVolumeAbsorption')
set_input(volume, 'Color', (0.10, 0.45, 0.18, 1.0)) # saturated wine-bottle green
set_input(volume, 'Density', 30.0) # higher = more colour over short distance
links.new(volume.outputs['Volume'], output.inputs['Volume'])
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:glass_wine_volume_absorption')
**密度调整**:0–10 = 非常淡的色调(透明瓶);20–40 = 透明瓶绿或琥珀色;60–100+ = 近乎不透明(钴蓝色药瓶)。
**颜色调整**:与直觉相反——体积颜色是光线穿过时会被移除的颜色,因此“酒瓶绿”使用饱和度高的绿色;“琥珀色”使用饱和度高的黄橙色。
**其他有色玻璃示例**(v0.9.0版本中针对主体类光照修复更新了密度值):
| 名称 | 体积颜色 | 密度 | 表面色调 |
|------|-------------|---------|---------------|
| 深绿色酒瓶 | (0.05, 0.32, 0.10) | 80 | 近白色 |
| 浅色染色瓶(透明小瓶) | (0.10, 0.45, 0.18) | 15 | 近白色 |
| 香槟色/浅金色 | (0.85, 0.65, 0.30) | 25 | 近白色 |
| 钴蓝色药瓶 | (0.10, 0.20, 0.85) | 80 | 近白色 |
| 琥珀色/棕色啤酒瓶 | (0.80, 0.40, 0.10) | 70 | 近白色 |
| 宝石红 | (0.85, 0.10, 0.15) | 100 | 近白色 |
**中性/玻璃类光照下的密度调整经验法则**:
- 密度5–15 = 轻微着色(透明+淡色调)
- 密度30–50 = 薄截面可见中等色调
- **密度60–100 = 酒瓶/啤酒瓶/钴蓝瓶的理想效果**(推荐用于特写镜头)
- 密度100+ = 近乎不透明(艺术/装饰用途)
如果在标准4:1:2金属类光照下体积色调变淡(v0.7.0版本问题),不要通过提高密度来补偿——在`blender-lighting`方案0a中切换为`subject_class='glass'`光照,该光照使用更柔和的边缘光以保留体积颜色。
**关键提示**:Cycles的`transmission_bounces`必须≥16(默认12),否则光线会提前终止,导致厚玻璃或多层有色玻璃内部渲染为黑色。
```python
scene.cycles.transmission_bounces = 24误区:不要同时将设置为色调颜色并添加体积吸收——这会导致双重着色,效果异常。表面应设为近白色,由体积吸收实现着色。
Base ColorRecipe 7 — Matte plastic (red)
方案7——哑光塑料(红色)
python
import bpy
mat = bpy.data.materials.new('MAT-plastic_matte_red')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.8, 0.1, 0.05, 1.0)
bsdf.inputs['Metallic'].default_value = 0.0
bsdf.inputs['Roughness'].default_value = 0.6
bsdf.inputs['IOR'].default_value = 1.45
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:plastic_matte_red')python
import bpy
mat = bpy.data.materials.new('MAT-plastic_matte_red')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.8, 0.1, 0.05, 1.0)
bsdf.inputs['Metallic'].default_value = 0.0
bsdf.inputs['Roughness'].default_value = 0.6
bsdf.inputs['IOR'].default_value = 1.45
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:plastic_matte_red')Recipe 8 — Lacquered plastic (car-paint look)
方案8——漆面塑料(汽车漆效果)
python
import bpy
mat = bpy.data.materials.new('MAT-plastic_lacquered')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.8, 0.1, 0.05, 1.0)
bsdf.inputs['Metallic'].default_value = 0.0
bsdf.inputs['Roughness'].default_value = 0.15
bsdf.inputs['IOR'].default_value = 1.45
bsdf.inputs['Coat Weight'].default_value = 0.8
bsdf.inputs['Coat Roughness'].default_value = 0.05
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:plastic_lacquered')python
import bpy
mat = bpy.data.materials.new('MAT-plastic_lacquered')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.8, 0.1, 0.05, 1.0)
bsdf.inputs['Metallic'].default_value = 0.0
bsdf.inputs['Roughness'].default_value = 0.15
bsdf.inputs['IOR'].default_value = 1.45
bsdf.inputs['Coat Weight'].default_value = 0.8
bsdf.inputs['Coat Roughness'].default_value = 0.05
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:plastic_lacquered')Recipe 9 — Skin (light tone)
方案9——浅色皮肤
Uses the helper because has on Blender 5.x and isn't reachable by string-key lookup. The other inputs work fine either way; using the helper consistently keeps the recipe safe across versions.
set_inputSubsurface IORenabled=Falsepython
import bpy
def set_input(node, name, value):
for inp in node.inputs:
if inp.name == name:
inp.default_value = value
return True
return False
mat = bpy.data.materials.new('MAT-skin_light')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
set_input(bsdf, 'Base Color', (0.85, 0.65, 0.55, 1.0))
set_input(bsdf, 'Metallic', 0.0)
set_input(bsdf, 'Roughness', 0.4)
set_input(bsdf, 'Subsurface Weight', 1.0)
set_input(bsdf, 'Subsurface Radius', (1.0, 0.2, 0.1))
set_input(bsdf, 'Subsurface IOR', 1.4) # ← string-key fails on Blender 5.x; helper bypasses it
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:skin_light')使用辅助函数,因为在Blender 5.x中的,无法通过字符串键访问。其他输入无论是否使用辅助函数均可正常工作;统一使用辅助函数可确保方案在不同版本中兼容。
set_inputSubsurface IORenabled=Falsepython
import bpy
def set_input(node, name, value):
for inp in node.inputs:
if inp.name == name:
inp.default_value = value
return True
return False
mat = bpy.data.materials.new('MAT-skin_light')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
set_input(bsdf, 'Base Color', (0.85, 0.65, 0.55, 1.0))
set_input(bsdf, 'Metallic', 0.0)
set_input(bsdf, 'Roughness', 0.4)
set_input(bsdf, 'Subsurface Weight', 1.0)
set_input(bsdf, 'Subsurface Radius', (1.0, 0.2, 0.1))
set_input(bsdf, 'Subsurface IOR', 1.4) # ← string-key fails on Blender 5.x; helper bypasses it
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:skin_light')Recipe 10 — Velvet / cloth with sheen
方案10——丝绒/带光泽织物
python
import bpy
mat = bpy.data.materials.new('MAT-velvet_red')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.6, 0.0, 0.1, 1.0)
bsdf.inputs['Roughness'].default_value = 0.9
bsdf.inputs['Sheen Weight'].default_value = 0.5
bsdf.inputs['Sheen Roughness'].default_value = 0.5
bsdf.inputs['Sheen Tint'].default_value = (0.8, 0.6, 0.6, 1.0)
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:velvet_red')python
import bpy
mat = bpy.data.materials.new('MAT-velvet_red')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.6, 0.0, 0.1, 1.0)
bsdf.inputs['Roughness'].default_value = 0.9
bsdf.inputs['Sheen Weight'].default_value = 0.5
bsdf.inputs['Sheen Roughness'].default_value = 0.5
bsdf.inputs['Sheen Tint'].default_value = (0.8, 0.6, 0.6, 1.0)
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:velvet_red')Recipe 11 — Soft silicone
方案11——软硅胶
python
import bpy
mat = bpy.data.materials.new('MAT-silicone')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.65, 0.63, 0.60, 1.0)
bsdf.inputs['Metallic'].default_value = 0.0
bsdf.inputs['Roughness'].default_value = 0.7
bsdf.inputs['IOR'].default_value = 1.4
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:silicone')python
import bpy
mat = bpy.data.materials.new('MAT-silicone')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.65, 0.63, 0.60, 1.0)
bsdf.inputs['Metallic'].default_value = 0.0
bsdf.inputs['Roughness'].default_value = 0.7
bsdf.inputs['IOR'].default_value = 1.4
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:silicone')Recipe 11b — Emission (light-emitting mesh, e.g. lamp bulb, neon sign, screen glow)
方案11b——自发光材质(发光网格,如灯泡、霓虹灯、屏幕光晕)
Emission is a separate shader from Principled BSDF — replace the BSDF entirely with a and connect to Material Output's Surface input. The mesh becomes a light source itself (contributes to scene illumination in Cycles).
ShaderNodeEmissionpython
import bpy
mat = bpy.data.materials.new('MAT-bulb_emission')
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links自发光是独立于Principled BSDF的着色器——将默认的BSDF替换为并连接到Material Output的Surface输入。网格本身会成为光源(在Cycles中为场景提供照明)。
ShaderNodeEmissionpython
import bpy
mat = bpy.data.materials.new('MAT-bulb_emission')
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.linksRemove the default Principled BSDF
Remove the default Principled BSDF
for n in list(nodes):
if n.type == 'BSDF_PRINCIPLED':
nodes.remove(n)
emission = nodes.new('ShaderNodeEmission')
emission.inputs['Color'].default_value = (1.0, 0.92, 0.78, 1.0) # warm tungsten
emission.inputs['Strength'].default_value = 1500.0 # see strength guide below
output = nodes['Material Output']
links.new(emission.outputs['Emission'], output.inputs['Surface'])
bpy.data.objects['GEO-bulb'].data.materials.append(mat)
print('material:bulb_emission')
undefinedfor n in list(nodes):
if n.type == 'BSDF_PRINCIPLED':
nodes.remove(n)
emission = nodes.new('ShaderNodeEmission')
emission.inputs['Color'].default_value = (1.0, 0.92, 0.78, 1.0) # warm tungsten
emission.inputs['Strength'].default_value = 1500.0 # see strength guide below
output = nodes['Material Output']
links.new(emission.outputs['Emission'], output.inputs['Surface'])
bpy.data.objects['GEO-bulb'].data.materials.append(mat)
print('material:bulb_emission')
undefinedStrength tuning — critical for mesh emitters
强度调整——发光网格的关键
Mesh emission's effective brightness scales with mesh surface area, not just the Strength value. A small sphere at Strength=50 is barely visible; the same sphere at Strength=1500 lights a desk like a real bulb. Use this table for ballpark values:
| Mesh size | Bulb-equivalent | Strength |
|---|---|---|
| 1-2 cm sphere (Edison bulb) | 40W warm bulb | 800-1500 |
| 3-5 cm sphere (LED globe) | 60-100W bulb | 1500-3000 |
| 10×10 cm flat panel (LED panel) | Indoor light panel | 100-300 |
| 100×30 cm strip (neon tube) | Neon sign | 50-150 |
| Large window plane (sky simulation) | Daylight | 5-20 |
Rule of thumb: smaller surface area → higher Strength. Doubling sphere radius reduces required Strength by ~4× (inverse surface-area scaling).
Use to set colour temperature:
(R, G, B)- Tungsten (3200K) —
(1.0, 0.85, 0.6) - LED warm (3000K) —
(1.0, 0.8, 0.6) - Daylight (5500K) —
(1.0, 1.0, 1.0) - Cool fluorescent (4500K) —
(0.95, 0.95, 1.0)
网格自发光的实际亮度与网格表面积成正比,而非仅取决于Strength值。一个小球体设置Strength=50几乎不可见;同样的球体设置Strength=1500则能像真实灯泡一样照亮桌面。使用下表作为参考值:
| 网格尺寸 | 等效灯泡 | 强度值 |
|---|---|---|
| 1-2厘米球体(爱迪生灯泡) | 40W暖光灯泡 | 800-1500 |
| 3-5厘米球体(LED球泡) | 60-100W灯泡 | 1500-3000 |
| 10×10厘米平板(LED面板) | 室内照明面板 | 100-300 |
| 100×30厘米灯带(霓虹灯管) | 霓虹灯牌 | 50-150 |
| 大型窗户平面(天空模拟) | 日光 | 5-20 |
经验法则:表面积越小→强度值越高。球体半径翻倍,所需强度值约减少4倍(与表面积成反比)。
使用设置色温:
(R, G, B)- 钨丝灯(3200K)——
(1.0, 0.85, 0.6) - 暖光LED(3000K)——
(1.0, 0.8, 0.6) - 日光(5500K)——
(1.0, 1.0, 1.0) - 冷荧光灯(4500K)——
(0.95, 0.95, 1.0)
Lamp shade — separate flipped-normal interior
灯罩——单独的翻转法线内部网格
If the bulb sits inside a shade, the shade's INSIDE surface needs to be bright matte (white) so it reflects bulb light realistically. Single-mesh shades only show the OUTSIDE material. Solution: duplicate the shade mesh, flip normals, scale 97% smaller, apply bright-white material. This gives proper interior-glow when the bulb illuminates the shade.
python
import bpy如果灯泡位于灯罩内部,灯罩的内表面需要设置为明亮的哑光(白色)材质,以真实反射灯泡光线。单一网格灯罩仅显示外表面材质。解决方案:复制灯罩网格,翻转法线,缩小至97%,应用亮白色材质。这样当灯泡照亮灯罩时,能呈现出真实的内部光晕效果。
python
import bpyAssuming shade
is the outer cone with the dark exterior material already applied
shadeAssuming shade
is the outer cone with the dark exterior material already applied
shadeshade = bpy.data.objects['GEO-lamp_shade']
bpy.ops.object.select_all(action='DESELECT')
shade.select_set(True); bpy.context.view_layer.objects.active = shade
bpy.ops.object.duplicate()
shade_in = bpy.context.active_object
shade_in.name = shade.name + '_interior'
shade = bpy.data.objects['GEO-lamp_shade']
bpy.ops.object.select_all(action='DESELECT')
shade.select_set(True); bpy.context.view_layer.objects.active = shade
bpy.ops.object.duplicate()
shade_in = bpy.context.active_object
shade_in.name = shade.name + '_interior'
Flip normals so the inside surface faces inward
Flip normals so the inside surface faces inward
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.flip_normals()
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.flip_normals()
bpy.ops.object.mode_set(mode='OBJECT')
Bright white interior
Bright white interior
mat_in = bpy.data.materials.new('MAT-shade_interior')
mat_in.use_nodes = True
b = mat_in.node_tree.nodes['Principled BSDF']
b.inputs['Base Color'].default_value = (0.95, 0.93, 0.88, 1.0)
b.inputs['Roughness'].default_value = 0.5
shade_in.data.materials.clear()
shade_in.data.materials.append(mat_in)
shade_in.scale = (0.97, 0.97, 0.97)
print('material:shade_interior_white')
undefinedmat_in = bpy.data.materials.new('MAT-shade_interior')
mat_in.use_nodes = True
b = mat_in.node_tree.nodes['Principled BSDF']
b.inputs['Base Color'].default_value = (0.95, 0.93, 0.88, 1.0)
b.inputs['Roughness'].default_value = 0.5
shade_in.data.materials.clear()
shade_in.data.materials.append(mat_in)
shade_in.scale = (0.97, 0.97, 0.97)
print('material:shade_interior_white')
undefinedRecipe 12 — Procedural wood (10 nodes)
方案12——程序化木纹(10个节点)
python
import bpy
mat = bpy.data.materials.new('MAT-wood_procedural')
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
bsdf = nodes['Principled BSDF']python
import bpy
mat = bpy.data.materials.new('MAT-wood_procedural')
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
bsdf = nodes['Principled BSDF']Texture coordinate
Texture coordinate
tex_coord = nodes.new('ShaderNodeTexCoord')
tex_coord.location = (-800, 0)
tex_coord = nodes.new('ShaderNodeTexCoord')
tex_coord.location = (-800, 0)
Mapping
Mapping
mapping = nodes.new('ShaderNodeMapping')
mapping.location = (-600, 0)
mapping.inputs['Scale'].default_value = (3, 3, 3)
mapping = nodes.new('ShaderNodeMapping')
mapping.location = (-600, 0)
mapping.inputs['Scale'].default_value = (3, 3, 3)
Wave (the grain)
Wave (the grain)
wave = nodes.new('ShaderNodeTexWave')
wave.location = (-400, 100)
wave.wave_type = 'BANDS'
wave.bands_direction = 'X'
wave.inputs['Scale'].default_value = 5.0
wave.inputs['Distortion'].default_value = 4.0
wave = nodes.new('ShaderNodeTexWave')
wave.location = (-400, 100)
wave.wave_type = 'BANDS'
wave.bands_direction = 'X'
wave.inputs['Scale'].default_value = 5.0
wave.inputs['Distortion'].default_value = 4.0
Noise (variation)
Noise (variation)
noise = nodes.new('ShaderNodeTexNoise')
noise.location = (-400, -100)
noise.inputs['Scale'].default_value = 8.0
noise = nodes.new('ShaderNodeTexNoise')
noise.location = (-400, -100)
noise.inputs['Scale'].default_value = 8.0
Mix wave + noise
Mix wave + noise
mix = nodes.new('ShaderNodeMixRGB')
mix.location = (-200, 0)
mix.blend_type = 'MULTIPLY'
mix.inputs[0].default_value = 0.5
mix = nodes.new('ShaderNodeMixRGB')
mix.location = (-200, 0)
mix.blend_type = 'MULTIPLY'
mix.inputs[0].default_value = 0.5
ColorRamp (tonal range)
ColorRamp (tonal range)
ramp = nodes.new('ShaderNodeValToRGB')
ramp.location = (0, 0)
ramp.color_ramp.elements[0].color = (0.15, 0.07, 0.03, 1.0) # dark wood
ramp.color_ramp.elements[1].color = (0.6, 0.35, 0.18, 1.0) # light wood
ramp = nodes.new('ShaderNodeValToRGB')
ramp.location = (0, 0)
ramp.color_ramp.elements[0].color = (0.15, 0.07, 0.03, 1.0) # dark wood
ramp.color_ramp.elements[1].color = (0.6, 0.35, 0.18, 1.0) # light wood
Wire
Wire
links.new(tex_coord.outputs['Generated'], mapping.inputs['Vector'])
links.new(mapping.outputs['Vector'], wave.inputs['Vector'])
links.new(mapping.outputs['Vector'], noise.inputs['Vector'])
links.new(wave.outputs['Color'], mix.inputs[1])
links.new(noise.outputs['Color'], mix.inputs[2])
links.new(mix.outputs['Color'], ramp.inputs['Fac'])
links.new(ramp.outputs['Color'], bsdf.inputs['Base Color'])
bsdf.inputs['Roughness'].default_value = 0.7
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:wood_procedural')
**Note**: procedural materials don't export to glTF. For web/game export, bake to image textures first.links.new(tex_coord.outputs['Generated'], mapping.inputs['Vector'])
links.new(mapping.outputs['Vector'], wave.inputs['Vector'])
links.new(mapping.outputs['Vector'], noise.inputs['Vector'])
links.new(wave.outputs['Color'], mix.inputs[1])
links.new(noise.outputs['Color'], mix.inputs[2])
links.new(mix.outputs['Color'], ramp.inputs['Fac'])
links.new(ramp.outputs['Color'], bsdf.inputs['Base Color'])
bsdf.inputs['Roughness'].default_value = 0.7
bpy.data.objects['GEO-target'].data.materials.append(mat)
print('material:wood_procedural')
**注意**:程序化材质无法导出到glTF。如需用于网页/游戏导出,请先烘焙为图像纹理。PBR values reference
PBR参数参考
For exact F0 reflectance values for any metal: physicallybased.info — covers 50+ materials. The recipes above use values from this database.
如需获取任何金属的精确F0反射率值,请访问physicallybased.info——涵盖50多种材质。上述方案使用的参数均来自该数据库。
Material naming convention
材质命名规范
MAT-{purpose}_{subtype}_{finish}MAT-frame_metal_brushedMAT-lens_glass_dark_mirrorMAT-pad_silicone_warm_grayMAT-wood_oak_glossy
Avoid , . Always rename.
Material.001Material.027MAT-{用途}_{子类型}_{质感}MAT-frame_metal_brushedMAT-lens_glass_dark_mirrorMAT-pad_silicone_warm_grayMAT-wood_oak_glossy
避免使用、这类命名。务必重命名。
Material.001Material.027Common pitfalls
常见误区
| Symptom | Fix |
|---|---|
| "Plasticky" metals | Metallic must be exactly 0 or 1 |
| Black metal | Base color too dark; metals reflect 30–100%; keep ≥0.5 sRGB |
| Roughness 0 = artifacts | Use 0.01–0.05 minimum |
| Glass renders black | Increase Cycles transmission bounces (Recipe section 11-rendering) |
| Material not visible in glTF | Procedural shader; bake to image first |
| Normal map looks wrong | Set image texture to "Non-Color" color space |
| sRGB on roughness map | Set image texture to "Non-Color" |
| Blender 5.x quirk: input has |
| 症状 | 解决方法 |
|---|---|
| 金属材质“塑料感” | 金属度必须设为0或1 |
| 金属材质渲染为黑色 | 基础颜色过暗;金属反射率为30–100%;保持sRGB值≥0.5 |
| 粗糙度设为0出现 artifacts | 使用0.01–0.05的最小值 |
| 玻璃渲染为黑色 | 增加Cycles的透射反弹次数(方案11-渲染部分) |
| 材质在glTF中不可见 | 使用了程序化着色器;先烘焙为图像纹理 |
| 法线贴图显示异常 | 将图像纹理设置为“非颜色”色彩空间 |
| 粗糙度贴图使用sRGB色彩空间 | 将图像纹理设置为“非颜色” |
| Blender 5.x特性:输入 |
When to load references/overview.md
references/overview.md何时加载references/overview.md
references/overview.mdLoad when:
- The recipe you need isn't in the 12 above
- You need anisotropy (brushed metal direction), volume absorption (tinted thick glass), or advanced shader-node combos
- The user asks for material variation across one mesh (Mix Shader patterns)
- You're baking procedural to image textures for export
The reference covers: full Principled BSDF parameter map, 50+ materials database link, procedural texture combinations (Voronoi, Wave, Noise), Sheen + Subsurface deep-dives, and bake-for-export workflow.
在以下情况加载:
- 所需方案不在上述12种之内
- 需要各向异性(拉丝金属方向)、体积吸收(厚有色玻璃)或高级着色器节点组合
- 用户要求单个网格上的材质变化(混合着色器模式)
- 将程序化纹理烘焙为图像纹理用于导出
参考文档涵盖:完整的Principled BSDF参数映射、50+材质数据库链接、程序化纹理组合(Voronoi、Wave、Noise)、光泽层+次表面散射深度解析,以及导出烘焙工作流。