Skip to content

Commit 87dad44

Browse files
TMHSDigitalclaude
andauthored
fix: bake-normal-high-to-low and lightmap-uv-channel quality pass (#244)
* fix(examples): stand the bake-normal panels in plinths Render path only. Both panels balanced on an edge and the leaning plate pierced the floor; each now stands in a low plinth, lifted so its lowest evaluated point seats 35 mm in the slot. The solidify rim wears plain bronze rather than the baked map. Bake statistics (frac 0.7211, MAD 0.09356) and exit codes unchanged on all three binaries. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> * fix(examples): raise the lightmap cart posts into its canopy The four 1.35 m posts stopped 0.33 m under the canopy arc, so the canopy floated. Each post now rises into the arc's underside at its own station, its top sheared to the arc for a uniform 12 mm bite. Every part keeps its UV1 island count, zero overlap and minimum island distance; exit codes are unchanged on all three binaries. Also refreshes the gallery alts and index for both examples. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> --------- Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 5174e81 commit 87dad44

14 files changed

Lines changed: 184 additions & 24 deletions

File tree

318 Bytes
Loading
6.83 KB
Loading

‎docs/gallery/bake-normal-high-to-low/index.html‎

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
<meta property="og:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/bake-normal-high-to-low-hero.webp" />
1717
<meta property="og:image:width" content="1280" />
1818
<meta property="og:image:height" content="720" />
19-
<meta property="og:image:alt" content="A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern." />
19+
<meta property="og:image:alt" content="A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern, both standing in low display plinths." />
2020
<meta property="og:site_name" content="Blender Developer Tools" />
2121
<meta name="twitter:card" content="summary_large_image" />
2222
<meta name="twitter:title" content="bake-normal-high-to-low — Examples — Blender Developer Tools" />
2323
<meta name="twitter:description" content="A collapse-decimated hatch plate receiving a Cycles cage-baked tangent normal map from a ribbed high-poly source" />
2424
<meta name="twitter:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/bake-normal-high-to-low-hero.webp" />
25-
<meta name="twitter:image:alt" content="A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern." />
25+
<meta name="twitter:image:alt" content="A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern, both standing in low display plinths." />
2626
<style>
2727
/* fonts are deployed by the landing build (docs/fonts/) */
2828
@font-face { font-family: 'Barlow Condensed'; font-weight: 600; font-display: swap;
@@ -268,8 +268,8 @@ <h1>bake-normal-high-to-low</h1>
268268
<p>A collapse-decimated hatch plate receiving a Cycles cage-baked tangent normal map from a ribbed high-poly source</p>
269269
</header>
270270
<main id="main">
271-
<button class="detail-hero" id="heroZoom" type="button" aria-label="View full size: A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern.">
272-
<img src="../assets/bake-normal-high-to-low-hero.webp" alt="A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern." width="1280" height="720" />
271+
<button class="detail-hero" id="heroZoom" type="button" aria-label="View full size: A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern, both standing in low display plinths.">
272+
<img src="../assets/bake-normal-high-to-low-hero.webp" alt="A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern, both standing in low display plinths." width="1280" height="720" />
273273
</button>
274274
<p class="zoom-hint">Rendered headless by the example itself — click to zoom.</p>
275275
<div class="callout"><span class="tag">witnesses</span> Statistical gates not byte-identity: detail frac 0.7211 / MAD 0.09356 vs flat 0.0000 / 0.00277; --flat-source exits 5; type=NORMAL not bake_type; RNA identical on 4.5.11, 5.1.2, 5.2.1</div>
@@ -284,6 +284,7 @@ <h1>bake-normal-high-to-low</h1>
284284
<ul><li><strong>Detail bake is not flat.</strong> <code>frac &gt;= 0.40</code> and <code>MAD &gt;= 0.05</code> (measured 0.7211 / 0.09356 on 4.5.11, 5.1.2, and 5.2.1). Catches an inactive Image Texture node, reversed selection, or EEVEE/GPU mis-setup that writes a blank map. MAD floor is half the measured hatch value, still ~30× a flat bake.</li><li><strong>Flat control is flat.</strong> <code>frac &lt;= 0.05</code> and <code>MAD &lt;= 0.03</code> (measured 0.0000 / 0.00277). Catches a noisy or wrongly-typed bake that would also satisfy the detail gates.</li><li><strong>Monotonic gap.</strong> <code>detail_frac - flat_frac &gt;= 0.30</code>. The two maps must separate; a tolerance wide enough to pass both would have no discriminating power.</li><li><strong><code>--flat-source</code> is the falsifier.</strong> Skips the ribs and still runs the detail gates. Must exit 5. Analogous to <code>--same-axis</code> in <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/export-preset-axis"><code>export-preset-axis</code></a>.</li></ul>
285285
<p>Neighbor of <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/lod-decimate-chain"><code>lod-decimate-chain</code></a> (the LOD is the cage target; collapse keeps UVs) and <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/image-pixels-testcard"><code>image-pixels-testcard</code></a> (<code>save_render</code>, not <code>Image.save()</code>, if you persist the datablock). UV transfer and atlas packing are out of scope.</p>
286286
<p>The still stages the baked map as an unlit card beside the LOD wearing it. If the bake were flat, the card would be uniform <code>(128, 128, 255)</code> periwinkle and the plate would shade like the undisplaced cage.</p>
287+
<p>Staging is render-only. Each panel stands in a low display plinth, lifted so its lowest evaluated point sits 35 mm in the slot. Both panels used to balance on an edge, and the leaning plate pierced the floor. The solidify rim wears plain bronze instead of the baked map. The slight waviness along the plate&#x27;s border is the bake itself, normal-map shading inside the UV margin, and is left as the map produces it. Bake statistics are unchanged: frac 0.7211, MAD 0.09356 on all three binaries.</p>
287288
<p>Operator RNA (<code>type=&#x27;NORMAL&#x27;</code>, <code>use_selected_to_active</code>, <code>cage_extrusion</code>, <code>cage_object</code> as a string, <code>normal_space=&#x27;TANGENT&#x27;</code>, <code>margin_type</code>) is identical on 4.5.11, 5.1.2, and 5.2.1 — no shim.</p>
288289
<h2>Run</h2>
289290
<pre><code># Cheap correctness check (no render) - the CI check:
@@ -686,6 +687,55 @@ <h2>Source</h2>
686687
<span class="k">return</span> ob
687688

688689

690+
PLINTH_H = <span class="n">0.10</span>
691+
PLINTH_SEAT = <span class="n">0.035</span>
692+
PLINTH_PAD = <span class="n">0.08</span>
693+
694+
695+
<span class="k">def</span> seat_on_plinth(ob, name):
696+
<span class="s">&quot;&quot;&quot;Stand a display panel in a low plinth by its own lowest point.
697+
698+
Render-only staging. The panel is lifted so its lowest evaluated vertex
699+
sits PLINTH_SEAT inside a dark slab sized from the panel&#x27;s footprint.
700+
Both panels used to balance on an edge, and the leaning plate&#x27;s lower
701+
edge pierced the floor.
702+
&quot;&quot;&quot;</span>
703+
bpy.context.view_layer.update()
704+
dg = bpy.context.evaluated_depsgraph_get()
705+
ev = ob.evaluated_get(dg)
706+
me = ev.to_mesh()
707+
<span class="k">try</span>:
708+
pts = [ev.matrix_world @ v.co <span class="k">for</span> v <span class="k">in</span> me.vertices]
709+
<span class="k">finally</span>:
710+
ev.to_mesh_clear()
711+
ob.location.z += (PLINTH_H - PLINTH_SEAT) - min(p.z <span class="k">for</span> p <span class="k">in</span> pts)
712+
base = [p <span class="k">for</span> p <span class="k">in</span> pts <span class="k">if</span> p.z &lt; min(q.z <span class="k">for</span> q <span class="k">in</span> pts) + <span class="n">0.15</span>]
713+
x0 = min(p.x <span class="k">for</span> p <span class="k">in</span> base) - PLINTH_PAD
714+
x1 = max(p.x <span class="k">for</span> p <span class="k">in</span> base) + PLINTH_PAD
715+
y0 = min(p.y <span class="k">for</span> p <span class="k">in</span> base) - PLINTH_PAD
716+
y1 = max(p.y <span class="k">for</span> p <span class="k">in</span> base) + PLINTH_PAD
717+
slab = bpy.data.meshes.new(name)
718+
bm = bmesh.new()
719+
<span class="k">try</span>:
720+
bmesh.ops.create_cube(bm, size=<span class="n">1.0</span>)
721+
<span class="k">for</span> v <span class="k">in</span> bm.verts:
722+
v.co.x = (x0 + x1) / <span class="n">2</span> + v.co.x * (x1 - x0)
723+
v.co.y = (y0 + y1) / <span class="n">2</span> + v.co.y * (y1 - y0)
724+
v.co.z = PLINTH_H / <span class="n">2</span> + v.co.z * PLINTH_H
725+
bmesh.ops.bevel(bm, geom=list(bm.edges), offset=<span class="n">0.012</span>, segments=<span class="n">2</span>,
726+
affect=<span class="s">&quot;EDGES&quot;</span>, clamp_overlap=<span class="k">True</span>)
727+
bm.to_mesh(slab)
728+
<span class="k">finally</span>:
729+
bm.free()
730+
pmat = bpy.data.materials.new(name + <span class="s">&quot;Mat&quot;</span>)
731+
pmat.use_nodes = <span class="k">True</span>
732+
paint_principled(pmat, (<span class="n">0.045</span>, <span class="n">0.042</span>, <span class="n">0.04</span>, <span class="n">1.0</span>), <span class="n">0.0</span>, <span class="n">0.55</span>)
733+
slab.materials.append(pmat)
734+
plinth = bpy.data.objects.new(name, slab)
735+
bpy.context.scene.collection.objects.link(plinth)
736+
<span class="k">return</span> plinth
737+
738+
689739
<span class="k">def</span> render_still(low, mat, tex, path, engine):
690740
scene = bpy.context.scene
691741
<span class="k">for</span> ob <span class="k">in</span> list(scene.objects):
@@ -694,13 +744,22 @@ <h2>Source</h2>
694744
ob.hide_viewport = <span class="k">True</span>
695745

696746
wire_normal_map(mat, tex)
747+
<span class="c"># The solidify rim is the plate&#x27;s edge, not baked surface: give it plain</span>
748+
<span class="c"># bronze. Wearing the map, it sampled the UV border and rendered ragged.</span>
749+
rim = bpy.data.materials.new(<span class="s">&quot;BronzeRim&quot;</span>)
750+
rim.use_nodes = <span class="k">True</span>
751+
paint_principled(rim, (<span class="n">0.22</span>, <span class="n">0.13</span>, <span class="n">0.07</span>, <span class="n">1.0</span>), <span class="n">0.58</span>, <span class="n">0.44</span>)
752+
low.data.materials.append(rim)
697753
solid = low.modifiers.new(<span class="s">&quot;SolidifyDisplay&quot;</span>, <span class="s">&quot;SOLIDIFY&quot;</span>)
698754
solid.thickness = THICKNESS
699755
solid.offset = <span class="n">1.0</span>
756+
solid.material_offset_rim = <span class="n">1</span>
700757
low.rotation_euler.x = math.radians(<span class="n">72.0</span>)
701758
low.location = (<span class="n">1.20</span>, <span class="n">0.0</span>, <span class="n">1.05</span>)
702759
card = make_map_card(tex.image)
703760
card.location = (-<span class="n">1.50</span>, <span class="n">0.0</span>, <span class="n">1.05</span>)
761+
plinths = [seat_on_plinth(ob, name) <span class="k">for</span> ob, name <span class="k">in</span>
762+
((card, <span class="s">&quot;CardPlinth&quot;</span>), (low, <span class="s">&quot;PlatePlinth&quot;</span>))]
704763

705764
floor_me = bpy.data.meshes.new(<span class="s">&quot;Floor&quot;</span>)
706765
bm = bmesh.new()
@@ -780,7 +839,7 @@ <h2>Source</h2>
780839
scene,
781840
cam,
782841
hero=[card, low],
783-
elements=[card, low],
842+
elements=[card, low] + plinths,
784843
stage=[floor, wall],
785844
)
786845
<span class="k">if</span> fcode:
@@ -840,7 +899,7 @@ <h2>Source</h2>
840899
</main>
841900
<dialog class="lightbox" id="lightbox" aria-label="Full-size render">
842901
<button class="lightbox-close" type="button" autofocus>Close</button>
843-
<img src="../assets/bake-normal-high-to-low-hero.webp" alt="A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern." />
902+
<img src="../assets/bake-normal-high-to-low-hero.webp" alt="A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern, both standing in low display plinths." />
844903
</dialog>
845904
<footer>
846905
<div class="statusbar">
50 Bytes
Loading
54.5 KB
Loading

‎docs/gallery/index.html‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ <h2><a href="modular-kit-snap/">modular-kit-snap</a></h2>
816816
</article>
817817
<article class="card" data-tags="uv game-pipeline rendering">
818818
<a class="card-media" href="lightmap-uv-channel/" tabindex="-1" aria-hidden="true">
819-
<img src="assets/lightmap-uv-channel-hero.webp" alt="A wooden covered cart beside a board showing its packed lightmap UV atlas as coloured islands." loading="lazy" decoding="async" />
819+
<img src="assets/lightmap-uv-channel-hero.webp" alt="A wooden covered cart, its four posts carrying an arched canvas canopy, beside a board showing its packed lightmap UV atlas as coloured islands." loading="lazy" decoding="async" />
820820
</a>
821821
<div class="card-body">
822822
<h2><a href="lightmap-uv-channel/">lightmap-uv-channel</a></h2>
@@ -882,7 +882,7 @@ <h2><a href="gn-zone-iterate/">gn-zone-iterate</a></h2>
882882
</article>
883883
<article class="card" data-tags="mesh">
884884
<a class="card-media" href="bake-normal-high-to-low/" tabindex="-1" aria-hidden="true">
885-
<img src="assets/bake-normal-high-to-low-hero.webp" alt="A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern." loading="lazy" decoding="async" />
885+
<img src="assets/bake-normal-high-to-low-hero.webp" alt="A baked tangent-space normal map shown as a lilac card beside a bronze plate wearing it, with a radial embossed pattern, both standing in low display plinths." loading="lazy" decoding="async" />
886886
</a>
887887
<div class="card-body">
888888
<h2><a href="bake-normal-high-to-low/">bake-normal-high-to-low</a></h2>

0 commit comments

Comments
 (0)