Nodes/BrainDead Nodes/BD Transfer Vertex Colors
ComfyUI Node

BD Transfer Vertex Colors

Put the colors back after you decimate

By BizaNator·Created 8 months ago·Updated 3 days ago· 15
BD Transfer Vertex Colors
  • source_mesh
  • target_mesh
  • mesh
  • status
transfer_modeface
default_color1.0,0.0,1.0,1.0

Decimation has a nasty habit: it throws away the vertices that were carrying your colors. You sample colors onto a high-poly mesh, decimate it down to a game-friendly count, and the survivors don't remember what color they were. BD Transfer Vertex Colors exists for exactly this moment - it transfers vertex colors from a high-poly source mesh onto a decimated target mesh, with a mode that keeps the colors crisp and per-face rather than bleeding into smudges.

What it is

A mesh-to-mesh color transfer: source_mesh (the high-poly mesh with the good vertex colors) and target_mesh (the decimated one that needs them) in, recolored target_mesh out. It's the third leg of the BrainDead low-poly pipeline and the one that makes the whole chain coherent.

How it works

Under the hood it uses a BVH spatial lookup (trimesh's proximity acceleration) to find where each target vertex or face sits relative to the source. The transfer_mode decides how colors map:

  • face (default) - one solid color per face, no bleeding. It splits the vertices so each face carries its own color - the target ends up with distinct, flat-color triangles. The tooltip calls it RECOMMENDED for stylized/low-poly looks, and it's the mode the README pipeline prescribes, with the honest cost: it triples the vertex count.
  • face_center - per-face lookup but assigns to shared vertices. Sharper than the alternatives but can bleed at edges.
  • vertex_nearest - per-vertex k=1 nearest neighbor. Smooth, but colors run across edges.
  • barycentric - smooth interpolation for high-poly blended looks; the one to pick when you're not going stylized.

default_color is the fallback (default magenta 1.0,0.0,1.0,1.0 - deliberately loud, so missing coverage is unmissable rather than silently gray).

Outputs: the recolored mesh and status.

The canonical workflow

The README lays it out as the standard pattern:

  1. Sample colors onto a high-poly mesh (BD Sample Voxelgrid Colors).
  2. Decimate it (BD Smart Decimate).
  3. Transfer the colors back with face mode for clean edges.

The reason face mode matters for this pipeline: after decimation the low-poly mesh has hard edges, and hard edges want hard color boundaries. Vertex-colored meshes exported from this flow read as intentional stylized geometry - think flat-shaded game assets - rather than blurry gradient soup. If you're instead after smooth, high-poly color blending, barycentric is your mode, but then you're not really doing the low-poly chain.

Gotchas

face mode tripling the vertex count is the cost of the clean look - fine for a game prop, wasteful if you're trying to keep a mesh tiny. And the magenta default is a feature: if you see magenta patches, your source mesh doesn't cover part of the target (mismatched scale or a region the source never had), and no amount of mode-switching fixes it - go check the meshes align. The node itself has no heavy dependencies beyond trimesh, which ships with ComfyUI.

Installing it

ComfyUI Manager: search "BrainDead" → install. Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/BizaNator/ComfyUI-BrainDead
cd ComfyUI-BrainDead
pip install -r requirements.txt

Restart, find it under 🧠BrainDead/Mesh. Wire your sampled high-poly into source_mesh, the decimated result into target_mesh, leave it in face mode, and you've got the pack's stylized low-poly recipe in three nodes.

Category🧠BrainDead/Mesh

Inputs (4)

NameTypeDefaultDescription
source_meshTRIMESHHigh-poly mesh with vertex colors
target_meshTRIMESHDecimated mesh to receive colors
transfer_modeoptCOMBOfaceface=NO bleed (splits verts), face_center=sharp, vertex_nearest=per-vertex, barycentric=smooth
default_coloroptSTRING1.0,0.0,1.0,1.0Fallback color (magenta) for missing coverage

Outputs (2)

NameTypeDescription
meshTRIMESH
statusSTRING