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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ non-destructive path.
<table>
<tr>
<td width="46%" valign="middle">
<a href="examples/bmesh-gear/"><img src="examples/bmesh-gear/preview.webp" alt="Bmesh gear: a machined steel 14-tooth gear at a three-quarter angle on a dark studio floor" /></a>
<a href="examples/bmesh-gear/"><img src="examples/bmesh-gear/preview.webp" alt="Bmesh gear: a machined brass 14-tooth gear with concentric turning marks catching the light, tilted at a three-quarter angle on a dark studio floor" /></a>
</td>
<td valign="middle">

Expand Down Expand Up @@ -251,7 +251,7 @@ semver on LTS builds (`"4.5.11 LTS"`), and that a Mesh reference dies at
</tr>
<tr>
<td width="46%" valign="middle">
<a href="examples/depsgraph-export/"><img src="examples/depsgraph-export/preview.webp" alt="Depsgraph-evaluated export: a matte graphite base cube beside its glossy green subdivision-surface evaluated form on a dark studio floor" /></a>
<a href="examples/depsgraph-export/"><img src="examples/depsgraph-export/preview.webp" alt="Depsgraph-evaluated export: a teal base cube beside the smooth teal sphere of its subdivision-surface evaluated form - one shared material, two silhouettes - on a dark studio floor with a warm light pool behind" /></a>
</td>
<td valign="middle">

Expand Down
Binary file modified docs/gallery/assets/bmesh-gear-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/depsgraph-export-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/gn-sdf-remesh-hero.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 25 additions & 7 deletions docs/gallery/bmesh-gear/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -295,15 +295,31 @@ <h2>Source</h2>
scene = bpy.context.scene
<span class="k">for</span> poly <span class="k">in</span> obj.data.polygons:
poly.use_smooth = <span class="k">False</span> <span class="c"># crisp machined facets</span>
mat = bpy.data.materials.new(<span class="s">&quot;Steel&quot;</span>)
<span class="c"># machined brass: a flat metal face lit by area lights renders as one</span>
<span class="c"># featureless gradient, so the finish carries the design — concentric</span>
<span class="c"># turning marks (a RINGS wave driving roughness) break the face into</span>
<span class="c"># rings that each catch the key at a different angle</span>
mat = bpy.data.materials.new(<span class="s">&quot;MachinedBrass&quot;</span>)
mat.use_nodes = <span class="k">True</span>
bsdf = mat.node_tree.nodes[<span class="s">&quot;Principled BSDF&quot;</span>]
bsdf.inputs[<span class="s">&quot;Base Color&quot;</span>].default_value = (<span class="n">0.75</span>, <span class="n">0.77</span>, <span class="n">0.8</span>, <span class="n">1.0</span>)
nt = mat.node_tree
bsdf = nt.nodes[<span class="s">&quot;Principled BSDF&quot;</span>]
bsdf.inputs[<span class="s">&quot;Base Color&quot;</span>].default_value = (<span class="n">0.72</span>, <span class="n">0.44</span>, <span class="n">0.16</span>, <span class="n">1.0</span>)
bsdf.inputs[<span class="s">&quot;Metallic&quot;</span>].default_value = <span class="n">1.0</span>
bsdf.inputs[<span class="s">&quot;Roughness&quot;</span>].default_value = <span class="n">0.45</span>
rings = nt.nodes.new(<span class="s">&quot;ShaderNodeTexWave&quot;</span>)
rings.wave_type = <span class="s">&#x27;RINGS&#x27;</span>
rings.rings_direction = <span class="s">&#x27;SPHERICAL&#x27;</span> <span class="c"># concentric from center, not X-axis bands</span>
rings.inputs[<span class="s">&quot;Scale&quot;</span>].default_value = <span class="n">16.0</span>
rings.inputs[<span class="s">&quot;Distortion&quot;</span>].default_value = <span class="n">0.5</span>
rough = nt.nodes.new(<span class="s">&quot;ShaderNodeMapRange&quot;</span>)
rough.inputs[<span class="s">&quot;From Min&quot;</span>].default_value = <span class="n">0.0</span>
rough.inputs[<span class="s">&quot;From Max&quot;</span>].default_value = <span class="n">1.0</span>
rough.inputs[<span class="s">&quot;To Min&quot;</span>].default_value = <span class="n">0.14</span>
rough.inputs[<span class="s">&quot;To Max&quot;</span>].default_value = <span class="n">0.36</span>
nt.links.new(rings.outputs[<span class="s">&quot;Fac&quot;</span>], rough.inputs[<span class="s">&quot;Value&quot;</span>])
nt.links.new(rough.outputs[<span class="s">&quot;Result&quot;</span>], bsdf.inputs[<span class="s">&quot;Roughness&quot;</span>])
obj.data.materials.append(mat)
obj.location = (<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">0.85</span>)
obj.rotation_euler = (math.radians(<span class="n">38</span>), <span class="n">0.0</span>, math.radians(<span class="n">22</span>))
obj.rotation_euler = (math.radians(<span class="n">46</span>), <span class="n">0.0</span>, math.radians(<span class="n">22</span>))

floor_me = bpy.data.meshes.new(<span class="s">&quot;Floor&quot;</span>)
bm = bmesh.new()
Expand Down Expand Up @@ -341,9 +357,11 @@ <h2>Source</h2>

<span class="c"># metals live on reflections: soft warm key, restrained cool fill, and the</span>
<span class="c"># warm wedge raking the back wall (docs/VISUAL-STYLE.md)</span>
light(<span class="s">&quot;Key&quot;</span>, (-<span class="n">3.5</span>, -<span class="n">4.5</span>, <span class="n">5.5</span>), <span class="n">700.0</span>, <span class="n">6.0</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">35</span>))
light(<span class="s">&quot;Fill&quot;</span>, (<span class="n">5.0</span>, -<span class="n">3.5</span>, <span class="n">2.5</span>), <span class="n">160.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">65</span>, <span class="n">0</span>, <span class="n">50</span>))
light(<span class="s">&quot;Key&quot;</span>, (-<span class="n">3.5</span>, -<span class="n">4.5</span>, <span class="n">5.5</span>), <span class="n">550.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">35</span>))
light(<span class="s">&quot;Fill&quot;</span>, (<span class="n">5.0</span>, -<span class="n">3.5</span>, <span class="n">2.5</span>), <span class="n">130.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">65</span>, <span class="n">0</span>, <span class="n">50</span>))
light(<span class="s">&quot;Wedge&quot;</span>, (<span class="n">2.5</span>, <span class="n">5.5</span>, <span class="n">4.0</span>), <span class="n">380.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>))
<span class="c"># a small hot glint: brass needs one crisp specular streak to read machined</span>
light(<span class="s">&quot;Glint&quot;</span>, (<span class="n">1.8</span>, -<span class="n">5.2</span>, <span class="n">6.2</span>), <span class="n">900.0</span>, <span class="n">0.9</span>, (<span class="n">1.0</span>, <span class="n">0.9</span>, <span class="n">0.7</span>), (<span class="n">40</span>, <span class="n">0</span>, <span class="n">18</span>))

cam_data = bpy.data.cameras.new(<span class="s">&quot;Cam&quot;</span>)
cam_data.lens = <span class="n">55.0</span>
Expand Down
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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 13 additions & 7 deletions docs/gallery/depsgraph-export/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,18 @@ <h2>Source</h2>
<span class="s">&quot;&quot;&quot;Base cube beside its evaluated form — the two counts the check compares.&quot;&quot;&quot;</span>
scene = bpy.context.scene

<span class="c"># one hero material on BOTH objects: the two silhouettes share a color so</span>
<span class="c"># the only visible difference is the thing the check measures — base-mesh</span>
<span class="c"># geometry versus the depsgraph-evaluated subsurf</span>
hero = principled(<span class="s">&quot;Teal&quot;</span>, (<span class="n">0.012</span>, <span class="n">0.30</span>, <span class="n">0.34</span>, <span class="n">1.0</span>), <span class="n">0.0</span>, <span class="n">0.2</span>)

<span class="c"># left: the base mesh, modifier-free (a plain copy of the datablock)</span>
base_obj = bpy.data.objects.new(<span class="s">&quot;Base&quot;</span>, obj.data.copy())
base_obj.location = (-<span class="n">1.7</span>, <span class="n">0.0</span>, <span class="n">1.0</span>)
base_obj.data.materials.append(
principled(<span class="s">&quot;Graphite&quot;</span>, (<span class="n">0.09</span>, <span class="n">0.10</span>, <span class="n">0.12</span>, <span class="n">1.0</span>), <span class="n">0.0</span>, <span class="n">0.55</span>))
<span class="c"># turned off camera-parallel so the key rakes the front face into a</span>
<span class="c"># gradient instead of one flat tone</span>
base_obj.rotation_euler = (<span class="n">0.0</span>, <span class="n">0.0</span>, math.radians(<span class="n">32</span>))
base_obj.data.materials.append(hero)
bpy.context.collection.objects.link(base_obj)

<span class="c"># right: the SUBSURF object — what the depsgraph evaluates and the OBJ ships.</span>
Expand All @@ -302,8 +309,7 @@ <h2>Source</h2>
bottom = min(v.co.z <span class="k">for</span> v <span class="k">in</span> em.vertices)
obj.evaluated_get(dg).to_mesh_clear()
obj.location = (<span class="n">1.8</span>, <span class="n">0.0</span>, -bottom)
obj.data.materials.append(
principled(<span class="s">&quot;EvalGreen&quot;</span>, (<span class="n">0.03</span>, <span class="n">0.32</span>, <span class="n">0.10</span>, <span class="n">1.0</span>), <span class="n">0.0</span>, <span class="n">0.15</span>))
obj.data.materials.append(hero)
<span class="k">for</span> poly <span class="k">in</span> obj.data.polygons:
poly.use_smooth = <span class="k">True</span>

Expand Down Expand Up @@ -345,10 +351,10 @@ <h2>Source</h2>
light(<span class="s">&quot;Wedge&quot;</span>, (<span class="n">2.5</span>, <span class="n">5.5</span>, <span class="n">4.0</span>), <span class="n">380.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>))

cam_data = bpy.data.cameras.new(<span class="s">&quot;Cam&quot;</span>)
cam_data.lens = <span class="n">46.0</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">8.2</span>, <span class="n">2.7</span>)
cam.rotation_euler = (math.radians(<span class="n">78</span>), <span class="n">0.0</span>, <span class="n">0.0</span>)
cam.location = (<span class="n">0.0</span>, -<span class="n">7.4</span>, <span class="n">3.0</span>)
cam.rotation_euler = (math.radians(<span class="n">76</span>), <span class="n">0.0</span>, <span class="n">0.0</span>)
scene.collection.objects.link(cam)
scene.camera = cam

Expand Down
15 changes: 9 additions & 6 deletions docs/gallery/gn-sdf-remesh/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ <h2>Source</h2>
p.use_smooth = <span class="k">True</span>
mat = bpy.data.materials.new(<span class="s">&quot;Ceramic&quot;</span>); mat.use_nodes = <span class="k">True</span>
b = mat.node_tree.nodes.get(<span class="s">&#x27;Principled BSDF&#x27;</span>)
b.inputs[<span class="s">&#x27;Base Color&#x27;</span>].default_value = (<span class="n">0.42</span>, <span class="n">0.028</span>, <span class="n">0.045</span>, <span class="n">1</span>) <span class="c"># crimson ceramic</span>
b.inputs[<span class="s">&#x27;Roughness&#x27;</span>].default_value = <span class="n">0.22</span>
b.inputs[<span class="s">&#x27;Base Color&#x27;</span>].default_value = (<span class="n">0.45</span>, <span class="n">0.025</span>, <span class="n">0.05</span>, <span class="n">1</span>) <span class="c"># crimson ceramic</span>
b.inputs[<span class="s">&#x27;Roughness&#x27;</span>].default_value = <span class="n">0.16</span> <span class="c"># glossy: the SDF facets read by their glints</span>
obj.data.materials.append(mat)
<span class="k">return</span> obj

Expand All @@ -275,12 +275,15 @@ <h2>Source</h2>
wall.rotation_euler = (<span class="n">1.5708</span>, <span class="n">0</span>, <span class="n">0</span>); bpy.context.collection.objects.link(wall)
w = bpy.data.worlds.new(<span class="s">&quot;W&quot;</span>); w.use_nodes = <span class="k">True</span>
w.node_tree.nodes[<span class="s">&quot;Background&quot;</span>].inputs[<span class="n">0</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</span>); sc.world = w
aim = bpy.data.objects.new(<span class="s">&quot;Aim&quot;</span>, <span class="k">None</span>); aim.location = (<span class="n">0</span>, <span class="n">0</span>, <span class="n">0.55</span>); bpy.context.collection.objects.link(aim)
cam = bpy.data.objects.new(<span class="s">&quot;cam&quot;</span>, bpy.data.cameras.new(<span class="s">&quot;cam&quot;</span>)); cam.location = (<span class="n">0</span>, -<span class="n">6.5</span>, <span class="n">2.2</span>)
aim = bpy.data.objects.new(<span class="s">&quot;Aim&quot;</span>, <span class="k">None</span>); aim.location = (<span class="n">0</span>, <span class="n">0</span>, <span class="n">0.5</span>); bpy.context.collection.objects.link(aim)
<span class="c"># off-axis and low: the remesh facets are the API evidence, and they only</span>
<span class="c"># read when a raking key skims them from the side</span>
cam = bpy.data.objects.new(<span class="s">&quot;cam&quot;</span>, bpy.data.cameras.new(<span class="s">&quot;cam&quot;</span>)); cam.location = (<span class="n">2.6</span>, -<span class="n">5.2</span>, <span class="n">1.5</span>)
bpy.context.collection.objects.link(cam); sc.camera = cam
c = cam.constraints.new(<span class="s">&#x27;TRACK_TO&#x27;</span>); c.target = aim; c.track_axis = <span class="s">&#x27;TRACK_NEGATIVE_Z&#x27;</span>; c.up_axis = <span class="s">&#x27;UP_Y&#x27;</span>
<span class="c"># shaped warm key, faint cool fill (docs/VISUAL-STYLE.md)</span>
<span class="k">for</span> nm, loc, en, sz, col <span class="k">in</span> [(<span class="s">&quot;K&quot;</span>, (-<span class="n">4</span>, -<span class="n">5</span>, <span class="n">7</span>), <span class="n">650</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="c"># low raking warm key so every facet catches a distinct glint, faint cool</span>
<span class="c"># fill (docs/VISUAL-STYLE.md)</span>
<span class="k">for</span> nm, loc, en, sz, col <span class="k">in</span> [(<span class="s">&quot;K&quot;</span>, (-<span class="n">5</span>, -<span class="n">3.5</span>, <span class="n">2.8</span>), <span class="n">480</span>, <span class="n">3.0</span>, (<span class="n">1.0</span>, <span class="n">0.96</span>, <span class="n">0.9</span>)),
(<span class="s">&quot;F2&quot;</span>, (<span class="n">5</span>, -<span class="n">4</span>, <span class="n">2</span>), <span class="n">110</span>, <span class="n">7.0</span>, (<span class="n">0.75</span>, <span class="n">0.85</span>, <span class="n">1.0</span>))]:
ld = bpy.data.lights.new(nm, <span class="s">&#x27;AREA&#x27;</span>); ld.energy = en; ld.size = sz; ld.color = col
lo = bpy.data.objects.new(nm, ld); lo.location = loc; bpy.context.collection.objects.link(lo)
Expand Down
32 changes: 25 additions & 7 deletions examples/bmesh-gear/bmesh_gear.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,31 @@ def render_still(obj, path, engine):
scene = bpy.context.scene
for poly in obj.data.polygons:
poly.use_smooth = False # crisp machined facets
mat = bpy.data.materials.new("Steel")
# machined brass: a flat metal face lit by area lights renders as one
# featureless gradient, so the finish carries the design — concentric
# turning marks (a RINGS wave driving roughness) break the face into
# rings that each catch the key at a different angle
mat = bpy.data.materials.new("MachinedBrass")
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
bsdf.inputs["Base Color"].default_value = (0.75, 0.77, 0.8, 1.0)
nt = mat.node_tree
bsdf = nt.nodes["Principled BSDF"]
bsdf.inputs["Base Color"].default_value = (0.72, 0.44, 0.16, 1.0)
bsdf.inputs["Metallic"].default_value = 1.0
bsdf.inputs["Roughness"].default_value = 0.45
rings = nt.nodes.new("ShaderNodeTexWave")
rings.wave_type = 'RINGS'
rings.rings_direction = 'SPHERICAL' # concentric from center, not X-axis bands
rings.inputs["Scale"].default_value = 16.0
rings.inputs["Distortion"].default_value = 0.5
rough = nt.nodes.new("ShaderNodeMapRange")
rough.inputs["From Min"].default_value = 0.0
rough.inputs["From Max"].default_value = 1.0
rough.inputs["To Min"].default_value = 0.14
rough.inputs["To Max"].default_value = 0.36
nt.links.new(rings.outputs["Fac"], rough.inputs["Value"])
nt.links.new(rough.outputs["Result"], bsdf.inputs["Roughness"])
obj.data.materials.append(mat)
obj.location = (0.0, 0.0, 0.85)
obj.rotation_euler = (math.radians(38), 0.0, math.radians(22))
obj.rotation_euler = (math.radians(46), 0.0, math.radians(22))

floor_me = bpy.data.meshes.new("Floor")
bm = bmesh.new()
Expand Down Expand Up @@ -139,9 +155,11 @@ def light(name, loc, energy, size, col, rot):

# metals live on reflections: soft warm key, restrained cool fill, and the
# warm wedge raking the back wall (docs/VISUAL-STYLE.md)
light("Key", (-3.5, -4.5, 5.5), 700.0, 6.0, (1.0, 0.96, 0.9), (48, 0, -35))
light("Fill", (5.0, -3.5, 2.5), 160.0, 9.0, (0.75, 0.85, 1.0), (65, 0, 50))
light("Key", (-3.5, -4.5, 5.5), 550.0, 4.5, (1.0, 0.96, 0.9), (48, 0, -35))
light("Fill", (5.0, -3.5, 2.5), 130.0, 9.0, (0.75, 0.85, 1.0), (65, 0, 50))
light("Wedge", (2.5, 5.5, 4.0), 380.0, 6.0, (1.0, 0.76, 0.5), (-68, 0, 190))
# a small hot glint: brass needs one crisp specular streak to read machined
light("Glint", (1.8, -5.2, 6.2), 900.0, 0.9, (1.0, 0.9, 0.7), (40, 0, 18))

cam_data = bpy.data.cameras.new("Cam")
cam_data.lens = 55.0
Expand Down
Binary file modified examples/bmesh-gear/preview.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 13 additions & 7 deletions examples/depsgraph-export/depsgraph_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,18 @@ def render_still(obj, path, engine):
"""Base cube beside its evaluated form — the two counts the check compares."""
scene = bpy.context.scene

# one hero material on BOTH objects: the two silhouettes share a color so
# the only visible difference is the thing the check measures — base-mesh
# geometry versus the depsgraph-evaluated subsurf
hero = principled("Teal", (0.012, 0.30, 0.34, 1.0), 0.0, 0.2)

# left: the base mesh, modifier-free (a plain copy of the datablock)
base_obj = bpy.data.objects.new("Base", obj.data.copy())
base_obj.location = (-1.7, 0.0, 1.0)
base_obj.data.materials.append(
principled("Graphite", (0.09, 0.10, 0.12, 1.0), 0.0, 0.55))
# turned off camera-parallel so the key rakes the front face into a
# gradient instead of one flat tone
base_obj.rotation_euler = (0.0, 0.0, math.radians(32))
base_obj.data.materials.append(hero)
bpy.context.collection.objects.link(base_obj)

# right: the SUBSURF object — what the depsgraph evaluates and the OBJ ships.
Expand All @@ -97,8 +104,7 @@ def render_still(obj, path, engine):
bottom = min(v.co.z for v in em.vertices)
obj.evaluated_get(dg).to_mesh_clear()
obj.location = (1.8, 0.0, -bottom)
obj.data.materials.append(
principled("EvalGreen", (0.03, 0.32, 0.10, 1.0), 0.0, 0.15))
obj.data.materials.append(hero)
for poly in obj.data.polygons:
poly.use_smooth = True

Expand Down Expand Up @@ -140,10 +146,10 @@ def light(name, loc, energy, size, col, rot):
light("Wedge", (2.5, 5.5, 4.0), 380.0, 6.0, (1.0, 0.76, 0.5), (-68, 0, 190))

cam_data = bpy.data.cameras.new("Cam")
cam_data.lens = 46.0
cam_data.lens = 50.0
cam = bpy.data.objects.new("Cam", cam_data)
cam.location = (0.0, -8.2, 2.7)
cam.rotation_euler = (math.radians(78), 0.0, 0.0)
cam.location = (0.0, -7.4, 3.0)
cam.rotation_euler = (math.radians(76), 0.0, 0.0)
scene.collection.objects.link(cam)
scene.camera = cam

Expand Down
Binary file modified examples/depsgraph-export/preview.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading