blender-lighting — Claude Code skill: what it does, how to install
Configures studio, outdoor, and cinematic lighting in Blender scenes using automated Python recipes via MCP.
npx skills add RobLe3/cc-blender-skill --skill blender-lighting -a claude-codeWhat blender-lighting does
The skill manages lighting setups in Blender by calling tools on mcp__blender or mcp__blender_official. It defaults to AREA lights for natural soft shadows. It also supports SUN, POINT, SPOT, and HDRI world environments. Helpers like aim_at and compute_scene_bbox_center point lamps toward specific meshes or calculated scene bounding boxes.
A built-in decision tree matches setups to moods, covering three-point layouts, noir spotlights, or sun-lit interiors. Subject material profiles adjust light ratios directly. Glass receives a softer rim to protect volume tint. Wood and skin use warmer color temperatures between 3000K and 3500K.
Operation requires an active Blender MCP backend capable of executing Python commands via bpy.
What it helps with
- set up three-point lighting tuned to specific surface materials
- configure outdoor sun and HDRI environment lighting
- aim lamps at arbitrary objects using the aim_at helper
- build dramatic single-spotlight lighting for noir scenes
Example prompts for the agent
- Set up three-point studio lighting for a glass bottle
- Make this scene dramatic with a high-angle spotlight and no fill
- Add outdoor lighting with a sun lamp and an HDRI background
How to install blender-lighting
1Skills CLI (Vercel)
npx skills add RobLe3/cc-blender-skill --skill blender-lighting -a claude-code2Manually: put the files in place
~/.claude/skills/blender-lighting/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/blender-lighting/
1Skills CLI (Vercel)
npx skills add RobLe3/cc-blender-skill --skill blender-lighting -a codex2Manually: put the files in place
.agents/skills/blender-lighting/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add RobLe3/cc-blender-skill --skill blender-lighting -a cursor2Manually: put the files in place
.cursor/skills/blender-lighting/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install RobLe3/cc-blender-skill blender-lighting2Manually: put the files in place
.github/skills/blender-lighting/SKILL.md1Skills CLI (Vercel)
npx skills add RobLe3/cc-blender-skill --skill blender-lighting -a gemini-cli2Platform CLI
gemini skills install https://github.com/RobLe3/cc-blender-skill --path plugin/skills/blender-lightingManually: put the files in place
.devin/skills/blender-lighting/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add RobLe3/cc-blender-skill --skill blender-lighting -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about blender-lighting
How to install blender-lighting in Claude Code?
Run npx skills add RobLe3/cc-blender-skill --skill blender-lighting -a claude-code. You can also place the file manually at ~/.claude/skills/blender-lighting/SKILL.md.
What does blender-lighting do?
It generates and runs Blender Python scripts that set up scene lamps, HDRI maps, light positions, and color temperatures.
Why does the skill tune lighting per subject class?
Materials react differently to illumination: strong rim lights wash out glass volume tints, while wood and skin look better under warmer kelvin ratings.
Source text
SKILL.md · MIT
---
name: blender-lighting
description: Light Blender scenes professionally — three-point setups, HDRI environments, studio/cinematic/dramatic configurations, light groups, color temperature, soft vs hard shadows. Use whenever the user asks to "light the scene", "set up lighting", "make it look cinematic / dramatic / studio / outdoor / sunset", "add a key light", "use HDRI", or any lighting-related request. Make sure to use this skill even if the user does not say "light" — also covers "make it look professional", "studio shot", "moody atmosphere", "golden hour", "rim light". Pairs with blender-materials (lighting reveals materials) and blender-cameras (lighting + composition together = shot).
allowed-tools: Read Bash mcp__blender__execute_blender_code mcp__blender__get_scene_info mcp__blender__get_object_info mcp__blender__get_objects_summary mcp__blender__get_object_detail_summary mcp__blender__render_viewport_to_path mcp__blender__search_api_docs mcp__blender_official__execute_blender_code mcp__blender_official__get_objects_summary mcp__blender_official__get_object_detail_summary mcp__blender_official__render_viewport_to_path mcp__blender_official__search_api_docs
---
## MCP backend
Use when: Any lighting setup or modification in Blender. Includes HDRI/environment lighting and individual lamp placement.
Before the first Blender call, read [../text-to-blender/references/mcp-backends.md](../text-to-blender/references/mcp-backends.md). Prefer official MCP for shared capabilities; preserve the selected backend for the whole task. Tool names in recipes are client/legacy examples: map them through that reference and its agent-host guide.
# Blender Lighting
Light scenes the way pros do: with structure, intent, and physically reasonable values.
## The five light types
| Type | Behavior | Use for |
|------|----------|---------|
| **AREA** | Light from a rectangular surface; soft shadows automatic | 80% of cases. Window, softbox, fluorescent panel |
| **SUN** | Parallel rays from "infinity" | Sunlight, moonlight, distant directional |
| **POINT** | Omnidirectional from a point | Bulbs, candles, small omnis |
| **SPOT** | Cone with falloff | Stage lights, headlights, focused beams |
| **HDRI/World** | 360° environment image | Realistic ambient, outdoor, product photography |
**Default rule**: Use **Area lights** for almost everything except the sun. Soft shadows come for free.
## Decision tree
```
What's the mood?
├── Studio / commercial → Three-point lighting (key+fill+rim) + HDRI fill 0.3
├── Outdoor / sunlit → Sun + HDRI sky environment
├── Indoor cinematic → Sun through window + HDRI low + practicals (lamps as Point)
├── Dramatic / noir → Single Spot at high angle, no fill
├── Stylized / cartoon → Three-point with high contrast + saturated key color
└── Unsure → Three-point with HDRI grounding (works for 90% of cases)
```
## Reference-look handoff
If the goal is to match an original/reference image rather than make a generally attractive render, chain-load `reference-look-calibration`. 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.
## Recipes
### Helper: `aim_at(light, target)` — required for subject-aware lighting
Recipe 1 below positions lights at fixed world coords with hardcoded rotations. That's fine for a generic 1m subject at the world origin. For ANY other subject (small jewellery, tall sword, sprawling building), you need lights aimed at the subject. Use this helper:
```python
from mathutils import Vector
def aim_at(light_obj, target):
"""Aim a light at a world-space target.
target may be a Vector or a tuple/list (x, y, z) or a Blender object.
"""
target_pos = Vector(target.location) if hasattr(target, 'location') else Vector(target)
direction = (target_pos - light_obj.location).normalized()
light_obj.rotation_euler = direction.to_track_quat('-Z', 'Y').to_euler()
```
### Helper: scene-aware light positioning
```python
from mathutils import Vector
def compute_scene_bbox_center(meshes):
"""Average bbox center over a list of mesh objects (world space)."""
import bpy
deps = bpy.context.evaluated_depsgraph_get()
all_verts = []
for o in meshes:
eval_obj = o.evaluated_get(deps)
em = eval_obj.to_mesh()
for v in em.vertices:
all_verts.append(o.matrix_world @ v.co)
eval_obj.to_mesh_clear()
xs = [v.x for v in all_verts]
ys = [v.y for v in all_verts]
zs = [v.z for v in all_verts]
center = Vector(((min(xs)+max(xs))/2, (min(ys)+max(ys))/2, (min(zs)+max(zs))/2))
extent = max(max(xs)-min(xs), max(ys)-min(ys), max(zs)-min(zs))
return center, extent
```
### Recipe 0a — Subject-CLASS-aware three-point lighting (use this for orchestrator E2E)
Generic three-point lighting (Recipe 0b below) places lights at fixed energy ratios. That works for opaque subjects (chair, sword) but breaks for **glass** (rim washes out volume tint) and is too cool for **wood** (loses warmth).
Pass a `subject_class` hint to tune the setup:
| Class | Key:Fill:Rim ratio | Key color temp | Reason |
|-------|--------------------|----------------|--------|
| `'metal'` | 4:1:2 (default) | warm 3200K | Standard 3-point reads metallic well |
| `'glass'` | 3:1:1.2 | neutral 5500K | Soft rim — strong rim WASHES OUT volume tint; brighter fill so transmission shows colour |
| `'wood'` | 4:1:1.5 | warm 3000K | Warmer key brings out wood tones; less rim (wood doesn't need silhouette boost) |
| `'fabric'` | 3:1:0.5 | neutral 5500K | Soft and balanced; sheen reads in fill light |
| `'skin'` | 4:1:1 | warm 3500K | Warm key for healthy tone; subtle rim (avoids harsh edges on faces) |
| `'product'` | 5:1:1.5 | neutral 5000K | Higher contrast; commercial/clean look |
| (unspecified) | falls back to Recipe 0b (default) | warm 3200K | |
```python
import bpy, math
from mathutils import Vector
def aim_at(light_obj, target):
target_pos = Vector(target.location) if hasattr(target, 'location') else Vector(target)
direction = (target_pos - light_obj.location).normalized()
light_obj.rotation_euler = direction.to_track_quat('-Z', 'Y').to_euler()
def apply_three_point(subject_class='metal'):
"""Configure 3-point lighting with subject-class-aware ratios.
subject_class: 'metal' | 'glass' | 'wood' | 'fabric' | 'skin' | 'product' | 'metal' (default)
"""
profiles = {
'metal': dict(ratio=(4.0, 1.0, 2.0), key_color=(1.0, 0.95, 0.85), fill_color=(0.85, 0.9, 1.0), rim_color=(0.7, 0.85, 1.0)),
'glass': dict(ratio=(3.0, 1.0, 1.2), key_color=(1.0, 0.98, 0.95), fill_color=(0.95, 0.95, 1.0), rim_color=(0.95, 0.95, 1.0)),
'wood': dict(ratio=(4.0, 1.0, 1.5), key_color=(1.0, 0.92, 0.78), fill_color=(0.95, 0.95, 1.0), rim_color=(0.85, 0.92, 1.0)),
'fabric': dict(ratio=(3.0, 1.0, 0.5), key_color=(1.0, 0.97, 0.92), fill_color=(0.92, 0.95, 1.0), rim_color=(0.95, 0.95, 1.0)),
'skin': dict(ratio=(4.0, 1.0, 1.0), key_color=(1.0, 0.93, 0.82), fill_color=(0.95, 0.96, 1.0), rim_color=(0.92, 0.92, 1.0)),
'product': dict(ratio=(5.0, 1.0, 1.5), key_color=(1.0, 0.98, 0.95), fill_color=(0.98, 0.98, 1.0), rim_color=(0.98, 0.98, 1.0)),
}
p = profiles.get(subject_class, profiles['metal'])
# Compute scene bbox
subject_meshes = [o for o in bpy.data.objects if o.type == 'MESH' and o.name.startswith('GEO-')]
deps = bpy.context.evaluated_depsgraph_get()
all_verts = []
for o in subject_meshes:
eo = o.evaluated_get(deps); em = eo.to_mesh()
for v in em.vertices: all_verts.append(o.matrix_world @ v.co)
eo.to_mesh_clear()
xs = [v.x for v in all_verts]; ys = [v.y for v in all_verts]; zs = [v.z for v in all_verts]
center = Vector(((min(xs)+max(xs))/2, (min(ys)+max(ys))/2, (min(zs)+max(zs))/2))
biggest = max(max(zs)-min(zs), max(xs)-min(xs))
light_dist = max(biggest * 1.5, 1.0)
# Energy scales with distance²
base_energy = 100 * (light_dist / 1.5) ** 2
key_e, fill_e, rim_e = (base_energy * r for r in p['ratio'])
# Remove existing lights
for o in list(bpy.data.objects):
if o.type == 'LIGHT' and (o.name.startswith('LGT-key') or o.name.startswith('LGT-fill') or o.name.startswith('LGT-rim')):
bpy.data.objects.remove(o, do_unlink=True)
# KEY (warm, front-right above)
key = bpy.data.objects.new('LGT-key', bpy.data.lights.new('LGT-key', type='AREA'))
key.data.energy = key_e; key.data.size = 0.5; key.data.color = p['key_color']
bpy.context.collection.objects.link(key)
key.location = (center.x + light_dist*0.7, center.y - light_dist*0.7, center.z + light_dist*0.5)
aim_at(key, center)
# FILL (cool, opposite, weaker)
fill = bpy.data.objects.new('LGT-fill', bpy.data.lights.new('LGT-fill', type='AREA'))
fill.data.energy = fill_e; fill.data.size = 1.0; fill.data.color = p['fill_color']
bpy.context.collection.objects.link(fill)
fill.location = (center.x - light_dist*0.7, center.y - light_dist*0.5, center.z + light_dist*0.3)
aim_at(fill, center)
# RIM
rim_type = 'AREA' if subject_class == 'glass' else 'SPOT'
rim = bpy.data.objects.new('LGT-rim', bpy.data.lights.new('LGT-rim', type=rim_type))
rim.data.energy = rim_e; rim.data.color = p['rim_color']
if rim_type == 'AREA':
rim.data.size = 1.5 # larger soft-source for glass
else:
rim.data.spot_size = math.radians(50)
bpy.context.collection.objects.link(rim)
rim.location = (center.x, center.y + light_dist, center.z + light_dist*0.5)
aim_at(rim, center)
print(f"lighting:{subject_class} key:fill:rim={p['ratio']} dist={light_dist:.2f}m")
# Usage:
# apply_three_point('glass') # for the wine bottle
# apply_three_point('wood') # for the chair
# apply_three_point('metal') # for the sword (or omit; 'metal' is default)
```
### Recipe 0b — Three-point lighting **aimed at a subject** (generic, no class hint)
Use this instead of Recipe 1 when you have a specific subject but the class doesn't matter. Lights are placed proportionally to the subject's largest dimension.
```python
import bpy, math
from mathutils import Vector
def aim_at(light_obj, target):
target_pos = Vector(target.location) if hasattr(target, 'location') else Vector(target)
direction = (target_pos - light_obj.location).normalized()
light_obj.rotation_euler = direction.to_track_quat('-Z', 'Y').to_euler()
# Determine subject and its scale
subject_meshes = [o for o in bpy.data.objects if o.type == 'MESH' and o.name.startswith('GEO-')]
deps = bpy.context.evaluated_depsgraph_get()
all_verts = []
for o in subject_meshes:
eo = o.evaluated_get(deps); em = eo.to_mesh()
for v in em.vertices:
all_verts.append(o.matrix_world @ v.co)
eo.to_mesh_clear()
xs = [v.x for v in all_verts]; ys = [v.y for v in all_verts]; zs = [v.z for v in all_verts]
center = Vector(((min(xs)+max(xs))/2, (min(ys)+max(ys))/2, (min(zs)+max(zs))/2))
extent = max(max(xs)-min(xs), max(ys)-min(ys), max(zs)-min(zs))
light_dist = max(extent * 1.5, 1.0)
# Energy values scale roughly inversely with squared distance from subject — recipe targets
# physically reasonable values for a ~1m subject at ~1.5m light distance.
key_energy = 100 * (light_dist / 1.5) ** 2
fill_energy = key_energy * 0.3
rim_energy = key_energy * 0.8
# KEY (warm, front-right above)
key = bpy.data.objects.new('LGT-key', bpy.data.lights.new('LGT-key', type='AREA'))
key.data.energy = key_energy; key.data.size = 0.5; key.data.color = (1.0, 0.95, 0.85)
bpy.context.collection.objects.link(key)
key.location = (center.x + light_dist * 0.7, center.y - light_dist * 0.7, center.z + light_dist * 0.5)
aim_at(key, center)
# FILL (cool, opposite, weaker)
fill = bpy.data.objects.new('LGT-fill', bpy.data.lights.new('LGT-fill', type='AREA'))
fill.data.energy = fill_energy; fill.data.size = 1.0; fill.data.color = (0.85, 0.9, 1.0)
bpy.context.collection.objects.link(fill)
fill.location = (center.x - light_dist * 0.7, center.y - light_dist * 0.5, center.z + light_dist * 0.3)
aim_at(fill, center)
# RIM (cool, behind, separates subject from BG)
rim = bpy.data.objects.new('LGT-rim', bpy.data.lights.new('LGT-rim', type='SPOT'))
rim.data.energy = rim_energy; rim.data.color = (0.7, 0.85, 1.0); rim.data.spot_size = math.radians(50)
bpy.context.collection.objects.link(rim)
rim.location = (center.x, center.y + light_dist, center.z + light_dist * 0.5)
aim_at(rim, center)
print(f'lighting:three_point_aimed center={tuple(round(v,2) for v in center)} extent={extent:.2f}m dist={light_dist:.2f}m')
```
### Recipe 0c — Practical lighting (scene contains its own emissive light source)
When the subject IS or CONTAINS a light source — desk lamp with bulb, candle with flame, monitor with glowing screen, neon sign — the scene needs a different setup:
1. **Make the world background dark** (Strength 0.10–0.20). Otherwise the bulb's contribution is drowned out by ambient.
2. **Reduce or remove the standard 3-point fill/rim**. The practical light should dominate.
3. **Keep a subtle ambient fill** (8-15W Area light from camera direction) so the lamp body itself is visible — pure practical-only renders make the lamp shape silhouette into shadow.
4. **Tune emission strength HIGH** for small mesh emitters (see `blender-materials` Recipe 11b — bulb spheres need Strength 800-3000 to read like real bulbs).
5. **Cycles `max_bounces` ≥ 16** for proper interior-shade lighting — the bulb's light needs to bounce inside the shade and out through the opening.
```python
import bpy
from mathutils import Vector
def aim_at(light_obj, target):
target_pos = Vector(target.location) if hasattr(target, 'location') else Vector(target)
direction = (target_pos - light_obj.location).normalized()
light_obj.rotation_euler = direction.to_track_quat('-Z', 'Y').to_euler()
# Dim world (let the practical dominate)
world = bpy.context.scene.world
world.use_nodes = True
nodes = world.node_tree.nodes
for n in list(nodes): nodes.remove(n)
output = nodes.new('ShaderNodeOutputWorld')
bg = nodes.new('ShaderNodeBackground')
bg.inputs['Color'].default_value = (0.02, 0.02, 0.03, 1.0)
bg.inputs['Strength'].default_value = 0.15
world.node_tree.links.new(bg.outputs['Background'], output.inputs['Surface'])
# Single subtle ambient fill from camera direction
fill = bpy.data.objects.new('LGT-ambient_fill', bpy.data.lights.new('LGT-ambient_fill', type='AREA'))
fill.data.energy = 8; fill.data.size = 1.0; fill.data.color = (0.85, 0.9, 1.0)
bpy.context.collection.objects.link(fill)
fill.location = (0.5, -0.8, 0.5)
aim_at(fill, Vector((0, 0, 0.3)))
# Cycles bounces
scene = bpy.context.scene
scene.cycles.max_bounces = 16
print('lighting:practical_setup')
```
The practical light's emission shader (mesh-emissive bulb / candle flame / etc.) handles the rest. Scene appears like real photography of an illuminated subject — dark surroundings, warm pool of light from the practical, subject silhouette gently filled.
**Validation proof**: see `text-to-blender/assets/v1.1.0-validation/desk_lamp_emission.webp` for what this setup produces (desk lamp with visible bulb glow, warm light pool on desk surface, lamp body visible against the dark scene).
### Recipe 1 — Three-point lighting (the canonical setup)
```python
import bpy, math
# KEY LIGHT (warm, front-right)
key_data = bpy.data.lights.new('LGT-key', type='AREA')
key_data.energy = 1000
key_data.size = 1.0
key_data.color = (1.0, 0.95, 0.85) # warm tungsten ~3200K
key = bpy.data.objects.new('LGT-key', key_data)
bpy.context.collection.objects.link(key)
key.location = (3, -3, 3.5)
key.rotation_euler = (math.radians(35), math.radians(45), 0)
# FILL LIGHT (cool, front-left, weaker)
fill_data = bpy.data.lights.new('LGT-fill', type='AREA')
fill_data.energy = 300
fill_data.size = 2.0
fill_data.color = (0.85, 0.9, 1.0) # cool sky ~6500K
fill = bpy.data.objects.new('LGT-fill', fill_data)
bpy.context.collection.objects.link(fill)
fill.location = (-3, -2, 2.5)
fill.rotation_euler = (math.radians(50), math.radians(-45), 0)
# BACK / RIM LIGHT (cool, behind subject)
rim_data = bpy.data.lights.new('LGT-rim', type='SPOT')
rim_data.energy = 600
rim_data.spot_size = math.radians(40)
rim_data.color = (0.7, 0.85, 1.0)
rim = bpy.data.objects.new('LGT-rim', rim_data)
bpy.context.collection.objects.link(rim)
rim.location = (0, 4, 3.0)
rim.rotation_euler = (math.radians(120), 0, math.radians(180))
print('lighting:three_point')
```
**Standard ratios**:
- High-key (commercial): Key:Fill = 2:1
- Medium (portrait): 4:1
- Low-key (dramatic): 8:1+
- Rim: 50–100% of key
### Recipe 2 — HDRI environment
```python
import bpy
world = bpy.context.scene.world
world.use_nodes = True
nodes = world.node_tree.nodes
links = world.node_tree.links
# Wipe existing world nodes
for n in list(nodes):
nodes.remove(n)
# Output → Background ← Environment Texture ← Mapping ← Texture Coordinate
output = nodes.new('ShaderNodeOutputWorld'); output.location = (300, 0)
bg = nodes.new('ShaderNodeBackground'); bg.location = (100, 0)
bg.inputs['Strength'].default_value = 1.0
env = nodes.new('ShaderNodeTexEnvironment'); env.location = (-100, 0)
env.image = bpy.data.images.load('/path/to/your.hdr') # ← user provides path
mapping = nodes.new('ShaderNodeMapping'); mapping.location = (-300, 0)
tex_coord = nodes.new('ShaderNodeTexCoord'); tex_coord.location = (-500, 0)
links.new(tex_coord.outputs['Generated'], mapping.inputs['Vector'])
links.new(mapping.outputs['Vector'], env.inputs['Vector'])
links.new(env.outputs['Color'], bg.inputs['Color'])
links.new(bg.outputs['Background'], output.inputs['Surface'])
print('lighting:hdri')
```
**Pro source**: free HDRIs at [polyhaven.com/hdris](https://polyhaven.com/hdris) (CC0).
### Recipe 3 — Sunny outdoor
```python
import bpy, math
sun_data = bpy.data.lights.new('LGT-sun', type='SUN')
sun_data.energy = 5.0
sun_data.color = (1.0, 0.95, 0.8) # golden hour
sun_data.angle = math.radians(0.5) # realistic sun size; bigger = softer
sun = bpy.data.objects.new('LGT-sun', sun_data)
bpy.context.collection.objects.link(sun)
sun.location = (0, 0, 10)
sun.rotation_euler = (math.radians(45), math.radians(15), 0)
print('lighting:outdoor_sun')
```
Combine with HDRI sky environment (Recipe 2) for natural ambient fill.
### Recipe 4 — Indoor window light
```python
import bpy, math
# Sun coming through window — cool blue, sharp
sun_data = bpy.data.lights.new('LGT-window_sun', type='SUN')
sun_data.energy = 3.0
sun_data.color = (0.85, 0.9, 1.0)
sun_data.angle = math.radians(2.0) # softer than direct sun
sun = bpy.data.objects.new('LGT-window_sun', sun_data)
bpy.context.collection.objects.link(sun)
sun.location = (5, -3, 4)
sun.rotation_euler = (math.radians(60), math.radians(-30), 0)
# Practical lamp — warm point light
lamp_data = bpy.data.lights.new('LGT-lamp', type='POINT')
lamp_data.energy = 60
lamp_data.color = (1.0, 0.7, 0.4) # warm bulb
lamp = bpy.data.objects.new('LGT-lamp', lamp_data)
bpy.context.collection.objects.link(lamp)
lamp.location = (-1, 2, 1.5)
print('lighting:indoor_window')
```
### Recipe 5 — Dramatic single-source
```python
import bpy, math
spot_data = bpy.data.lights.new('LGT-drama', type='SPOT')
spot_data.energy = 800
spot_data.spot_size = math.radians(30)
spot_data.spot_blend = 0.3
spot_data.color = (1.0, 0.95, 0.85)
spot = bpy.data.objects.new('LGT-drama', spot_data)
bpy.context.collection.objects.link(spot)
spot.location = (2, -2, 6)
spot.rotation_euler = (math.radians(60), 0, 0)
print('lighting:dramatic')
```
For full noir: pair with strong volumetrics (atmosphere) — see `references/overview.md` for the volumetric setup.
### Recipe 6 — Color-temperature cheat sheet
| Source | RGB |
|--------|-----|
| Candle (1850K) | `(1.0, 0.6, 0.3)` |
| Tungsten (3200K) | `(1.0, 0.85, 0.6)` |
| LED warm (3000K) | `(1.0, 0.8, 0.6)` |
| Sunset / golden (3500K) | `(1.0, 0.85, 0.65)` |
| Daylight noon (5500K) | `(1.0, 1.0, 1.0)` |
| Overcast sky (6500K) | `(0.95, 0.95, 1.0)` |
| Blue hour (8000K) | `(0.8, 0.9, 1.0)` |
**Pro mix**: Warm key (tungsten) + cool fill (daylight) = the "golden/teal" Hollywood look.
### Recipe 7 — Soft vs hard shadow tweak
```python
import bpy, math
light_data = bpy.data.lights['LGT-key']
# Make shadows softer
light_data.size = 2.0 # Area: bigger size = softer shadow
# Or for Sun:
# light_data.angle = math.radians(5) # bigger angle = softer shadow
# Make shadows harder (crisp)
# light_data.size = 0.1
# Or:
# light_data.angle = math.radians(0.5)
```
## Naming convention
| Prefix | Meaning |
|--------|---------|
| `LGT-key` | Main / key light |
| `LGT-fill` | Fill light |
| `LGT-rim` / `LGT-back` | Rim or back light |
| `LGT-sun` | Sun lamp |
| `LGT-{name}` | Practical lights (lamp, candle, neon, etc.) |
## Common pitfalls
| Symptom | Fix |
|---------|-----|
| Half the model in pitch black | Add fill (Area light or HDRI) |
| Render looks "flat" | Increase key:fill ratio; add rim |
| Hard shadows everywhere | Increase Area size or Sun angle |
| Too dark overall | Boost View Transform exposure or HDRI strength |
| No reflections on materials | Always set a world environment (HDRI) |
| Light inside object | Check world position; light must be visible from camera |
| Backlight blowing out subject | Rim energy ≤ key energy |
## When to load `references/overview.md`
Load when:
- The user asks for a setup not in the recipes (volumetric god rays, light groups, light linking)
- HDRI rotation / strength tuning is needed beyond defaults
- Multi-light scenes (5+ lamps) require organization
- Color science or color management gets specific (AgX, Filmic)
The reference covers: all 5 light types in depth, full HDRI workflow, light groups for re-lighting in compositor, recipes for product/portrait/architectural/character/animation looks.
© RobLe3 · MIT · RobLe3/cc-blender-skill