Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"examples/triangulate-tangents",
"examples/turntable",
"examples/uv-layer-grid",
"examples/vertex-color-ao",
"examples/vertex-weight-limit",
"examples/vse-cut-list",
"examples/vse-gamma-cross",
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/blender-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -609,3 +609,18 @@ jobs:
# root scale down into the children. Exits non-zero on failure.
xvfb-run -a "$BLENDER" --background \
--python examples/socket-attach-points/socket_attach_points.py --

- name: Shipped example - vertex colour AO (baked occlusion attribute)
run: |
set -euo pipefail
# Check only (no render): a deterministic cosine-weighted hemisphere
# AO integrator validated against the closed form
# 1 - 0.5(1 - 1/sqrt(1+k^2)) at six probe distances, an unoccluded
# plate baking to exactly 1.0, strict monotonicity with distance,
# then the same integrator run over an 11-part stone well: values in
# [0,1] with real spread, FLOAT_COLOR exact round-trip vs BYTE_COLOR
# matching an independent sRGB quantisation model, both attributes
# surviving depsgraph evaluation at deviation 0 with element counts
# intact, and reuse hygiene. Exits non-zero on failure.
xvfb-run -a "$BLENDER" --background \
--python examples/vertex-color-ao/vertex_color_ao.py --
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</p>

<p align="center">
<strong>12 skills</strong> &nbsp;&bull;&nbsp; <strong>6 rules</strong> &nbsp;&bull;&nbsp; <strong>2 templates</strong> &nbsp;&bull;&nbsp; <strong>17 snippets</strong> &nbsp;&bull;&nbsp; <strong>43 examples</strong>
<strong>12 skills</strong> &nbsp;&bull;&nbsp; <strong>6 rules</strong> &nbsp;&bull;&nbsp; <strong>2 templates</strong> &nbsp;&bull;&nbsp; <strong>17 snippets</strong> &nbsp;&bull;&nbsp; <strong>44 examples</strong>
</p>

<p align="center">
Expand All @@ -36,7 +36,7 @@

## Overview

This repository ships **12 skills, 6 rules, 2 templates, 17 snippets, and 43 runnable examples** for Blender Python development targeting Blender 5.1 (current stable) with Blender 4.5 LTS fallback support.
This repository ships **12 skills, 6 rules, 2 templates, 17 snippets, and 44 runnable examples** for Blender Python development targeting Blender 5.1 (current stable) with Blender 4.5 LTS fallback support.

The content is consumed by AI coding agents (Cursor, Claude Code, any MCP-capable client) when working on Blender add-ons, geometry nodes scripts, batch pipelines, or animation tooling. There is no build step. Edit the markdown and Python files directly.

Expand Down Expand Up @@ -843,6 +843,27 @@ Companion to [`prop-origin-transform`](examples/prop-origin-transform/)
[`parent-inverse-orrery`](examples/parent-inverse-orrery/) (parent-inverse
under animation).

</td>
</tr>
<tr>
<td width="46%" valign="middle">
<a href="examples/vertex-color-ao/"><img src="examples/vertex-color-ao/preview.webp" alt="Vertex colour AO: a stone village well on a dark studio stage, its masonry joints, shaft mouth and coping undersides darkened by ambient occlusion baked into a colour attribute rather than by the lights" /></a>
</td>
<td valign="middle">

### [vertex-color-ao](examples/vertex-color-ao/)

Baked occlusion in a colour attribute, checked against a **formula** instead
of a captured value: the cosine-weighted hemisphere integral for a wall of
height `H` at distance `d` is `1 - ½(1 - 1/√(1+k²))`, `k = H/d`, and the
integrator matches it to **6.760e-04** across two decades of `k`. An
unoccluded plate bakes to exactly **1.0**. `FLOAT_COLOR` round-trips exactly
while **`BYTE_COLOR` is sRGB-encoded 8-bit** — 0.735 reads back
**0.7379107**, matching an independent encode/quantise/decode model to
**3.189e-07**. Both survive depsgraph evaluation at deviation **0.0**.
Companion to [`color-attribute-wheel`](examples/color-attribute-wheel/) and
[`attribute-domain-shear`](examples/attribute-domain-shear/).

</td>
</tr>
</table>
Expand Down
1 change: 1 addition & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo
- ~~Modular kit snap witness~~ **SHIPPED** as `examples/modular-kit-snap/` — tiling corridor segment: 16 boundary verts on `x ∈ {0, TILE}` within 1e-6 m, end rings coincident under the tile offset (nearest-key match), linked-duplicate joint deviation 0.0, shell bbox == declared tile (dev 0.0), manifold except the 16 open-end edges, 20 detail parts contained inside the tile; unsnapped probe (3 mm skew, 2 mm nudge) fails at exits 3/4 with measured errors; sorted-zip ring matching mispairs displaced verts — match by nearest key (authoring hazard, fixed); byte-identical on 4.5.11 and 5.1.2
- ~~Lightmap UV channel witness~~ **SHIPPED** as `examples/lightmap-uv-channel/` — two-channel UV contract on a market cart: per-part `UVMap`/`UVLight` with `active`/`active_render` re-asserted after the ops (edit-mode UV ops clear both flags; `uv_layers.new()` never moves them), UV0 drift 0.0 (clobber trap measured 2.068), every UV1 loop in [0,1], 0 overlapping islands via independent binned strict-SAT (15 hits when falsified), min island distance 0.00401 vs nominal margin 0.002 (`MARGIN_DIV × 0.01` semantics measured live); held `MeshUVLoopLayer.data` after edit-mode UV ops segfaults 4.5.11 (5/5, EXCEPTION_ACCESS_VIOLATION), silent no-op pack without prior unwrap; byte-identical on 4.5.11 and 5.1.2 (3680 islands)
- ~~Socket attach-point witness~~ **SHIPPED** as `examples/socket-attach-points/` — named `SKT_` empties as the spawn contract on a survey drone: 7 socket world matrices within 1.788e-07 of the authored transform with orthonormal right-handed bases (Gram 3.576e-07, det err 2.980e-07), socket +Z == the mount pad's Newell normal (1.794e-07) by a quaternion-swing construction independent of the Gram-Schmidt basis, origin on the mount-face centroid (6.687e-08), documented up-axis fallback for the +Z/−Z mounts, module seating offset exactly 0.0 with strictly identity local matrices, rigid invariance under a re-pose (2.384e-07); `transform_apply` on an **Empty** root preserves world matrices (2.235e-07) but clears **7/7** `matrix_parent_inverse` and pushes the root scale down into every child (0.35 for an applied 1.35) — both halves asserted; a child left selected during the apply drifts sockets **2.335 m**; `bm.normal_update()` does not fix inward winding (`recalc_face_normals` does — the lofted fuselage rendered as a flat white panel); no-parent-inverse probe jumps 0.690128 m; byte-identical on 4.5.11 and 5.1.2
- ~~Vertex-colour AO witness~~ **SHIPPED** as `examples/vertex-color-ao/` — baked occlusion in a colour attribute on a stone village well, checked against a closed form rather than a captured value: the cosine-weighted hemisphere integral for an infinitely wide wall of height H at distance d is `AO = 1 − ½(1 − 1/√(1+k²))`, `k = H/d`, matched to **6.760e-04** across k = 60.0…0.60 (gate 2.5e-03, QMC noise ~1/√n at 4096 samples); unoccluded plate bakes to **exactly 1.0**; strictly monotone 0.508301 → 0.928467; asset values in [0,1] with spread 1.0; **`BYTE_COLOR` is sRGB-encoded 8-bit, not linear** (0.735 → 0.7379107, peak round-trip error 3.782e-03, matching an independent encode/quantise/decode model to 3.189e-07) while `FLOAT_COLOR` is exact; both survive depsgraph evaluation at deviation 0.0; `bmesh.ops.bevel` offsets along **cached** face normals and flips outward past 90° of staleness (12 mm below ground on a ring of boxes, fixed by `normal_update()`); point-domain AO needs subdivision or the crevice gradient never reaches the attribute; `color_attributes` enumeration order differs between 4.5.11 and 5.1.2 — look up by name; byte-identical on 4.5.11 and 5.1.2 (6966 verts)
- UV atlas **utilization** witness — coverage/wasted-texel closed forms for a packed lightmap atlas (the non-overlap, unit-square, margin, and active/active_render contracts shipped in `lightmap-uv-channel`; utilization is the remaining unbuilt slice of the old "UV atlas pack" candidate)
- ~~GAMMA_CROSS blend-curve witness~~ **SHIPPED** as `examples/vse-gamma-cross/` — the cross blends in a gamma-0.5 space: `((1-t)·√A + t·√B)²` with `t = (frame − start)/duration`, never 1 inside the effect; mid-cross dips 0.115 below the sRGB lerp from crimson/teal (closed form (0.341, 0.349, 0.463) confirmed per frame); AgX-default sampling poisons the fit (0.146 red-channel error, `view_transform='Standard'` mandatory); deleting a consumed input orphans-and-deletes the effect — follow-up to `vse-cut-list`
- Falsy `bpy_prop_collection` trap snippet: an empty collection is falsy, so `editor.strips or editor.sequences` silently falls through to the legacy accessor on an empty timeline — always branch on `hasattr`; likely generalizes across the API (found authoring `vse-cut-list`)
Expand Down
Binary file added docs/gallery/asset-sheets/vertex-color-ao.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/gallery/assets/vertex-color-ao-hero.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 12 additions & 1 deletion docs/gallery/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ <h1>Examples Gallery</h1>
autocomplete="off" spellcheck="false" aria-label="Search examples" />
<button class="q-clear" id="qClear" type="button" aria-label="Clear search" hidden>&times;</button>
</div>
<span class="count" id="count" role="status" aria-live="polite">43 examples</span>
<span class="count" id="count" role="status" aria-live="polite">44 examples</span>
<div class="density" role="group" aria-label="Card density">
<button class="density-btn" data-density="compact" type="button" aria-pressed="false">Compact</button>
<button class="density-btn" data-density="detailed" type="button" aria-pressed="false">Detailed</button>
Expand Down Expand Up @@ -795,6 +795,17 @@ <h2><a href="socket-attach-points/">socket-attach-points</a></h2>
<a class="card-link" href="socket-attach-points/">View example <span aria-hidden="true">&rarr;</span></a>
</div>
</article>
<article class="card" data-tags="mesh attributes game-pipeline render">
<a class="card-media" href="vertex-color-ao/" aria-label="vertex-color-ao example detail page">
<img src="assets/vertex-color-ao-hero.webp" alt="vertex-color-ao — A stone well carrying baked ambient occlusion in a colour attribute, with the bake held to the closed-form hemisphere integral rather than to a captured value." loading="lazy" decoding="async" />
</a>
<div class="card-body">
<h2><a href="vertex-color-ao/">vertex-color-ao</a></h2>
<p class="teaches">A stone well carrying baked ambient occlusion in a colour attribute, with the bake held to the closed-form hemisphere integral rather than to a captured value.</p>
<p class="witnesses"><span class="tag">witnesses</span> Integrator matches 1 - 0.5(1 - 1/sqrt(1+k^2)) to 6.760e-04, unoccluded plate exactly 1.0, FLOAT_COLOR exact vs BYTE_COLOR sRGB-quantised (model agreement 3.189e-07), evaluated deviation 0.0.</p>
<a class="card-link" href="vertex-color-ao/">View example <span aria-hidden="true">&rarr;</span></a>
</div>
</article>
</div>
<p class="noresults" id="noResults" hidden>No examples match the current filters.
<button class="chip" id="resetFilters" type="button">Clear search and tags</button></p>
Expand Down
Loading
Loading