GNM Head Viewport
GNM Head Viewport is the fun one
- image
- normal_map
- depth_map
- mask
ComfyUI-GNM's GNMHeadViewport is the node that makes the whole pack feel like a toy, in the best way. Drop it on the canvas, wire image to a Preview node, and you have a live 3D head you can drag sliders on - no queueing, no waiting for a render. Drag on the preview itself to orbit the camera; scroll to zoom. It's the closest thing this pack has to a videogame.
It's also a genuine all-in-one: everything the separate nodes do, in one box, with the model loaded internally - no GNM_MODEL wire required. Every face-relevant widget is right there: gender, ethnicity, identity_seed + identity_strength, the 20-class expression dropdown with its own expression_seed + expression_strength, plus head/eyes rotation, camera azimuth/elevation, zoom, fov, surface, and antialias. The outputs are the same four as the render node: image, normal_map, depth_map, mask.
The trick that makes it feel instant: the frontend is a three.js viewport that POSTs the current widget values to a /gnm/viewport/preview endpoint on ComfyUI's own server, debounced so it doesn't spam. That endpoint runs the same pyrender pipeline as the final render, downscaled, and returns a preview - which is why what you see is exactly what you get. Drag the camera and the preview writes the new angles back into the camera_azimuth/camera_elevation widgets, so the queued render comes out in the exact composition you previewed.
Two practical notes. First, the preview runs low-res while you're actively dragging so it stays smooth, then refines to a sharper image once you let go - but a queued render is always the full width/height you set, at full resolution. Second, this is the node for fast random faces: seeds, demographics, expression, done, and the same ControlNet-ready normal/depth/mask outputs come out the other side. If you want to sculpt individual facial components instead of rolling dice, that's what the Advanced and Pro variants are for.
Install
ComfyUI Manager is the easy path: Custom Nodes → search "ComfyUI-GNM" → Install, then restart. Or clone by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/soylab-edu/ComfyUI-GNM
cd ComfyUI-GNM
pip install -r requirements.txt
Model data ships in vendor/; no separate download, no TensorFlow. The viewport needs the web extension plus the renderer deps (pyrender, pyglet<2, pinned PyOpenGL==3.1.10).
Common issues
If the live preview never appears, the server routes didn't register. The pack prints [ComfyUI-GNM] live viewport endpoints registered on startup - if you don't see that line, ComfyUI was probably already running when you installed, so restart it. And the same renderer notes as the render node apply: headless Linux needs PYOPENGL_PLATFORM=egl, and the pyglet<2 pin is there for a reason - newer pyglet breaks pyrender's GL context.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| gender | COMBO | 2 options: female, male | |
| ethnicity | COMBO | 4 options: middle_eastern, asian, white, black | |
| identity_seed | INT | 00–18446744073709550000 | — |
| identity_strength | FLOAT | 1.000–3 | — |
| expression | COMBO | 20 options: surprise, disgust, suck, compress_face, stretch_face, happy, +14 | |
| expression_seed | INT | 00–18446744073709550000 | — |
| expression_strength | FLOAT | 1.000–3 | — |
| head_yaw | FLOAT | 0.0-90–90 | — |
| head_pitch | FLOAT | 0.0-90–90 | — |
| head_roll | FLOAT | 0.0-90–90 | — |
| eyes_yaw | FLOAT | 0.0-40–40 | — |
| eyes_pitch | FLOAT | 0.0-30–30 | — |
| camera_azimuth | FLOAT | 0.0-180–180 | — |
| camera_elevation | FLOAT | 0.0-89–89 | — |
| zoom | FLOAT | 1.000.2–5 | — |
| fov | FLOAT | 255–90 | — |
| width | INT | 51264–4096 | — |
| height | INT | 51264–4096 | — |
| background | FLOAT | 0.950–1 | — |
| surface | COMBO | 2 options: plain, edgeflow_texture | |
| antialias | INT | 21–4 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| normal_map | IMAGE | — |
| depth_map | IMAGE | — |
| mask | MASK | — |