feat: Add new Geometry Nodes groups for image relief and shadeless shader

- Implemented the "O Image Relief Plane" Geometry Nodes group to create a fixed-base image relief using depth images and various parameters.
- Created the "O Shadeless" shader node group to display color without scene lighting while preserving shadows and reflections.
- Introduced a preview feature for node groups, allowing for interactive visualization of node arrangements in an HTML format.
- Added a template HTML file for rendering node previews with customizable views and controls.
This commit is contained in:
2026-09-09 21:24:57 +08:00
parent f5aff50b13
commit 89087fc2e2
118 changed files with 5635 additions and 3130 deletions

View File

@@ -120,13 +120,38 @@ def test_diagonal_pixels_share_a_component():
assert result.depth[5, 5] == 2
def test_invalid_donors_are_excluded():
@pytest.mark.parametrize("validity", [0.0, 0.2, 0.5])
def test_invalid_donors_are_excluded(validity):
frame, alpha = silhouette()
frame.depth[10, 12] = 100
frame.validity[10, 12] = 0
frame.depth[10, 6] = 100
frame.validity[10, 6] = validity
result = extend_edge_depth(frame, alpha)
assert result.depth[10, 12] == 2
assert result.validity[10, 12] == 0
assert result.depth[10, 4] == 2
assert result.depth[10, 6] == 100
assert result.validity[10, 6] == np.float32(validity)
def test_internal_mask_hole_does_not_expand_alpha_repair():
frame, alpha = silhouette()
frame.depth[9:14, 10:15] = 100
frame.validity[9:14, 10:15] = 0
original = frame.depth.copy()
result = extend_edge_depth(frame, alpha)
np.testing.assert_array_equal(result.depth[6:19, 6:20], original[6:19, 6:20])
assert result.depth[12, 24] == 2
def test_opaque_image_keeps_low_mask_depth():
frame = make_frame(np.ones((10, 10)))
frame.depth[5, 5] = 100
frame.validity[5, 5] = 0
assert extend_edge_depth(frame, np.ones((10, 10))) is frame
def test_component_without_valid_donors_keeps_its_depth():
frame, alpha = silhouette()
frame.validity[alpha > 0] = 0
assert extend_edge_depth(frame, alpha) is frame
def test_local_smoothing_reduces_donor_step_and_preserves_core():
@@ -159,16 +184,16 @@ def test_alpha_resize_retains_threshold_values(tmp_path):
@pytest.mark.parametrize(
"generate_depth,normal_mode,correct",
"generate_depth,normal_mode",
[
(True, "OBJECT", True),
(True, "TANGENT", True),
(True, "TANGENT", False),
(False, "OBJECT", True),
(True, "OBJECT"),
(True, "TANGENT"),
(True, "NONE"),
(False, "OBJECT"),
],
)
def test_artifacts_use_corrected_depth_and_original_normals(
tmp_path, generate_depth, normal_mode, correct
tmp_path, generate_depth, normal_mode
):
frame, alpha = silhouette()
rgba = np.full((*alpha.shape, 4), 255, np.uint8)
@@ -197,17 +222,18 @@ def test_artifacts_use_corrected_depth_and_original_normals(
):
artifacts.generate_moge2_artifacts(
context, {}, path, generate_depth=generate_depth, normal_mode=normal_mode,
correct_edge_depth=correct,
)
assert normal.call_args.args[0] is frame
assert repair.call_count == int(correct and generate_depth)
if normal_mode != "NONE":
assert normal.call_args.args[0] is frame
else:
normal.assert_not_called()
assert repair.call_count == int(generate_depth)
if generate_depth:
written_frame = depth.call_args.args[0]
np.testing.assert_array_equal(depth.call_args.kwargs["alpha"], alpha)
assert metadata.call_args.args[0] is written_frame
if correct:
assert written_frame.depth[12, 24] == 2
else:
assert written_frame is frame
assert written_frame.depth[12, 24] == 2
assert written_frame.validity is frame.validity
else:
metadata.assert_not_called()
depth.assert_not_called()