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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ toward the core (dot ≥ 0.998).
</tr>
<tr>
<td width="46%" valign="middle">
<a href="examples/color-attribute-wheel/"><img src="examples/color-attribute-wheel/preview.webp" alt="Color attribute wheel: an HSV color wheel disc with a white center fading into a vivid rainbow rim, resting on a dark studio floor" /></a>
<a href="examples/color-attribute-wheel/"><img src="examples/color-attribute-wheel/preview.webp" alt="Color attribute wheel: an HSV color wheel disc with a white center fading into a vivid rainbow rim, leaning upright toward the camera on a dark studio floor with a warm light pool behind it" /></a>
</td>
<td valign="middle">

Expand Down
20 changes: 14 additions & 6 deletions docs/gallery/armature-bend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,8 @@ <h2>Source</h2>
fmat = bpy.data.materials.new(<span class="s">&quot;Studio&quot;</span>)
fmat.use_nodes = <span class="k">True</span>
fb = fmat.node_tree.nodes[<span class="s">&quot;Principled BSDF&quot;</span>]
fb.inputs[<span class="s">&quot;Base Color&quot;</span>].default_value = (<span class="n">0.05</span>, <span class="n">0.055</span>, <span class="n">0.065</span>, <span class="n">1.0</span>)
fb.inputs[<span class="s">&quot;Roughness&quot;</span>].default_value = <span class="n">0.55</span>
fb.inputs[<span class="s">&quot;Base Color&quot;</span>].default_value = (<span class="n">0.03</span>, <span class="n">0.032</span>, <span class="n">0.037</span>, <span class="n">1.0</span>)
fb.inputs[<span class="s">&quot;Roughness&quot;</span>].default_value = <span class="n">0.7</span>
floor_me.materials.append(fmat)
floor = bpy.data.objects.new(<span class="s">&quot;Floor&quot;</span>, floor_me)
scene.collection.objects.link(floor)
Expand All @@ -446,7 +446,7 @@ <h2>Source</h2>

world = bpy.data.worlds.new(<span class="s">&quot;World&quot;</span>)
world.use_nodes = <span class="k">True</span>
world.node_tree.nodes[<span class="s">&quot;Background&quot;</span>].inputs[<span class="s">&quot;Color&quot;</span>].default_value = (<span class="n">0.03</span>, <span class="n">0.033</span>, <span class="n">0.04</span>, <span class="n">1.0</span>)
world.node_tree.nodes[<span class="s">&quot;Background&quot;</span>].inputs[<span class="s">&quot;Color&quot;</span>].default_value = (<span class="n">0.02</span>, <span class="n">0.021</span>, <span class="n">0.025</span>, <span class="n">1.0</span>)
scene.world = world

<span class="k">def</span> light(name, loc, energy, size, col, rot):
Expand All @@ -457,9 +457,14 @@ <h2>Source</h2>
ob.rotation_euler = tuple(math.radians(a) <span class="k">for</span> a <span class="k">in</span> rot)
scene.collection.objects.link(ob)

light(<span class="s">&quot;Key&quot;</span>, (-<span class="n">4.0</span>, -<span class="n">5.0</span>, <span class="n">6.0</span>), <span class="n">1500.0</span>, <span class="n">7.0</span>, (<span class="n">1.0</span>, <span class="n">0.97</span>, <span class="n">0.92</span>), (<span class="n">48</span>, <span class="n">0</span>, -<span class="n">38</span>))
light(<span class="s">&quot;Fill&quot;</span>, (<span class="n">5.0</span>, -<span class="n">4.0</span>, <span class="n">3.0</span>), <span class="n">500.0</span>, <span class="n">9.0</span>, (<span class="n">0.75</span>, <span class="n">0.85</span>, <span class="n">1.0</span>), (<span class="n">62</span>, <span class="n">0</span>, <span class="n">50</span>))
light(<span class="s">&quot;Rim&quot;</span>, (<span class="n">0.5</span>, <span class="n">4.5</span>, <span class="n">5.0</span>), <span class="n">900.0</span>, <span class="n">5.0</span>, (<span class="n">0.55</span>, <span class="n">0.75</span>, <span class="n">1.0</span>), (-<span class="n">55</span>, <span class="n">0</span>, <span class="n">175</span>))
<span class="c"># a shaped warm key from the upper left, a faint cool fill so the shadow</span>
<span class="c"># side of each tube stays legible, a cool rim to lift the silhouettes off</span>
<span class="c"># the backdrop, and a warm wedge raking the back wall — the falloff pool</span>
<span class="c"># behind the subjects that the rest of the gallery stages against.</span>
light(<span class="s">&quot;Key&quot;</span>, (-<span class="n">4.0</span>, -<span class="n">5.0</span>, <span class="n">6.0</span>), <span class="n">650.0</span>, <span class="n">4.5</span>, (<span class="n">1.0</span>, <span class="n">0.96</span>, <span class="n">0.9</span>), (<span class="n">48</span>, <span class="n">0</span>, -<span class="n">38</span>))
light(<span class="s">&quot;Fill&quot;</span>, (<span class="n">5.0</span>, -<span class="n">4.0</span>, <span class="n">3.0</span>), <span class="n">110.0</span>, <span class="n">9.0</span>, (<span class="n">0.75</span>, <span class="n">0.85</span>, <span class="n">1.0</span>), (<span class="n">62</span>, <span class="n">0</span>, <span class="n">50</span>))
light(<span class="s">&quot;Rim&quot;</span>, (<span class="n">0.5</span>, <span class="n">4.5</span>, <span class="n">5.0</span>), <span class="n">350.0</span>, <span class="n">4.0</span>, (<span class="n">0.6</span>, <span class="n">0.78</span>, <span class="n">1.0</span>), (-<span class="n">55</span>, <span class="n">0</span>, <span class="n">175</span>))
light(<span class="s">&quot;Wedge&quot;</span>, (<span class="n">2.5</span>, <span class="n">3.5</span>, <span class="n">4.2</span>), <span class="n">520.0</span>, <span class="n">6.0</span>, (<span class="n">1.0</span>, <span class="n">0.76</span>, <span class="n">0.5</span>), (-<span class="n">72</span>, <span class="n">0</span>, <span class="n">195</span>))

cam_data = bpy.data.cameras.new(<span class="s">&quot;Cam&quot;</span>)
cam_data.lens = <span class="n">45.0</span>
Expand All @@ -481,6 +486,9 @@ <h2>Source</h2>
scene.render.resolution_y = <span class="n">720</span>
scene.render.image_settings.file_format = <span class="s">&#x27;PNG&#x27;</span>
scene.render.filepath = path
<span class="c"># AgX (the 4.x/5.x default) desaturates the BoneTint bands toward pastel,</span>
<span class="c"># hiding exactly the weight boundaries the LBS check asserts.</span>
scene.view_settings.view_transform = <span class="s">&#x27;Standard&#x27;</span>
bpy.ops.render.render(write_still=<span class="k">True</span>)
<span class="k">return</span> os.path.exists(path) <span class="k">and</span> os.path.getsize(path) &gt; <span class="n">0</span>

Expand Down
Binary file modified docs/gallery/assets/armature-bend-hero.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 modified docs/gallery/assets/color-attribute-wheel-hero.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 24 additions & 7 deletions docs/gallery/color-attribute-wheel/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,15 @@ <h2>Source</h2>
<span class="s">&quot;&quot;&quot;Vertex coords and per-vertex (h, s, v) in the same order as vidx().&quot;&quot;&quot;</span>
coords = [(<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">0.0</span>)]
hsv = [(<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">1.0</span>)] <span class="c"># center: fully desaturated, white</span>
<span class="c"># the hue origin is rotated off the picture horizontal: red is the</span>
<span class="c"># perceptually sharpest hue transition, and the 0/360-degree wrap reads</span>
<span class="c"># as a seam artifact when it lies level in frame</span>
angle0 = math.radians(-<span class="n">52.0</span>)
<span class="k">for</span> r <span class="k">in</span> range(<span class="n">1</span>, RINGS + <span class="n">1</span>):
radius = R_OUTER * r / RINGS
sat = min(<span class="n">1.0</span>, (r / RINGS) * <span class="n">1.4</span>)
<span class="k">for</span> s <span class="k">in</span> range(SEGMENTS):
angle = <span class="n">2.0</span> * math.pi * s / SEGMENTS
angle = angle0 + <span class="n">2.0</span> * math.pi * s / SEGMENTS
coords.append((radius * math.cos(angle), radius * math.sin(angle), <span class="n">0.0</span>))
hsv.append((s / SEGMENTS, sat, <span class="n">1.0</span>))
<span class="k">return</span> coords, hsv
Expand Down Expand Up @@ -360,7 +364,11 @@ <h2>Source</h2>
<span class="k">if</span> <span class="s">&quot;Emission Color&quot;</span> <span class="k">in</span> bsdf.inputs: <span class="c"># Principled gained built-in emission in 4.x+</span>
nt.links.new(attr_node.outputs[<span class="s">&quot;Color&quot;</span>], bsdf.inputs[<span class="s">&quot;Emission Color&quot;</span>])
bsdf.inputs[<span class="s">&quot;Emission Strength&quot;</span>].default_value = <span class="n">0.12</span>
bsdf.inputs[<span class="s">&quot;Roughness&quot;</span>].default_value = <span class="n">0.62</span>
<span class="c"># fully matte: any specular component reflects the wall/floor horizon as</span>
<span class="c"># a hard line across the disc face</span>
bsdf.inputs[<span class="s">&quot;Roughness&quot;</span>].default_value = <span class="n">0.85</span>
<span class="k">if</span> <span class="s">&quot;Specular IOR Level&quot;</span> <span class="k">in</span> bsdf.inputs:
bsdf.inputs[<span class="s">&quot;Specular IOR Level&quot;</span>].default_value = <span class="n">0.0</span>

<span class="c"># The step AI code most often skips: the attribute must actually be wired</span>
<span class="c"># into the shader, not just present on the mesh.</span>
Expand All @@ -385,8 +393,11 @@ <h2>Source</h2>
<span class="k">if</span> mat <span class="k">is</span> <span class="k">None</span>:
<span class="k">return</span> <span class="k">False</span>
obj.data.materials.append(mat)
obj.location = (<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">0.55</span>)
obj.rotation_euler = (math.radians(<span class="n">14</span>), <span class="n">0.0</span>, math.radians(<span class="n">12</span>))
<span class="c"># stand the disc up toward the camera like an easel: the wheel is the</span>
<span class="c"># subject, so it should present nearly face-on and fill the frame instead</span>
<span class="c"># of lying foreshortened on the floor.</span>
obj.location = (<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">1.34</span>)
obj.rotation_euler = (math.radians(<span class="n">52</span>), <span class="n">0.0</span>, math.radians(<span class="n">10</span>))

floor_me = bpy.data.meshes.new(<span class="s">&quot;Floor&quot;</span>)
bm = bmesh.new()
Expand Down Expand Up @@ -424,9 +435,15 @@ <h2>Source</h2>
<span class="c"># a bright soft key from above reads the hue ring clearly; a low cool fill</span>
<span class="c"># keeps the shadow side legible; a faint warm rim separates the disc edge</span>
<span class="c"># from the dark backdrop without washing out the attribute colors.</span>
light(<span class="s">&quot;Key&quot;</span>, (-<span class="n">2.0</span>, -<span class="n">3.0</span>, <span class="n">5.5</span>), <span class="n">380.0</span>, <span class="n">11.0</span>, (<span class="n">1.0</span>, <span class="n">0.98</span>, <span class="n">0.96</span>), (<span class="n">58</span>, <span class="n">0</span>, -<span class="n">28</span>))
light(<span class="s">&quot;Fill&quot;</span>, (<span class="n">4.5</span>, -<span class="n">2.5</span>, <span class="n">1.6</span>), <span class="n">140.0</span>, <span class="n">9.0</span>, (<span class="n">0.78</span>, <span class="n">0.86</span>, <span class="n">1.0</span>), (<span class="n">68</span>, <span class="n">0</span>, <span class="n">55</span>))
light(<span class="s">&quot;Key&quot;</span>, (-<span class="n">2.0</span>, -<span class="n">3.0</span>, <span class="n">5.5</span>), <span class="n">320.0</span>, <span class="n">8.0</span>, (<span class="n">1.0</span>, <span class="n">0.98</span>, <span class="n">0.96</span>), (<span class="n">58</span>, <span class="n">0</span>, -<span class="n">28</span>))
light(<span class="s">&quot;Fill&quot;</span>, (<span class="n">4.5</span>, -<span class="n">2.5</span>, <span class="n">1.6</span>), <span class="n">90.0</span>, <span class="n">9.0</span>, (<span class="n">0.78</span>, <span class="n">0.86</span>, <span class="n">1.0</span>), (<span class="n">68</span>, <span class="n">0</span>, <span class="n">55</span>))
light(<span class="s">&quot;Rim&quot;</span>, (<span class="n">0.5</span>, <span class="n">3.6</span>, <span class="n">2.2</span>), <span class="n">170.0</span>, <span class="n">4.0</span>, (<span class="n">1.0</span>, <span class="n">0.78</span>, <span class="n">0.55</span>), (-<span class="n">70</span>, <span class="n">0</span>, <span class="n">175</span>))
<span class="c"># a warm wedge raking the back wall — the falloff pool behind the subject</span>
<span class="c"># the rest of the gallery stages against.</span>
<span class="c"># placed between the disc and the back wall so it can only rake the wall:</span>
<span class="c"># from any position in front, its grazing terminator draws a hard line</span>
<span class="c"># across the flat disc face.</span>
light(<span class="s">&quot;Wedge&quot;</span>, (<span class="n">2.0</span>, <span class="n">5.2</span>, <span class="n">3.6</span>), <span class="n">220.0</span>, <span class="n">6.0</span>, (<span class="n">1.0</span>, <span class="n">0.76</span>, <span class="n">0.5</span>), (-<span class="n">68</span>, <span class="n">0</span>, <span class="n">190</span>))

aim = bpy.data.objects.new(<span class="s">&quot;Aim&quot;</span>, <span class="k">None</span>)
aim.location = obj.location
Expand All @@ -435,7 +452,7 @@ <h2>Source</h2>
cam_data = bpy.data.cameras.new(<span class="s">&quot;Cam&quot;</span>)
cam_data.lens = <span class="n">50.0</span>
cam = bpy.data.objects.new(<span class="s">&quot;Cam&quot;</span>, cam_data)
cam.location = (<span class="n">0.0</span>, -<span class="n">7.4</span>, <span class="n">3.6</span>)
cam.location = (<span class="n">0.0</span>, -<span class="n">8.0</span>, <span class="n">2.4</span>)
con = cam.constraints.new(<span class="s">&#x27;TRACK_TO&#x27;</span>)
con.target = aim
con.track_axis = <span class="s">&#x27;TRACK_NEGATIVE_Z&#x27;</span>
Expand Down
8 changes: 4 additions & 4 deletions docs/gallery/grease-pencil-rosette/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>grease-pencil-rosette — Examples — Blender Developer Tools</title>
<meta name="description" content="Grease Pencil v3&#x27;s attribute-based API — layer → frames.new().drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves." />
<meta name="description" content="Grease Pencil v3&#x27;s attribute-based API — layer → frames.new(1).drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves." />
<link rel="canonical" href="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/grease-pencil-rosette/" />
<link rel="icon" href="../../assets/favicon.svg" type="image/svg+xml" />
<meta name="theme-color" content="#1a1b1e" />
<meta property="og:type" content="website" />
<meta property="og:title" content="grease-pencil-rosette — Examples — Blender Developer Tools" />
<meta property="og:description" content="Grease Pencil v3&#x27;s attribute-based API — layer → frames.new().drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves." />
<meta property="og:description" content="Grease Pencil v3&#x27;s attribute-based API — layer → frames.new(1).drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves." />
<meta property="og:url" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/grease-pencil-rosette/" />
<meta property="og:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/grease-pencil-rosette-hero.webp" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="grease-pencil-rosette — Examples — Blender Developer Tools" />
<meta name="twitter:description" content="Grease Pencil v3&#x27;s attribute-based API — layer → frames.new().drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves." />
<meta name="twitter:description" content="Grease Pencil v3&#x27;s attribute-based API — layer → frames.new(1).drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves." />
<meta name="twitter:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/grease-pencil-rosette-hero.webp" />
<style>
/* fonts are deployed by the landing build (docs/fonts/) */
Expand Down Expand Up @@ -170,7 +170,7 @@
</div>
<header class="hero">
<h1>grease-pencil-rosette</h1>
<p>Grease Pencil v3&#x27;s attribute-based API — layer → frames.new().drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves.</p>
<p>Grease Pencil v3&#x27;s attribute-based API — layer → frames.new(1).drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves.</p>
</header>
<main id="main">
<button class="detail-hero" id="heroZoom" type="button" aria-label="Zoom grease-pencil-rosette render">
Expand Down
2 changes: 1 addition & 1 deletion docs/gallery/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ <h2><a href="parent-inverse-orrery/">parent-inverse-orrery</a></h2>
</a>
<div class="card-body">
<h2><a href="grease-pencil-rosette/">grease-pencil-rosette</a></h2>
<p class="teaches">Grease Pencil v3&#x27;s attribute-based API — layer → frames.new().drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves.</p>
<p class="teaches">Grease Pencil v3&#x27;s attribute-based API — layer → frames.new(1).drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves.</p>
<p class="witnesses"><span class="tag">witnesses</span> The GPv3 address break: 4.5 keeps GPv3 at grease_pencils_v3 while grease_pencils is still legacy GPencil (frame.strokes, no .drawing); 5.x deletes legacy and GPv3 takes over the grease_pencils name. Point writes lazily materialize attribute layers, and every position round-trips through the raw POINT buffer.</p>
<a class="card-link" href="grease-pencil-rosette/">View example <span aria-hidden="true">&rarr;</span></a>
</div>
Expand Down
Loading
Loading