Lighting, rendering and compositing
SkillMediaGuides your agent through lighting, rendering and compositing scenes in Blender.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the Lighting, rendering and compositing skill
About this skill
Use when lighting, rendering or compositing in Blender: light a character, product or hero shot, interior at dusk or night, three-point or motivated lighting, sun and sky, HDRI, EEVEE vs Cycles settings, light leaks or noise, flat or muddy renders, subject not standing out, AgX/ACES color management
What this skill tells your AI
The instructions your AI receives, as published by scenario-labs/skills in skills/dcc/blender/scenario-blender-lighting-rendering/SKILL.md and read by ahel’s review.
Expert lighting controls where the eye goes. Shape comes from gradients, the subject is separated from its surroundings by value (checked desaturated), every light has a source and a purpose, and every decision is measured on the render, not on lamp values. Work from a controlled base, change one thing at a time, and compare. If a sibling skill named here is missing from your available skills, ask the user to install it (npx skills add scenario-labs/skills --skill <name>); unattended, proceed from tool schemas and flag the gap.
REQUIRED BACKGROUND: scenario-blender-expert (execution channel, review loop, 5.2 API changes). Related: scenario-blender-texturing-shading (materials, skin SSS), scenario-blender-previs-storyboard (shot planning, cameras).
Toolkit: scripts/bx_light.py (tested on 5.2.1): rigs placed relative to subject and camera, EEVEE/Cycles presets, color setup and audit, 5.x compositor helpers, render analysis. Import: sys.path.append("<this skill>/scripts"); import bx_light as BL.
Stance (the expert delta)
- Value separation first. Andy Goralczyk separates character from background by value in almost every shot and checks it desaturated. Andrew Price: the highest-contrast area becomes the focal point whether you want it or not (the bright window beats the couch). Fix by darkening the set before brightening the subject.
- Light size and distance are the controls. Andrew: a large source reads form and hides pores, a small one reads texture and grit, so a face key is a large source, never a small bulb (unless toon or deliberately harsh). Inverse square is an attention tool: move a light closer instead of adding helpers. No key:fill ratio is a rule (Andrew: "half the key is bogus"): dim the shadow side until it reads as shadow with detail, and measure on the subject.
- Motivate, then cheat plausibly. Every light needs a source and a color from the world (Gleb Alexandrov, Lino Thomas). Andy puts the rim on the key side, because on the shadow side it reads as a bounce from nowhere. When the source is behind the subject he fakes a key into the face. Shadow casters and light linking keep cheats off the set. Gleb stops before the image "looks lit".
- EEVEE is a trench coat (Andrew). Ray tracing is off in a factory scene. World light passes through walls unless the volume probe's outer samples sit at the inner walls (Andrew; measured 0.26 leak to 0.002; 5.2.1 puts samples one spacing inside the box, so size the box from the points). Soft lights need per-light jitter (Gleb) and custom distance (measured: automatic distance loses 8 %).
- Cycles economy (Andy, Sprite Fright): 3 bounces, no caustics, no clamping, Fast GI, and bounces faked with lights. Keep sharp speculars for the eyes and hero metal only.
- Linear and wide until the end (Jacob Holiday). EXR stays linear while PNG bakes the view transform. AgX hides clipping (linear 4 displays 0.91), so read the EXR. Global brightness is
exposurein the view transform, not scaled lights (keeps every ratio, including world and emissives). AgX for scenes, Khronos PBR Neutral for product color. Set the working space once (Nathan Vegdahl). - Rebalance in comp, not by re-rendering (Wyatt, Robin). In Cycles, light groups per role (key, fill, rim, window): one render, then gains in the compositor (
BL.light_groups,BL.lightgroup_mix). EEVEE has no light-group outputs: use light linking and view layers. - Always comp, lightly (Pau Homs): bloom, vignette, then a correction, stopping before it reads as a filter. In 5.x the compositor is a node group.
- Color has three contrasts (Lino): value, saturation and hue. Keep one saturated focus hue and desaturate its complement over large areas.
Establish first
| Input | Why it changes the plan | Default when silent |
|---|---|---|
| Still or animation | Continuity, flicker and temporal denoise | Still |
| Engine | EEVEE: stylized, fast iteration, volumes, NPR, viewport comp with passes. Cycles: glass close-ups, bounce realism, reference | EEVEE to iterate, plus a Cycles reference render |
| Style | Toon terminators need a small, unjittered key | Stylized-realistic |
| Subject and focus point | Rig target (the face), mask for the analysis | Character head, else bbox center |
| Time and motivation | Color scheme: warm practicals, cool sky, sun | Night/dusk interior: warm key (2,700 K [added]), cool fill |
| Delivery | PNG display plus EXR master; external grade? | PNG + 32-bit multilayer EXR |
| Color fidelity | Brand RGB: Khronos PBR Neutral; skin: ACES 2.0 or AgX High Contrast | AgX |
| Late balance changes, comp hand-off | Cycles light groups per role, multilayer EXR | groups when rendering in Cycles |
Workflow
- Compose, then lock the camera. Lighting is view dependent (Andrew). Use
BL.screen_xyandBL.aim_camera_at_frame_point(head, 1/3 or 2/3, 0.62)for look room, and 80 mm for boxy products. GATE: one focal element; subject near a thirds point or a deliberate symmetry, pyramid or full frame. - Controlled base. For a studio: world strength 0 and a near-black rough ground (Andrew). For an EEVEE interior:
pb = BL.volume_probe_for_room(inner_lo, inner_hi, cell=0.5, wall=0.2)(outer samples on the inner walls),BL.probe_report(pb, inner_lo, inner_hi), thenBL.bake_probes(). For an exterior:BL.outdoor_sun_sky(..., azimuth_space="world"). GATE:probe_reportflags nothing and a world-only render of a sealed interior is near black. - Key. Use
BL.three_point,BL.motivated_interior(window + practical, cheated linked key, spot practical, rims, bounce) orBL.outdoor_sun_sky. Lights stay out of walls automatically. GATE:BL.light_report(target=head, face=head)has no flags (frontal key, key below the eye line, key smaller than the head), and a clay render (BL.clay(True)) givesinternal_ratio >= 2.5. - Supporting lights. Add fill, rim, bounce and
BL.eye_light, plusBL.shadow_caster,BL.fake_sun,BL.split_worldorBL.hazeas needed. Linking lives on the light OBJECT (obj.light_linking, viaBL.link_light), not the Light datablock. Adjust one lamp at a time:BL.light_contributions(lights, mask, dir), or in CyclesBL.lightgroup_check(exr, mask)from one render. GATE: the key has the largest share on the subject, the world is under 10 % indoors, and each rim is motivated. - Measure and look.
r = BL.render(base)gives PNG + EXR. Thenmask = BL.mask_cryptomatte(r["exr"], names)(orBL.mask_workbench),rep = BL.analyse(r["png"], mask, exr=r["exr"]),BL.verdict(rep)andBL.value_study(...), and open the images. GATE: the verdict is empty and in the value study the subject owns a value group; otherwise darken the set, carve with spots or blockers, and link the key. - Color.
BL.color_setup(view, look, exposure)(brightness here, never by scaling lamps) andBL.color_audit(). GATE: the audit is empty, no complementary clash is flagged, clip is at most 0.5 % outside emitters, and the linear max is intended. - Render settings.
BL.preset_eevee(quality="final", interior=...)orBL.preset_cycles(quality="final", budget="film"). For EEVEE finals, render a Cycles preview reference (Andrew). GATE: the subject is within about 30 % of Cycles and there are no engine artifacts (critique section 7). - Comp. Cycles:
mix = BL.lightgroup_mix(gains, exr=r["exr"])re-grades key/fill/rim/window from the EXR in about 0.2 s (BL.set_gain, RGB gains recolor). ThenBL.comp_finish(bloom=0.25, vignette=0.3, contrast=0.05, source=mix["socket"]); masks withBL.matte(tree, names); pixel sizes throughBL.relative_px; passes, back to beauty and view layers are in procedures P13. GATE: re-run the verdict on the finished frame; the vignette ratio should fall. - Deliver with evidence: final PNG, EXR, value study, the light table, the verdict, and what was not verified.
Animation: pin the sun per location with sun_azimuth within about 30 deg (Andy). Light the wide shot and propagate it to coverage. Check shots with BL.contact_sheet and BL.sheet_stats (outliers more than 0.5 stop from the median). Keep temporal denoise on and never use ray-tracing resolution 1/16.
Numbers
| Value | Relative to | Source |
|---|---|---|
| Level of a white card: point P/(4π²d²), area P/(π²d²), sun S/π | BL.energy_for | measured, both engines |
| Source as big as its distance delivers 75 % of the nominal level | apparent size | measured |
| AgX display: 0.18 to 0.463, 1.0 to 0.773, 4.0 to 0.910 | linear value | measured |
| Key 40 deg off axis, 35 deg up, 3 subject radii, size = radius | subject, camera | [added] defaults |
| Frontal flag: key < 20 deg off the camera axis | camera axis | [added] |
| Sun angle about 2 deg; continuity ±30 deg | set | Andy |
| Kelvin: candle 1,500, incandescent 2,000 to 2,500, daylight 6,500 (practical default 2,700 [added]) | light | Andrew |
| EEVEE: RT 1:1 and GI 1:2 for finals, Fast GI steps 16, shadow steps 12 to 16 (leaks), shadow rays 2 (penumbra) | render | Andrew |
| Volume probe: outer samples on the inner walls (samples at local (i+1)/(N+1)x2-1); leak 0.22 at 0.44 m inside, 0.054 at 0.2 m, 0.002 at the wall, 0.009 past the wall; surfel density 100 | room | Andrew, measured |
| Brand color error (of 255): Khronos 3.8, AgX 27 to 42, Standard 33 | white furnace | measured |
| Haze density about 0.05 for a room | volume | Andrew |
| Cycles film: 3 bounces, clamp 0, no caustics, 100 test / 500 to 1,500 final samples | render | Andy |
| EXR: multilayer, half float, DWAA for comp; 32-bit masters | output | Robin, Andy |
| Verdict: surround separation ≥ 0.10, edge merge ≤ 35 %, clay form ratio ≥ 2.5, value range ≥ 0.30, clip ≤ 0.5 % | display luma | [added], calibrated |
Quality gates
Measurable:
rep = BL.analyse(png, mask, exr=exr); problems = BL.verdict(rep) # [] = pass
flags = BL.light_report(target=head, face=head)["flags"]; audit = BL.color_audit()
probe = BL.probe_report(pb, inner_lo, inner_hi)["flags"] # EEVEE interiors: []
groups = BL.lightgroup_check(exr, mask) # Cycles: rel_error ~0, shares
shares = BL.light_contributions(lights, mask, out_dir) # per-light share on subject
Visual: open the render, the value_study panel (desaturated | value groups | squint) and, for sequences, the contact sheet. Judge them with references/critique.md: first read, value structure, form, motivation, color, composition, artifacts, finish.
Common mistakes
| Mistake | What it looks like | Fix |
|---|---|---|
| Frontal key | Flat, "flash photo", clay form ratio about 1.3 | Key 30 to 60 deg off axis, above the eye line |
| Practical behind the subject used as the key | Dull face, bright wall steals focus | Cheated key on the source's side, linked to the subject |
| Bare point practical near a wall | Blown wall, shelf becomes the focal point | Spot with the shade's cone; blocker |
| EEVEE interior without probe, or a probe box drawn to the walls | Shadows lifted blue/gray everywhere, muddy | Outer samples at the inner walls (probe_report), bake, sealed-room test |
| Small bulb as a face key | Pores and texture, harsh face | Large source (head-sized or more); flag in light_report(face=) |
| Brightening by scaling lamps | World and emissives left behind, ratios drift | exposure in the view transform |
light.data.light_linking | AttributeError | Linking and light groups are Object properties |
| Re-rendering to rebalance lights | Hours per tweak | Cycles light groups + lightgroup_mix |
| Rig lights inside walls | A rim that contributes nothing | avoid=subject (default in rigs) |
| Unlinked faked key | Set brightens with the subject, no separation | link_key=True; key share high, background share near 0 |
| Judging clipping on AgX PNG | Highlights look fine, EXR at 20+ | Read linear_max, use exposure |
| Big soft jittered key on a toon material | Dithered, noisy terminator | Small unjittered key for NPR (Wyatt: crisp shadows for toon) |
| Inverted hull outline | Character goes dark or flat | Outline material transparent to shadow rays (outline_hull) |
| AOV named in shader only | Pass silently missing | BL.register_aovs() |
| Pixel-sized comp effects | Look changes between preview and final | BL.relative_px |
| Exclude instead of indirect-only in layers | Missing shadows in the comp | indirect_only (0.0004 vs 0.016 diff) |
Blender 5.2 notes
- EEVEE id is
BLENDER_EEVEE;use_raytracingis False by default;use_bloom/ssr/gtao/soft_shadowsare gone (Glare node, ray tracing, Fast GI, per-light jitter). - Probes are
SPHERE/PLANE/VOLUME;lightprobe_cache_bakeruns synchronously headless; the sphere-probe default is 512. Volume samples sit one spacing inside the box faces, never on them. - EEVEE writes Cryptomatte but no Object Index pass; light groups are Cycles only (EEVEE Render Layers has no
Combined_<group>); light linking works in both engines.light_linkingandlightgroupare Object properties;bpy.types.Lighthas neither. - Compositor:
scene.compositing_node_group, Group Output,ShaderNodeMix(color sockets 6/7, result 2), menu inputs take display names ('Bloom'). GPU is the default device. Assets live indatafiles/assets/nodes/compositing_nodes_essentials.blend. - Color: the working space is read-only (use
bpy.ops.wm.set_working_color_space); looks are prefixed ('AgX - Punchy'); 'Linear'/'Raw' are rejected; camera log spaces exist; Principled Thin Wall exists for window glass. matrix_worldis stale after setting a transform; callview_layer.update(). OIIOread_image(subimage, ...): the first argument selects the part.
References
references/procedures.md: tested code for every stage (P1 units to P17 exposure and color), with measured results and test paths. Load before writing code.references/critique.md: the rubric to judge a render or sequence, in expert reading order, with the code check behind each question.references/expert-notes.md: principles per expert with timestamps, plus the disagreements table. Load for judgment calls and attribution.references/sources.md: the 15 videos, credentials, best timestamps, and which to consult for which question.
Signals
- GitHub stars
- 681
- Forks
- 82
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
scenario-blender-lighting-rendering- Source
- github.com/scenario-labs/skills