Nodes/ComfyUI-Pixal3D/Pixal3D: Image to Mesh
ComfyUI Node

Pixal3D: Image to Mesh

One image, one queue, a PBR mesh — Pixal3D without the pain

By dreamrec·Created 4 months ago·Updated 4 months ago· 22
Pixal3D: Image to Mesh
  • image
  • mask
  • pipeline_ready
  • mesh
  • preprocessed_image
  • camera_angle_x
  • distance
  • glb_path
pipeline_type1024_cascade
seed42
low_vramfalse
max_num_tokens49152
mesh_scale1.0
image_resolution512
camera_angle_x_override0.000
distance_override0.00
ss_guidance_strength7.5
ss_sampling_steps12
ss_guidance_rescale0.70
ss_rescale_t5.0
shape_guidance_strength7.5
shape_sampling_steps12
shape_guidance_rescale0.50
shape_rescale_t3.0
tex_guidance_strength1.0
tex_sampling_steps12
tex_guidance_rescale0.00
tex_rescale_t3.0
decimation_target200000
texture_size2048
remeshtrue
background_colorgray
keep_warmtrue
save_to_output_dirtrue
output_filename_prefixpixal3d
save_objfalse

This is the node that turns one image into a textured, PBR-ready 3D mesh - and earns its keep by making something genuinely miserable into something you just queue.

Pixal3D is Tencent ARC + Tsinghua's SIGGRAPH 2026 model - one image in, a GLB with real PBR textures out, in about 3–5 minutes on a modern RTX card. Running the raw repo is a gauntlet: people documented the Blackwell kernel builds, the natten dance, and a lot of yelling at Claude to get it going. This wrapper sidesteps all of that - it installs into ComfyUI's own Python and you never touch a terminal past the setup. People who've run Trellis.2 call Pixal3D a real step up: it back-projects pixel features into 3D instead of loosely injecting them through attention.

How it works

The pipeline is longer than you'd guess from the single input socket. Roughly: your image gets its background removed by BiRefNet (the MIT remover ComfyUI itself shipped in core), then smart-cropped and composited onto a background color. MoGe-2 estimates camera intrinsics, four DINOv3 extractors project conditioning features into 3D, and a cascade of sampler stages builds the sparse structure, the shape, and the texture - finishing with mesh extraction, a PBR bake, decimation, and GLB export.

The part that will bite you isn't the AI - it's memory: a ~24 GB weight set, and a ~14 GB resident pipeline once loaded.

The inputs that matter

Most of the widget list is "leave it alone" - the defaults are tuned. You'll actually touch these:

  • image - your photo. Only the first batch entry is used, so don't feed it a batch.
  • pipeline_type - 1024_cascade (default, recommended) or 1536_cascade (heavier, marginally better, needs a 34 GB-class card).
  • seed - same seed and settings give you the same mesh, handy for iterating on one parameter.
  • max_num_tokens - the HR token budget, and your main VRAM dial. Default 49152 ≈ 9 GB of activations. If you're on a 16 GB card, dropping this to 32768 or 24576 is the first thing to try before you OOM.
  • low_vram - offloads submodels to CPU between stages. Slower, but the difference between fitting and not.
  • background_color - keep it gray. The tooltip spells out why: black bakes thin black silhouette lines into the PBR texture. That's the classic "why do my meshes have dark streaks" fix.
  • keep_warm - true by default, so the ~14 GB pipeline stays in VRAM and the next run is ~3 minutes instead of a 7–10 minute cold load. Flip it off when you want that memory back.

There are also ss_/shape_/tex_ guidance widgets and camera overrides; setting both camera_angle_x_override and distance_override above zero skips MoGe and forces your own camera - useful for retrying a run that came out geometrically off.

What you get out

Five outputs, and you'll use two:

  • mesh (TRIMESH) - wire into a Preview3D node to look at it.
  • glb_path (STRING) - the absolute path of the auto-saved file. You can chain this straight into Preview3D and skip the explicit export step.
  • preprocessed_image - the cropped/composited image that actually went in, handy for debugging a bad mask.
  • camera_angle_x / distance - the camera values MoGe actually estimated, which you can feed back as overrides on a retry.

The GLB (plus an optional OBJ if you flip save_obj) lands in ComfyUI/output/pixal3d_<timestamp>_<seed>.glb with PNG textures - Blender, Three.js, any standard viewer.

Installing it

ComfyUI Manager is the easy path: search ComfyUI-Pixal3D, install, restart - the plugin's install.py runs automatically and drops everything into ComfyUI's own Python, no separate worker env. Manual route:

cd $HOME\Documents\ComfyUI\custom_nodes
git clone https://github.com/dreamrec/ComfyUI-Pixal3D.git
cd ComfyUI-Pixal3D
& "$HOME\Documents\ComfyUI\.venv\Scripts\python.exe" install.py

Then restart. The hard requirements: Windows 10/11 x64, Python 3.12, PyTorch 2.8 + CUDA 12.8 (the ComfyUI Desktop defaults), an NVIDIA RTX 30/40/50 with ≥16 GB VRAM (24 GB+ recommended), and ~50 GB of disk - the first queue downloads ~26 GB of weights from HuggingFace. No AMD/Intel GPUs; upstream Pixal3D is CUDA-only. And note the license: the wrapper is MIT, but the Pixal3D model itself is academic / non-commercial only and explicitly not for use in the EU.

Where people get burned

  • Black lines baked into the texture - an old saved workflow with background_color: black. Re-create the node from the menu; the default is gray.
  • OOM - drop max_num_tokens to 32768/24576, enable low_vram, or step down to 1024_cascade.
  • VRAM fragmentation after many runs - the README documents ten consecutive warm runs succeeding and the eleventh OOMing. Queue Pixal3D: Free Pipeline between batches to defrag.

If the run itself dies with Repository Not Found on a HuggingFace URL or a device-resync after toggling low_vram, you're on an old plugin version - git pull, re-run install.py, restart.

CategoryPixal3D

Inputs (31)

NameTypeDefaultDescription
imageIMAGEInput image (RGB). Single image; first batch entry is used.
pipeline_typeCOMBO1024_cascade1024_cascade is recommended; 1536_cascade is heavier and may overflow VRAM.
seedINT420–2147483647
maskoptMASKForeground mask (white=object). If provided, BiRefNet is skipped.
pipeline_readyoptPIXAL3D_PIPELINE_READY
low_vramoptBOOLEANfalseOnly used if pipeline_ready is not connected.
max_num_tokensoptINT4915216384–131072HR token budget. Lower = less VRAM, smaller mesh. 49152 ~= 9GB activations.
mesh_scaleoptFLOAT1.00.1–5
image_resolutionoptINT512256–2048
camera_angle_x_overrideoptFLOAT0.0000–3.140 = auto (MoGe-2). Set both override fields > 0 to skip MoGe.
distance_overrideoptFLOAT0.000–50
ss_guidance_strengthoptFLOAT7.51–20
ss_sampling_stepsoptINT121–50
ss_guidance_rescaleoptFLOAT0.700–1
ss_rescale_toptFLOAT5.00–10
shape_guidance_strengthoptFLOAT7.51–20
shape_sampling_stepsoptINT121–50
shape_guidance_rescaleoptFLOAT0.500–1
shape_rescale_toptFLOAT3.00–10
tex_guidance_strengthoptFLOAT1.01–20
tex_sampling_stepsoptINT121–50
tex_guidance_rescaleoptFLOAT0.000–1
tex_rescale_toptFLOAT3.00–10
decimation_targetoptINT2000005000–1000000
texture_sizeoptINT2048256–4096
remeshoptBOOLEANtrue
background_coloroptCOMBOgrayColor composited behind the foreground mask. Default 'gray' (128,128,128) prevents dark-silhouette bleed that bakes thin black lines into the PBR texture; 'black' matches Pixal3D inference.py defaults but causes those artifacts; 'white' for light-on-dark subjects.
keep_warmoptBOOLEANtrueTrue: keep the loaded Pixal3D pipeline in VRAM after this run (~14 GB) so the NEXT call is fast (~3 min instead of ~7-10 min cold-load). False: auto-free the pipeline at the end of THIS call. Use False if you're done with Pixal3D for a while and need that VRAM back for other nodes.
save_to_output_diroptBOOLEANtrueWhen True, auto-save the GLB to ComfyUI/output/<prefix>_<unix_ns>_<seed>.glb. Disable for chained workflows that export downstream via another node — leaves the mesh in memory only.
output_filename_prefixoptSTRINGpixal3dPrefix for the auto-saved GLB filename. Final name: <prefix>_<unix_ns>_<seed>.glb. Ignored if save_to_output_dir=False.
save_objoptBOOLEANfalseAlso export an OBJ (+ .mtl + texture PNGs) alongside the GLB. OBJ is base-color-only (the format has no standard metallic/roughness slots) — keep the GLB as the canonical PBR artifact and use the OBJ for DCC tools that prefer it (Blender, ZBrush, Marmoset). Ignored if save_to_output_dir=False.

Outputs (5)

NameTypeDescription
meshTRIMESH
preprocessed_imageIMAGE
camera_angle_xFLOAT
distanceFLOAT
glb_pathSTRING