From ac817a9a05e82da6c9a1ca05321acab386e161fb Mon Sep 17 00:00:00 2001 From: m3ultra Date: Wed, 22 Jul 2026 19:36:38 +1000 Subject: [PATCH] =?UTF-8?q?feat(trellis2=5Fmlx):=20metal=20PBR=20baker=20b?= =?UTF-8?q?y=20default=20=E2=80=94=20the=20fast=20lane=20now=20ships=20mes?= =?UTF-8?q?hgod-grade=20textures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fork lane (72s vertex) gains the trellis_mac 2026-07-22 quality fixes: metal UV-PBR bake with explicit RAM-sized face cap (the fork bakes FULL density when no target passed — 75GB peak; always pass one), forced- opaque alpha, texture_size/max_bake_faces/alpha_mode params. Verified m3ultra: 156s e2e, 26.2GB peak, 391,782-tri candidate + 2.19M-tri raw master. Vendor checkout synced to fork ba4e2ad. Co-Authored-By: Claude Fable 5 --- server/operators/trellis2_mlx/manifest.json | 7 +++++-- server/operators/trellis2_mlx/run.py | 20 ++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/server/operators/trellis2_mlx/manifest.json b/server/operators/trellis2_mlx/manifest.json index 210cf83..d316fa8 100644 --- a/server/operators/trellis2_mlx/manifest.json +++ b/server/operators/trellis2_mlx/manifest.json @@ -2,7 +2,7 @@ "id": "trellis2_mlx", "name": "TRELLIS.2 MLX (local, fastest)", "category": "mesh-gen", - "description": "Image → full-density vertex-baked GLB via the MRP MLX fork of TRELLIS.2 (monster/trellis-2-mrp-mlx): pure-MLX sampler + vertex baker + validated pipeline. 72s/gen @ 26.5GB on m3ultra, 182s @ 17.2GB on m1ultra — 3× faster and 3× lighter than the torch-MPS trellis_mac operator. Vertex-colored output (albedo; no MR maps) — pair with the MESHGOD finish farm for game budgets. Weights: TRELLIS.2-4B + gated DINOv3/RMBG (rsync from m3 HF cache to workers; no HF login needed).", + "description": "Image → PBR GLB via the MRP MLX fork of TRELLIS.2 (monster/trellis-2-mrp-mlx): pure-MLX sampler, Metal PBR bake with RAM-sized face cap + forced-opaque alpha (2026-07-22 quality fixes — fal-parity detail), kdtree/vertex fallbacks. ~72s vertex / ~2min metal-PBR on m3ultra — still the fastest local TRELLIS.2. baker=vertex for the 1s clean-albedo bake (no MR maps). Weights: TRELLIS.2-4B + gated DINOv3/RMBG (rsync from m3 HF cache to workers; no HF login needed).", "accepts": ["image"], "produces": ["model"], "resources": "gpu", @@ -14,7 +14,10 @@ "pipeline_type": {"type": "string", "enum": ["512", "1024", "1024_cascade"], "default": "1024_cascade", "description": "Resolution tier"}, "seed": {"type": "integer", "default": 0, "description": "Random seed"}, "steps": {"type": "integer", "default": 12, "description": "Sampler steps per stage (12 = upstream default)"}, - "baker": {"type": "string", "enum": ["vertex", "metal", "kdtree"], "default": "vertex", "description": "vertex = 1s bake, clean colors (recommended); metal = UV textures but has the dark-patch sampling bug"} + "baker": {"type": "string", "enum": ["metal", "vertex", "kdtree"], "default": "metal", "description": "metal = UV PBR textures (meshgod-grade; minor dark-patch texels remain); vertex = 1s bake, cleanest colors, no MR maps"}, + "texture_size": {"type": "integer", "enum": [512, 1024, 2048, 4096], "default": 2048, "description": "Baked texture resolution (metal/kdtree bakers)"}, + "max_bake_faces": {"type": "integer", "enum": [200000, 500000, 1000000], "default": 500000, "description": "Pre-bake face cap. 500k ≈ fal parity (M3 Ultra verified); node RAM sizes the default when unset — laptops get 200k"}, + "alpha_mode": {"type": "string", "enum": ["opaque", "auto"], "default": "opaque", "description": "opaque = force alphaMode OPAQUE (fixes speckle-veil hair); auto = keep baked alpha for glassy subjects"} } } } diff --git a/server/operators/trellis2_mlx/run.py b/server/operators/trellis2_mlx/run.py index 6d5cb21..450edc2 100644 --- a/server/operators/trellis2_mlx/run.py +++ b/server/operators/trellis2_mlx/run.py @@ -36,15 +36,27 @@ if not py.exists(): sys.exit(1) outdir = Path(a.outdir) + +# Meshgod-grade PBR by default (metal baker + capped bake), matching the +# trellis_mac lane's 2026-07-22 quality fixes. The fork's schedule bakes the +# FULL-density mesh when no target is passed (75GB peak, 131MB GLB) — always +# pass an explicit cap; RAM-sized default like trellis_mac (500k ≈ fal parity +# on ≥96GB Studios, 200k mtlbvh-safe elsewhere). +faces = p.get("max_bake_faces") +if faces is None: + mem_gb = os.sysconf("SC_PAGE_SIZE") * os.sysconf("SC_PHYS_PAGES") / 1e9 + faces = 500000 if mem_gb >= 96 else 200000 + cmd = [ str(py), str(FORK / "scripts" / "generate_asset.py"), str(Path(a.input[0]).resolve()), "--output-dir", str(outdir.resolve()), "--backend", "mlx-experimental", - "--baker", str(p.get("baker", "vertex")), + "--baker", str(p.get("baker", "metal")), "--pipeline-type", str(p.get("pipeline_type", "1024_cascade")), "--seed", str(p.get("seed", 0)), - "--texture-size", "2048", + "--texture-size", str(p.get("texture_size", 2048)), + "--pbr-decimation-target", str(faces), "--force", ] if p.get("steps"): @@ -52,6 +64,10 @@ if p.get("steps"): env = os.environ.copy() env["HF_HUB_DISABLE_XET"] = "1" +# "auto" keeps o_voxel's baked-alpha BLEND detection (glass etc.); default +# opaque — noisy baked alpha renders solid hair as a speckle veil. +if p.get("alpha_mode"): + env["TRELLIS2_ALPHA_MODE"] = str(p["alpha_mode"]) print("+", " ".join(cmd), flush=True) res = subprocess.run(cmd, cwd=str(FORK), stdout=sys.stdout,