Three Render
Turn the 3D scene into an image batch ComfyUI can use
- app
- images
- depth
- normal
- frame_count
- fps
This is where the WAS Node Suite Three family stops being a toy 3D viewer and becomes part of a real ComfyUI pipeline. Three Viewer and the geometry/material nodes let you look at a scene on the canvas; WASThreeRender is the node that draws it at a chosen resolution and hands it out as an IMAGE, so the result can be saved, composited, upscaled, or fed straight into a sampler or ControlNet. Every frame comes back three ways - picture, depth and normals - so one render feeds a preview and a depth ControlNet at the same time.
How it works
The render happens in your browser. Three App carries the scene, camera and renderer settings; Three Render takes that app plus frame parameters, and the browser draws each frame and posts PNGs back. That architecture is why the node's description is blunt about one thing: the drawing happens in an open ComfyUI tab, so a tab has to be open and the graph queued from it. A headless run fails with a message saying so rather than hanging. You can't just fire this in API-only mode and walk away.
The inputs that matter
- width / height - frame size in pixels. 1024 is a working size; 4096 wants a capable GPU. The camera fits its view to the frame shape.
- num_frames / fps / start - how the animation is sampled.
fpstimes Three App'sloop_secondsis one whole loop, so 96 frames at 24 fps exactly covers a 4-second loop. Set num_frames to 1 to capturestartalone as a still. Changing fps alone changes smoothness, not speed. - transparent -
trueleaves the background clear and returns alpha. - supersample - draws each frame this many times oversize and scales it down, which smooths stepped edges. 1 is fastest, 2 is the usual choice, 4 costs significantly more.
- depth_near / depth_far - what the depth pass maps to white and black. At 0.0 they auto-fit to whatever's in shot, which a wide floor stretches out; for a subject 8 units away, a near/far of 6 and 10 gives it the whole range.
Outputs
Five: images, depth and normal (all IMAGE, in time order), plus frame_count and fps to hand a video saver - the fps output exists so a Save Video node gets exactly the rate the render ran at. The depth and normal passes are the same dimensions as the pictures, which is what makes them ControlNet-ready with zero extra work.
What trips people up
The scene has to be wound forward properly: motion that adds up frame by frame - a camera track, an animation - lands where it would if you'd run the whole thing in real time. And because this is rasterization, Three Render does use the App's effects chain, antialias and supersample - the things Three Path Trace Render deliberately ignores. If you want physically-traced light instead of faked shadows, that's the sibling node. For motion preview at low cost, Three Viewer.
Install
WASThreeRender ships with WAS Node Suite v3. Install via ComfyUI Manager (search WAS Node Suite v3) or:
cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui.git
Restart after. Requires ComfyUI 0.14.0+ and Python 3.10+, no extra packages. If the node's missing from Add Node, set features.threejs: true in <ComfyUI user dir>/was-node-suite/config.yaml and restart.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| app | THREE_APP | The scene, camera and renderer settings, from Three App. | |
| width | INT | 102416–8192 | Frame width in pixels. 1024 is a working size, 4096 needs a capable GPU. |
| height | INT | 102416–8192 | Frame height in pixels. 1024 is square; the camera fits its view to this shape. |
| transparent | BOOLEAN | false | `true` leaves the background clear and returns alpha; `false` fills it with the scene's background colour. |
| num_frames | INT | 961–512 | How many frames to draw. `fps` times Three App's loop_seconds is one whole loop, so 96 at 24 a second covers a 4 second loop exactly. 1 captures `start` alone as a still. |
| start | FLOAT | 0.000–3600 | Seconds into the animation the first frame is taken at. 0.0 is the pose the scene starts in. |
| fps | FLOAT | 240.01–1000 | Frames a second. It sets how densely the animation is sampled, never how fast it moves. 24.0 over 96 frames is four seconds. Give the same number to a video saver, or wire the fps output straight into it. |
| timeout | FLOAT | 1801–86400 | Seconds to wait for the whole run. 180.0 covers a 96 frame loop, 30.0 a single frame, and a long run at a large size wants thousands. |
| supersample | INT | 21–4 | Draws the frame this many times oversize and scales it back down, which is what smooths a stepped edge. 1 is fastest, 2 is the usual choice, 4 costs sixteen times the pixels. |
| depth_near | FLOAT | 0.00–100000 | Distance from the camera the depth pass calls white. 0.0 fits the range to whatever is in shot, which a wide floor stretches; set it and depth_far around the subject to spend the whole range on it. |
| depth_far | FLOAT | 0.00–100000 | Distance the depth pass calls black. 0.0 fits it to what is in shot. For a figure 8 units away, 6.0 and 10.0 give it the whole range. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | The frames, as one batch in time order. RGBA where transparent was on, RGB otherwise. |
| depth | IMAGE | The same frames as distance from the camera, white for near, spread across what is actually in shot rather than across near and far. Feeds a depth ControlNet. |
| normal | IMAGE | The same frames as the direction each surface faces, in the tangent-space layout a normal ControlNet reads. |
| frame_count | INT | How many frames each batch holds, which is num_frames. |
| fps | FLOAT | The frame rate the frames were taken at, for a video saver's own fps so the two cannot disagree. |