Light Link Studio

examples/light-link-studio/

One key, one hero: a light linked to a receiver collection lights only the hero, proven by two pixel renders in one pass. Linked: 3.6x luminance ratio; unlinked in the same check: the decoy rises 233% while the hero holds at 0.3% drift.

Rendered headless by the example itself. Select it to enlarge.

witnesses The API is obj.light_linking on the light OBJECT (ld.light_linking is an AttributeError). Luminance is sampled at each sphere's projected center; EEVEE honors linking too (probe-measured 3.8x on 4.5.11 EEVEE Next and 5.1.2 EEVEE), Cycles pinned for deterministic samples.

tags rendering objects

runs on 4.5 LTS · 5.1 · 5.2 LTS

blender --background --python examples/light-link-studio/light_link_studio.py --

falsify it Breaks the contract on purpose and must exit 6

blender --background --python examples/light-link-studio/light_link_studio.py -- --skip-link

A runnable example that stages one key light linked to a hero sphere beside an identical decoy, renders the studio twice in one pass, and proves the whole light-linking contract in pixels — the feature AI-generated staging code most often misses or misaddresses.

What it witnesses: the light-linking contract and the traps around it.

What each check catches on failure: inverting the link to the decoy collection (exit 6 — hero/decoy ratio collapses to 0.39x), an RNA move of the API onto the Light datablock (exit 3, guarded), a lost assignment read-back (exit 5), a link that doesn't restrict (exit 7, rise below 50%), and a non-surgical restriction (exit 8, hero drift above 5%).

Version witness: ObjectLightLinking API and the measured ratios match on Blender 4.5 LTS and 5.1 (3.7x vs 3.6x linked; rise 238% vs 233% — inside the rise noise described above).

The render is the contract at a glance, on designed subjects: after the check passes on the spheres, the still hides them and stands two identical lathed porcelain chess kings (gilt collar and cross, one shared material) in the hero and decoy collections. The only difference between the kings is the linked key, recoloured amber for the still: the LINKED king glows warm over its placard and the warm floor inlay, the UNLINKED king stays cool grey. The shared fill and rim are pulled down for the still only, because glossy porcelain picks up far more of them than the matte check spheres do. The still's render path gates framing through examples/gallery_framing.py (exit 10) before writing.

Run#

# Two-render correctness check (tiny Cycles CPU renders) — the CI check:
blender --background --python light_link_studio.py --

# Falsifier: receiver_collection unset. Must exit non-zero (linked render: decoy lit).
blender --background --python light_link_studio.py -- --skip-link

# Also render the gallery still (Cycles, deterministic samples):
blender --background --python light_link_studio.py -- --output linked.png

Exit codes#

Per-script sequential checks. 9 is a valid check code; there is no rule against it.

CodeMeaning
0Success
1Uncaught exception (FATAL wrapper)
2argparse / usage
3Light datablock gained light_linking
4Light objects lost light_linking
6Linked state: hero dark or hero/decoy ratio below gate (--skip-link lands here)
7Decoy rise below gate when unlinked
8Hero drifted across the unlink
9--output produced no file
10Framing gate violation on the --output path (gallery_framing)

The blender-smoke workflow runs the check on Blender 5.2 LTS and 4.5 LTS (5.1 on the weekly cron, the needs-5.1 PR label, or manual dispatch). Smoke does not pass --output. Its catalog falsifier is --skip-link (expects exit 6).

Source

examples/light-link-studio/light_link_studio.py View the script on GitHub →
Two identical porcelain chess kings on dark plinths: the left, labelled LINKED, glows under an amber key; the right, labelled UNLINKED, stays cool grey.