Extensions/ComfyUI-TrellisMac
ComfyUI Extension

ComfyUI-TrellisMac

A lean ComfyUI node pack wrapping trellis-mac — the Apple Silicon port of Microsoft's TRELLIS.2 image-to-3D model for MPS-based 3D generation.

By dmvvilela·Created 2 months ago·Updated 2 months ago· 1
dmvvilela/ComfyUI-TrellisMac
Nodes
On cloudLocal install
Stars1
Updated2 months ago
Readme

ComfyUI-TrellisMac

<p align="center"> <strong>TRELLIS.2 image-to-3D on Apple Silicon — inside ComfyUI.</strong><br> Three nodes. No CUDA. The same code path that <code>trellis-mac/generate.py</code> uses. </p> <p align="center"> <img src="https://img.shields.io/badge/macOS-Apple%20Silicon-black?logo=apple" /> <img src="https://img.shields.io/badge/PyTorch-MPS-blue?logo=pytorch" /> <img src="https://img.shields.io/badge/ComfyUI-custom%20node-orange?logo=comfyui" /> </p>

⚠️ This is NOT a standalone plugin. It wraps trellis-mac — you need both repos. This plugin provides the ComfyUI nodes; trellis-mac provides the patched TRELLIS.2 source, Metal backends, and setup scripts.

TL;DR: set up trellis-mac, put this repo in custom_nodes/, run install.py once with ComfyUI's Python, then open ComfyUI normally.


What is this?

A lean ComfyUI node pack that wraps trellis-mac — the Apple Silicon port of Microsoft's TRELLIS.2 image-to-3D model. Drop an image in, get a textured .glb out, preview it in 3D — all on MPS, no NVIDIA required.

LoadImage → TrellisMacLoader → TrellisMacGenerate → TrellisMacExport → Preview3D

Why a separate plugin and not the existing ComfyUI-Trellis2?

ComfyUI-Trellis2 targets the original NVIDIA/Microsoft repo. It's 7,400 lines, imports cumesh, nvdiffrast, pymeshlab, meshlib at top level, hardcodes .cuda() everywhere, and calls a forked pipeline.run() with CUDA-specific params. None of that works on Apple Silicon.

This pack instead wraps the exact code path already proven to work on Macgenerate.py's pipeline.run() → Metal o_voxel bake → KDTree fallback → GLB export — in ~800 lines. No ported CUDA code, no forked pipeline, no guessing.


Prerequisites

1. trellis-mac (the model + backends)

You need a working trellis-mac checkout. If you've already run its setup.sh and generated a .glb with generate.py, you're good — the model weights (~16 GB), local dependency repos, Metal backends, and patched pipeline are all there.

git clone https://github.com/shivampkumar/trellis-mac
cd trellis-mac
./setup.sh

⚠️ 2. HuggingFace model access (gated models)

TRELLIS.2 uses two gated models that require you to accept their license on HuggingFace before downloading weights. Without this, the pipeline will fail at load time with an authentication error.

You must request access to and accept the license for:

| Model | Link | Why it's needed | |---|---|---| | facebook/dinov3-vitl16-pretrain-lvd1689m | Request access | Image feature extractor — runs on every input image | | briaai/RMBG-2.0 | Request access | Background removal preprocessing |

Then authenticate:

hf auth login
# Paste your HF token (get one at https://huggingface.co/settings/tokens)

If trellis-mac already generated successfully for you, you've already done this and can skip it.

3. ComfyUI Python environment

Any recent ComfyUI install works. The key requirement is that the same Python environment that launches ComfyUI can import both ComfyUI dependencies and the trellis-mac dependencies.

Do not launch ComfyUI with trellis-mac/.venv/bin/python. That environment is for the standalone CLI and often lacks ComfyUI dependencies such as SQLAlchemy.

Instead, keep launching ComfyUI with its normal Python and run this plugin's installer once. The installer is basically the ComfyUI-env version of trellis-mac/setup.sh: it installs the TRELLIS-side packages into ComfyUI's Python, installs the local trellis-mac/deps/* packages, and writes config.json so the node pack knows where trellis-mac lives.

The easiest path is to use install.py after this repo is in custom_nodes/:

/path/to/ComfyUI/.venv/bin/python custom_nodes/ComfyUI-TrellisMac/install.py \
  --trellis-mac /path/to/trellis-mac

Then verify:

/path/to/ComfyUI/.venv/bin/python custom_nodes/ComfyUI-TrellisMac/doctor.py

After that, open ComfyUI with one of the options below.

Manual pip installs are possible, but install.py is the recommended path because it uses the exact Python executable you ran it with and keeps the local Metal package paths together.

If you use ComfyUI Desktop, its Python environment may be hidden inside the Desktop-managed install. Use the Python executable that appears in your ComfyUI startup log.


Install

  1. Symlink or copy this folder into ComfyUI's custom_nodes/:
ln -s /path/to/ComfyUI-TrellisMac /path/to/ComfyUI/custom_nodes/ComfyUI-TrellisMac
  1. Install trellis-mac dependencies into the Python environment that launches ComfyUI:
/path/to/ComfyUI/.venv/bin/python custom_nodes/ComfyUI-TrellisMac/install.py \
  --trellis-mac /path/to/trellis-mac
  1. Run the doctor:
/path/to/ComfyUI/.venv/bin/python custom_nodes/ComfyUI-TrellisMac/doctor.py
  1. Launch ComfyUI with MPS fallback enabled.

TRELLIS.2 on Apple Silicon needs PYTORCH_ENABLE_MPS_FALLBACK=1 set before PyTorch imports. This is the only setting that has to be present every time ComfyUI starts.

Pick one:

Option A: Use the included launcher

For a normal source-style ComfyUI install, double-click or run:

custom_nodes/ComfyUI-TrellisMac/launch_comfy_trellis.command

This sets PYTORCH_ENABLE_MPS_FALLBACK=1, reads config.json for TRELLIS_MAC_PATH, and starts ComfyUI.

Option B: Keep using your usual ComfyUI launcher

Set the env var for your current macOS login session:

launchctl setenv PYTORCH_ENABLE_MPS_FALLBACK 1

Then fully quit and reopen ComfyUI normally. If you reboot or log out, run the command again.

This does not install anything and is generally safe: it tells PyTorch to use CPU fallback for unsupported MPS ops instead of crashing. The tradeoff is that some unsupported ops may run slower.

  1. Load the example workflow: workflows/mesh_only.json

How the plugin finds trellis-mac

It looks in this order (first win):

  1. TRELLIS_MAC_PATH env var — set it if trellis-mac is in a non-standard location
  2. config.json next to this plugin — the Loader node's trellis_mac_path input writes here (persists across runs)
  3. Heuristic — walks upward from this plugin and looks for nearby trellis-mac/ directories

The Nodes

📦 TrellisMacLoader — Load TrellisMac Pipeline

Loads microsoft/TRELLIS.2-4B from HuggingFace, moves it to MPS, caches it for the session.

| Input | Type | Default | Description | |---|---|---|---| | model_path | STRING | microsoft/TRELLIS.2-4B | HuggingFace model ID or local path | | reload | BOOLEAN | false | Force reload (clears session cache) | | trellis_mac_path | STRING | (empty) | Override trellis-mac location (persists to config.json) |

Output: pipeline (TRELLIS_PIPELINE)


🎨 TrellisMacGenerate — TrellisMac Image to 3D

The core node. Takes a ComfyUI image, runs the full TRELLIS.2 pipeline, outputs a mesh with voxel texture data.

| Input | Type | Default | Description | |---|---|---|---| | pipeline | TRELLIS_PIPELINE | (from Loader) | The loaded pipeline | | image | IMAGE | (from LoadImage) | Input image (any ComfyUI image node) | | seed | INT | 42 | Random seed | | pipeline_type | COMBO | 512 - fast | Maps to CLI values: 512 · 1024 · 1024_cascade | | steps | INT | 0 | Sampler steps per phase (0 = use pipeline defaults, usually 12) | | num_samples | INT | 1 | Number of meshes to generate |

Output: mesh (MESHWITHVOXEL) — the raw MeshWithVoxel object with vertices, faces, voxel attrs, UVs, etc.


💾 TrellisMacExport — Export TrellisMac Mesh

Bakes PBR textures and writes a 3D file to ComfyUI's output directory. The glb_path output plugs straight into ComfyUI's built-in Preview3D node.

Automatically selects the best bake method:

  1. 🪲 Metalo_voxel.postprocess.to_glb + mtldiffrast (fastest, GPU-accelerated)
  2. 🌳 KDTreexatlas UV unwrap + scipy nearest-voxel lookup (CPU fallback, same quality)
  3. 🟦 Vertex colors — bare geometry with vertex colors (if no voxel data)

Pre-simplifies meshes to ≤200K faces before baking to keep things fast.

| Input | Type | Default | Description | |---|---|---|---| | mesh | MESHWITHVOXEL | (from Generate) | The mesh to export | | filename_prefix | STRING | TrellisMac/3D | Output subfolder/name in ComfyUI's output dir | | file_format | COMBO | glb | glb · obj · ply | | texture_size | COMBO | 1024 | PBR texture resolution: 512 · 1024 · 2048 | | bake_texture | BOOLEAN | true | Disable for vertex-color-only export (faster) | | also_obj | BOOLEAN | false | Also write a plain .obj alongside the GLB |

Output: glb_path (STRING) · relative_path (STRING)


Example Workflow

Load workflows/mesh_only.json in ComfyUI. It wires up:

LoadImage → Load TrellisMac Pipeline → TrellisMac Image to 3D → Export TrellisMac Mesh → Preview 3D

Drop in any image and hit Queue. First run downloads ~16 GB of model weights (only once, cached by HuggingFace).


Troubleshooting

Start with the doctor:

/path/to/ComfyUI/.venv/bin/python custom_nodes/ComfyUI-TrellisMac/doctor.py

If it reports a missing package, rerun install.py with the same Python that launches ComfyUI.

Model download or authentication fails

Accept the gated model licenses, then authenticate with hf auth login. See HuggingFace model access.

Nodes don't appear in ComfyUI

Make sure the node folder is in custom_nodes/, restart ComfyUI, and check the ComfyUI startup log for import errors.

MPS fallback warning in doctor.py

Run ComfyUI with PYTORCH_ENABLE_MPS_FALLBACK=1. Either use launch_comfy_trellis.command or run:

launchctl setenv PYTORCH_ENABLE_MPS_FALLBACK 1

Then fully quit and reopen ComfyUI.

"ERROR: The decoder produced an empty mesh" (GPU watchdog)

This is the macOS GPU watchdog killing a long-running Metal kernel in the SLat decoder. It is workload/display-load dependent, not usually an install problem.

Workarounds, cheapest first:

  1. Run headless — close the lid / unplug external displays, re-run over SSH. The watchdog tightens with WindowServer load.
  2. MTL_CAPTURE_ENABLED=1 at launch — extends the timeout as a side effect of Metal-debugger mode.
  3. SPARSE_CONV_BACKEND=none at launch — slower path, may avoid the triggering dispatch.

Metal bake fails, falls back to KDTree

Expected on some meshes. mtlbvh can crash on very large meshes. The KDTree fallback produces the same PBR result, just slower. No action needed.


How it works (technical)

| Aspect | Detail | |---|---| | Pipeline | Stock Trellis2ImageTo3DPipeline.from_pretrained() + pipeline.run() — no forked code | | Device | MPS (pipeline.to(torch.device("mps"))) | | Backends | Attention: SDPA · Conv: flex_gemm (or none fallback) · set via runtime setters (not env vars) | | Texture bake | Metal o_voxel → KDTree CPU → vertex-color fallback | | Pipeline caching | Loaded once per ComfyUI session, reused across queue runs | | Watchdog detection | Catches empty-mesh signatures and surfaces actionable error |

Architecture

ComfyUI-TrellisMac/
├── __init__.py          # ComfyUI entrypoint — NODE_CLASS_MAPPINGS
├── nodes.py             # The 3 node classes (Loader, Generate, Export)
├── _pipeline.py         # Path resolution, sys.path setup, cached pipeline loader
├── _bake.py             # Bake branches: Metal / KDTree / vertex-color
├── _watchdog.py         # macOS GPU watchdog detection + help message
├── workflows/
│   └── mesh_only.json   # Example workflow
└── README.md

All ML code paths are lifted from trellis-mac/generate.py. No new inference logic.


Credits

License

MIT