feat(cutout): implement boundary padding for cutout textures
- Introduced a new `Boundary Padding` preference in the Cutout Tool with a default of 2 px and a configurable range of 1-4 px. - Updated the Cutout client to establish inward mapping from the final Mask, sampling in a fixed direction and processing independent material RGBA and Depth. - Enhanced the handling of RGBA and Depth during cutout operations, ensuring proper mapping and preservation of source data. - Added tests to validate the new boundary padding functionality and its integration with existing cutout processes. feat(geometry): remove overall mesh smoothing from geometry nodes - Removed the `Smooth` input from several geometry node groups to eliminate unnecessary overall mesh smoothing. - Retained `Smooth Weight` for depth nodes while removing it from Cutout and Relief Plane nodes. - Ensured that boundary, normal, and fill smoothing behaviors remain intact and consistent. - Updated tests and documentation to reflect the changes in node interfaces and behaviors. feat(normals): scale tangent normals with depth - Reused the existing `o_normal_reduction` attribute to adjust Tangent Normal strength based on the geometry's `Depth Scale`. - Ensured that Tangent Normal strength is consistent with the geometry depth, preserving full strength for materials that do not provide the attribute. - Updated tests to verify the correct behavior of normal strength adjustments in both Tangent and Object Space.
This commit is contained in:
@@ -18,18 +18,22 @@ def test_saved_parameter_descriptions_match_definitions():
|
||||
parameters = {
|
||||
"O Image Plane": {"Subdivide"},
|
||||
"O Image Depth Plane": {
|
||||
"Subdivide", "Thickness", "Depth Split", "Smooth", "Smooth Weight",
|
||||
"Subdivide", "Thickness", "Depth Split", "Smooth Weight",
|
||||
"Depth Mask", "Mask Threshold", "Boundary Smooth",
|
||||
},
|
||||
"O Image Relief Plane": {"Subdivide", "Thickness", "Smooth", "Smooth Weight"},
|
||||
"O Image Cutout": {"Thickness", "Smooth", "Smooth Weight"},
|
||||
"O Image Relief Plane": {
|
||||
"Subdivide", "Thickness", "Depth Direction", "Depth Offset",
|
||||
},
|
||||
"O Image Cutout": {"Thickness"},
|
||||
"O Image Depth Cutout": {
|
||||
"Thickness", "Depth Split", "Smooth", "Smooth Weight",
|
||||
"Thickness", "Depth Split", "Smooth Weight",
|
||||
"Boundary Smooth", "Normal Smooth", "Front Inflation",
|
||||
},
|
||||
"O Image Cutout Symmetry": {"Symmetry Direction", "Depth Offset", "Fill Sides", "Fill Smooth"},
|
||||
"O Image Cutout Symmetry": {
|
||||
"Direction", "Offset", "Scale", "Fill Sides", "Fill Smooth",
|
||||
},
|
||||
"O Image Depth Panorama": {
|
||||
"Subdivide", "Depth Scale", "Depth Split", "Smooth", "Smooth Weight",
|
||||
"Subdivide", "Depth Scale", "Depth Split", "Smooth Weight",
|
||||
"Depth Mask", "Mask Threshold", "Boundary Smooth", "Invalid Distance",
|
||||
},
|
||||
"O Image Layer": {"Alpha Fix", "Normal Scale", "Bump Scale", "Object Space"},
|
||||
@@ -48,18 +52,54 @@ def test_saved_parameter_descriptions_match_definitions():
|
||||
]
|
||||
assert {item.name for item in sockets} == parameters[group.name]
|
||||
assert all(item.description for item in sockets), group.name
|
||||
input_names = {
|
||||
item.name for item in group.interface.items_tree
|
||||
if item.item_type == "SOCKET" and item.in_out == "INPUT"
|
||||
}
|
||||
input_items = [
|
||||
item for item in group.interface.items_tree
|
||||
if item.item_type == "SOCKET" and item.in_out == "INPUT"
|
||||
]
|
||||
if group.name in {
|
||||
"O Image Cutout", "O Image Depth Cutout", "O Image Depth Plane",
|
||||
"O Image Depth Panorama", "O Image Relief Plane",
|
||||
}:
|
||||
assert "Smooth" not in input_names
|
||||
if group.name in {"O Image Cutout", "O Image Relief Plane"}:
|
||||
assert "Smooth Weight" not in input_names
|
||||
if group.name in {"O Image Depth Plane", "O Image Depth Cutout"}:
|
||||
boundary = next(item for item in sockets if item.name == "Boundary Smooth")
|
||||
assert boundary.default_value == 4
|
||||
assert boundary.min_value == 0
|
||||
assert boundary.max_value == 16
|
||||
assert boundary.parent.name == "Options"
|
||||
if group.name == "O Image Depth Plane":
|
||||
depth_scale = next(item for item in input_items if item.name == "Depth Scale")
|
||||
assert (depth_scale.min_value, depth_scale.max_value) == (0.0, 2.0)
|
||||
if group.name == "O Image Depth Panorama":
|
||||
defaults = {item.name: item.default_value for item in sockets
|
||||
if item.name in {"Subdivide", "Depth Split", "Boundary Smooth"}}
|
||||
assert defaults == pytest.approx({
|
||||
"Subdivide": 8, "Depth Split": 0.1, "Boundary Smooth": 2,
|
||||
})
|
||||
boundary = next(item for item in input_items if item.name == "Boundary Smooth")
|
||||
assert (boundary.min_value, boundary.max_value) == (0, 16)
|
||||
if group.name == "O Image Relief Plane":
|
||||
names = [item.name for item in group.interface.items_tree
|
||||
if item.item_type == "SOCKET" and item.in_out == "INPUT"]
|
||||
start = names.index("Thickness")
|
||||
assert names[start:start + 4] == [
|
||||
"Thickness", "Depth Direction", "Depth Offset", "Depth Scale",
|
||||
]
|
||||
thickness = next(item for item in sockets if item.name == "Thickness")
|
||||
direction = next(item for item in sockets if item.name == "Depth Direction")
|
||||
offset = next(item for item in sockets if item.name == "Depth Offset")
|
||||
assert offset.default_value == pytest.approx(1.0)
|
||||
assert (offset.min_value, offset.max_value) == (-10.0, 10.0)
|
||||
assert offset.subtype == "DISTANCE"
|
||||
assert direction.parent == thickness.parent == offset.parent
|
||||
depth_scale = next(item for item in input_items if item.name == "Depth Scale")
|
||||
assert (depth_scale.min_value, depth_scale.max_value) == (0.0, 2.0)
|
||||
if "Depth Mask" in parameters[group.name]:
|
||||
names = [item.name for item in group.interface.items_tree
|
||||
if item.item_type == "SOCKET" and item.in_out == "INPUT"]
|
||||
@@ -71,8 +111,15 @@ def test_saved_parameter_descriptions_match_definitions():
|
||||
assert [item.name for item in mode.enum_items] == ["Balloon", "Shell"]
|
||||
thickness = [item.description for item in sockets if item.name == "Thickness"]
|
||||
assert len(thickness) == 2 and len(set(thickness)) == 2
|
||||
thicknesses = [item for item in input_items if item.name == "Thickness"]
|
||||
balloon = next(item for item in thicknesses if item.subtype == "NONE")
|
||||
shell = next(item for item in thicknesses if item.subtype == "DISTANCE")
|
||||
assert (balloon.min_value, balloon.max_value) == (0.0, 2.0)
|
||||
assert (shell.min_value, shell.max_value) == (0.0, 1.0)
|
||||
if group.name == "O Image Depth Cutout":
|
||||
assert all(item.default_value == 0 for item in sockets if item.name == "Thickness")
|
||||
depth_scale = next(item for item in input_items if item.name == "Depth Scale")
|
||||
assert (depth_scale.min_value, depth_scale.max_value) == (0.0, 2.0)
|
||||
assert not {"Outline Depth Fix", "Center Smooth", "Center Subdivide", "Show Center"} & {
|
||||
item.name for item in group.interface.items_tree if item.item_type == "SOCKET"
|
||||
}
|
||||
@@ -83,6 +130,13 @@ def test_saved_parameter_descriptions_match_definitions():
|
||||
assert normal_smooth.min_value == 16
|
||||
assert normal_smooth.max_value == 512
|
||||
assert normal_smooth.parent.name == "Options"
|
||||
if group.name == "O Image Cutout Symmetry":
|
||||
offset = next(item for item in input_items if item.name == "Offset")
|
||||
scale = next(item for item in input_items if item.name == "Scale")
|
||||
fill_smooth = next(item for item in input_items if item.name == "Fill Smooth")
|
||||
assert (offset.min_value, offset.max_value) == (-10.0, 10.0)
|
||||
assert (scale.min_value, scale.max_value) == (0.0, 2.0)
|
||||
assert (fill_smooth.min_value, fill_smooth.max_value) == (0, 16)
|
||||
result[group.name] = [
|
||||
(item.identifier, item.name, item.description) for item in sockets
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user