Super Director Tools · Panorama viewer
Drag the Sphere Until the Shot Looks Right, Then Let the Prompt Clean It Up
- image
- image
- prompt
- presets_json
Most panorama nodes make you think in numbers. Yaw 47 degrees, pitch -3, vertical FOV 62 - and you adjust them blind, run the graph, save a file, look, adjust again. It's like framing a shot through a telescope with the lens cap on.
This node puts the sphere in the node. You drag the image, scroll to zoom, and the framing widgets update live. Then you run the graph and get the perspective render. It's what makes a 360 panorama usable as a location library instead of a novelty, and it's what the rest of the pack is built around.
What's actually happening
The node treats your 2:1 image as a spherical environment map and renders a perspective camera from inside it. For each output pixel it computes a ray, converts that ray into longitude/latitude with atan2/asin, and samples the equirect texture bilinearly. Longitude wraps, so you can rotate a full 360° and never hit an edge - the sampler even adds a wrapped column at each side to interpolate across the join cleanly. That's pure PyTorch, no Three.js, no CUDA extension.
The preview you drag is a WebGL2 sphere drawn by the pack's frontend extension, backed by a temporary 8-bit PNG at most 1536 px on the long edge. Which explains the two-step feel people complain about: adjusting the camera does not re-render. It updates the preview and the widgets, nothing else. You press run. Run once on a fresh workflow to load the preview at all - loading a workflow doesn't execute upstream nodes.
The fields worth knowing
image takes exactly one RGB image - upstream batches need picking first, and the node raises otherwise. Expect a 2:1 equirectangular panorama.
projection is the mode switch: 360 Panorama gives you the sphere and perspective output, Flat is the legacy plain crop-and-zoom. New nodes default to 360 Panorama; if an old workflow of yours renders a flat crop, this is why.
aspect_ratio, width, height are the output frame: seven ratios plus Free, 1–8192 px per side, and editing one dimension recomputes the other when a ratio is locked. zoom runs 0.5–32×, and in 360 mode it is the field of view: 1× = 75° vertical FOV, 0.5× = about 113.8°, 32× = about 2.7°.
center_x / center_y are normalised look direction, 0–1, both defaulting to 0.5 - centre of the source, level horizon. x=0 and x=1 are the seam.
camera_height is the odd one: -0.8 to 0.8 sphere radii, positive up. It's a simulated viewpoint move inside a unit sphere, not a metre value, and Flat mode ignores it. Because a panorama has no depth, pushing off-centre can't reveal what was hidden behind anything - near objects just warp. Treat it as a slight tilt-shift for floors and ceilings, not a dolly.
The three outputs
image is the framed perspective render - feed it to Save Image, or into an img2img/upscale pass for detail.
prompt is an English editing instruction for exactly that pass. It tells the downstream model this is one camera view of a panorama, not an equirect, and asks it to fix residual spherical warping, straighten architectural lines that should be straight, tame unnatural wide-angle stretch at the frame edges, and reduce the warping from an off-centre viewpoint - while preserving composition, framing, apparent field of view, identities, layout and lighting. It's a genuinely good prompt. Better than most people would write.
presets_json is the shot list - the camera presets you build in the node's controls (an Add preset button, named shots like Wide or Close-up, JSON export/import). Wire it into Batch Panorama's presets_json input, converting that widget to an input first. Each preset stores yaw, pitch, vertical FOV, size, ratio and camera height.
Install
Manager → search Super Director Tools, or:
cd ComfyUI/custom_nodes
git clone https://github.com/mch000534/ComfyUI-DirectorTools
Restart ComfyUI and refresh the browser tab - the interactive preview is a frontend extension, and a stale page will show the node with no controls. No models, no pip install; requirements.txt is a one-line note that there are no dependencies. You do need a browser with WebGL2 and hardware acceleration on.
Where it goes wrong
The node renders nothing on load: expected, run once. Preview says expired: the temp PNG got cleaned, run again. No new buttons after updating the pack: refresh the page, and check the DirectorToolsPanoramaViewer.FixedViewport extension wasn't disabled. Viewer received more than one source image: pick a frame. And if you're driving it over the API, remember "projection": "360 Panorama" must be passed explicitly - omitting it keeps old Flat behaviour, and locked-aspect API calls need matching width/height.
One more thing: high zoom magnifies a small patch of a 2K panorama with a bilinear filter, so the crop is real perspective but soft. That's what the prompt output and a light img2img pass afterwards are for - the node frames the shot, a model makes it good.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | One RGB image. 360 Panorama expects an equirectangular 2:1 panorama. | |
| aspect_ratio | COMBO | 16:9 | 7 options: 16:9, 9:16, 1:1, 4:3, 3:2, 2.39:1, +1 |
| width | INT | 19201–8192 | — |
| height | INT | 10801–8192 | — |
| center_x | FLOAT | 0.5000–1 | Normalized horizontal source center. |
| center_y | FLOAT | 0.5000–1 | Normalized vertical source center. |
| zoom | FLOAT | 1.000.5–32 | 360: 1 gives 75 degree vertical FOV. 360: 0.5 gives a wider view. Flat: values up to 1 fill viewport. Larger values zoom in. |
| projectionopt | COMBO | 360 Panorama | 360 wraps longitude and outputs perspective. Flat keeps legacy crop behavior. |
| camera_heightopt | FLOAT | 0.00-0.8–0.8 | Height in sphere radii. Positive moves up; 0 is sphere center. Simulated sphere movement, not real scene depth. Ignored in Flat mode. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| prompt | STRING | — |
| presets_json | STRING | — |