Add new node asset scripts for geometry and shader operations

- Implemented `build_mesh_plane.py` to create a geometry node group for mesh planes with customizable parameters.
- Created `build_shadeless.py` for a shader node group that displays color without scene lighting while preserving shadows and reflections.
- Added `validate.py` to validate the integrity of the newly created node groups and their inputs.
- Introduced `validate_cutout.py` to ensure the functionality of cutout node groups and their dependencies.
- Developed `validate_mesh_plane.py` to test the mesh plane creation and its modifier settings.
This commit is contained in:
2026-08-30 00:17:29 +08:00
parent 7d39fe8c5e
commit 32bcd45d7b
168 changed files with 7213 additions and 13121 deletions

View File

@@ -1,10 +1 @@
from .depth import write_da3_depth, write_moge_depth
from .surface import write_normal_texture, write_surface_archive
__all__ = (
"write_da3_depth",
"write_moge_depth",
"write_normal_texture",
"write_surface_archive",
)
"""Debug output serializers used by Job Server workflows."""

View File

@@ -1,64 +0,0 @@
from pathlib import Path
from .surface import write_normal_texture
def write_da3_depth(prediction, output_path):
import numpy as np
values = {"depth": np.round(prediction.depth, 8)}
for name in ("conf", "extrinsics", "intrinsics"):
value = getattr(prediction, name, None)
if value is not None:
values[name] = np.round(value, 2) if name == "conf" else value
output_path = Path(output_path)
output_path.parent.mkdir(parents=True, exist_ok=True)
np.savez_compressed(output_path, **values)
return output_path
def write_moge_depth(output_directory, prediction):
import numpy as np
output_directory = Path(output_directory)
np.savez(
output_directory / "results.npz",
**prediction.archive_values(),
)
for index, (depth, normal, mask) in enumerate(
zip(prediction.depth, prediction.normal, prediction.mask)
):
_write_moge_maps(
output_directory,
None if len(prediction.depth) == 1 else index,
depth,
normal,
mask,
)
def _write_moge_maps(output_directory, index, depth, normal, mask):
import numpy as np
from PIL import Image
suffix = "" if index is None else f".{index + 1:04d}"
valid = mask & np.isfinite(depth) & (depth > 0)
preview = np.zeros(depth.shape, dtype=np.uint8)
if np.any(valid):
low, high = np.percentile(depth[valid], (2.0, 98.0))
span = max(float(high - low), 1e-6)
preview[valid] = np.clip(
(depth[valid] - low) / span * 255.0,
0.0,
255.0,
).astype(np.uint8)
Image.fromarray(preview, mode="L").save(
output_directory / f"depth{suffix}.png"
)
write_normal_texture(
normal,
output_directory / f"normal{suffix}.png",
)
Image.fromarray(mask.astype(np.uint8) * 255, mode="L").save(
output_directory / f"mask{suffix}.png"
)

View File

@@ -1,35 +0,0 @@
from pathlib import Path
def write_surface_archive(mesh, output_path):
import numpy as np
output_path = Path(output_path)
output_path.parent.mkdir(parents=True, exist_ok=True)
np.savez_compressed(
output_path,
vertices=mesh.vertices,
faces=mesh.faces,
uv=mesh.uv,
intrinsics=mesh.intrinsics,
image_size=np.asarray(mesh.image_size, dtype=np.int32),
reference_depth=np.asarray(mesh.reference_depth, dtype=np.float32),
**mesh.point_attributes,
**mesh.face_attributes,
)
return output_path
def write_normal_texture(normal, output_path):
import numpy as np
from PIL import Image
normal_rgb = np.clip(
(normal * np.array([1.0, -1.0, -1.0], dtype=np.float32) + 1.0)
* 127.5,
0.0,
255.0,
).astype(np.uint8)
output_path = Path(output_path)
Image.fromarray(normal_rgb, mode="RGB").save(output_path)
return output_path