Nodes/ComfyTV/Line Art
ComfyUI Node

Line Art

Render a 3D model as line art, ready to feed a ControlNet

By jtydhr88·Created 3 months ago·Updated about 15 hours ago· 725
Line Art
  • model
  • image
force_run_token0
project_id
parent_output_id0
width1024
height1024
thickness2.0
silhouettetrue
creasetrue
boundarytrue
crease_angle60
occlusiontrue
invertfalse
camera

Line Art is the bridge between the 3D side of ComfyTV and the 2D side. You point it at a 3D model and it renders a technical line drawing - the kind of clean, stylized line art that used to mean hours in a toon shader or a vectorizer. And because it defaults to white lines on black, what it actually hands you is a ready-to-use ControlNet lineart condition: generate a 3D scene, render the lines, and use them to pin the composition of a diffusion image. That's a workflow that's genuinely hard to build any other way.

ComfyTV is the canvas-style app layer on ComfyUI where every operation is its own node. Line Art sits in the 3D category because it consumes a COMFYTV_MODEL - a mesh from Mesh Primitive, a generated model, or an imported asset.

How it works. The renderer doesn't shade the surface - it detects edges in four categories you can toggle: silhouette (where the surface turns away from the camera), crease (sharp edges past a crease_angle), boundary (open mesh borders), and it can hide lines behind the surface using a BVH ray test (occlusion) so you get a proper line render instead of a wireframe. The result is drawn at thickness (in output pixels) onto a canvas sized by width/height. invert flips the palette: default gives white-on-black for ControlNet lineart preprocessors; flip it for black-on-white if that's what your model expects. The camera is set in the node body's 3D viewport (empty camera = auto-framed).

The inputs that matter. The force_run_token, project_id, parent_output_id and camera inputs are internal plumbing. The real controls:

  • model - the mesh to render. Required; the node errors without it.
  • width / height - output canvas size (256–4096, step 64). Match your generation target.
  • thickness - line width in pixels, 0.5–8.
  • silhouette / crease / boundary - which edge classes to draw. All on by default; turn boundary off if raw mesh borders are making it messy.
  • crease_angle - degrees (1–179, default 60) above which a shared edge counts as a crease.
  • occlusion - on by default (BVH hide-behind-surface). Off gives the see-through wireframe look.
  • invert - white-on-black (default) vs black-on-white.

The single output is image (a COMFYTV_IMAGE) - wire it straight into a ControlNet lineart slot or into any image stage downstream.

Install. Install the pack once:

cd ComfyUI/custom_nodes
git clone https://github.com/jtydhr88/ComfyTV

Restart ComfyUI (full restart, not a browser refresh) and the stage appears under ComfyTV → 3D. ComfyUI Manager - search "ComfyTV" - works too. Zero Python dependencies (the pack's pyproject.toml dependency list is empty) and no model files for the line render itself - you only need a mesh to feed it. The usual install trap applies: on Desktop or multi-install machines, clone into the running instance's path from the startup log or the node won't register.

Where people get burned. Feeding it a model with no clear silhouette - dense, noisy topology renders as a scribble no matter the settings; run a decimate or remesh first. Second: invert is easy to forget, and a ControlNet that was trained on black-on-white will do weird things if you hand it white-on-black. And occlusion being on is what separates a usable line render from a wireframe - if the output looks like a spiderweb, check that it hasn't been toggled off rather than blaming your mesh.

CategoryComfyTV/3D

Inputs (14)

NameTypeDefaultDescription
force_run_tokenINT00–2147483647Internal — bumped on Run to invalidate ComfyUI's input cache.
project_idSTRINGInternal — populated by the projectStore on the frontend.
parent_output_idINT00–2147483647Internal — lineage parent set by spawn handlers on the frontend.
widthINT1024256–4096
heightINT1024256–4096
thicknessFLOAT2.00.5–8Line width in output pixels.
silhouetteBOOLEANtrueEdges where the surface turns away from the camera.
creaseBOOLEANtrueSharp edges — dihedral angle above the crease angle.
boundaryBOOLEANtrueOpen-mesh border edges.
crease_angleFLOAT601–179Angle between face normals (deg) above which an edge counts as a crease.
occlusionBOOLEANtrueHide lines behind the surface (BVH ray test). Off = wireframe-style see-through.
invertBOOLEANfalseOff: white lines on black (ControlNet lineart). On: black lines on white.
cameraSTRINGInternal — view camera (position/target/fov JSON) set by the node body; empty = auto-framed.
modeloptCOMFYTV_MODEL

Outputs (1)

NameTypeDescription
imageCOMFYTV_IMAGE