Nodes/SAM3D Cam Shot Toolkit/Cam Shot Toolkit: Render Offset View
ComfyUI Node

Cam Shot Toolkit: Render Offset View

The payoff node that puts your person back in the shot

By EnviralDesign·Created 6 months ago·Updated about a month ago· 2
Cam Shot Toolkit: Render Offset View
  • mesh_data
  • reference_image
  • rendered_image
  • camera_info
◄render_width512►
◄render_height512►
◄enable_viewertrue►
◄use_interactive_viewtrue►
◄autofalse►
◄show_viewer_hudfalse►
◄focal_scale1.00►
◄lighting_presetstudio►
◄ambient_intensity0.35►
◄key_intensity14.0►
◄key_yaw35.0►
◄key_pitch35.0►
◄fill_intensity6.0►
◄rim_intensity8.0►
◄mesh_r235►
◄mesh_g235►
◄mesh_b235►
◄bg_presetmid_gray►
◄bg_r38►
◄bg_g38►
◄bg_b38►
◄interactive_state{}►

This is the node the whole pack is named after, and the reason a 3D reconstruction is worth doing at all. Process Image gives you a mesh of a person standing in some original photo; Render Offset View lets you move the camera around that mesh and render a new frame - same person, same world, different angle - while keeping the lens calibrated to the original shot. If you've ever tried to fake a new camera angle on a 2D image with ControlNet and watched it invent geometry, this is the version that doesn't have to guess.

How it works

Two inputs set the whole thing up. mesh_data comes straight from Process Image, and reference_image is the photo the person was reconstructed from. The node reads the reconstruction's focal length and uses the reference image's aspect ratio to compute matching intrinsics - fx, fy, and the principal point - scaled to your render_width/render_height. That's the "calibrated" part: the render behaves like a real camera that was at the original shoot, so a focal_scale of 1.0 puts the mesh back in roughly the same framing the photo had.

Then it renders. Here's the part worth appreciating: there's no PyOpenGL, no pyrender, no OSMesa, no EGL - nothing to compile. The pack ships a self-contained NumPy mesh rasterizer that projects vertices, shades faces, and composites the frame. It's deliberately simple (flat-ish studio shading, mesh color, background color), but it runs anywhere your Python runs and installs without a fight. That trade - boring shading for zero native-dependency pain - is the right one for a tool whose whole point is camera setup, not final beauty lighting.

The interactive viewer

The fun part is enable_viewer. When it's on, the node mounts a Three.js preview in the browser where you can orbit, pan, roll, and dolly the camera to scout your shot. The camera you settle on gets saved into the hidden interactive_state string, and on the next workflow run the backend rasterizer reproduces that exact pose - no live WebGL frame, just the saved state. Two switches govern this:

  • use_interactive_view (default on) - the browser camera overrides the parameter-based camera when saved state exists.
  • auto (default off) - ignore any saved viewer camera and realign from the current SAM 3D input on every run. This is the one to flip for API/batch workflows where you don't want a stale saved camera from a previous session steering your render.

For beginners, the honest workflow is: keep use_interactive_view on, scout in the viewer, and let the saved state do the work. The parameter camera (key/lighting/bg fields) matters more once you want reproducible shots without the viewer.

The inputs you'll actually touch

Beyond the camera logic above: lighting_preset (studio/flat/dramatic), bg_preset (mid_gray/black/white/custom), mesh_r/g/b to tint the mesh, and focal_scale to push the lens wider or tighter. Render size caps at 4096. The two outputs are rendered_image (a normal IMAGE you can preview, save, or feed back into a pipeline) and camera_info, a JSON string carrying the calibrated camera - focal lengths, principal point, camera position, target - which is gold if you're exporting the shot to Blender or Unreal later.

Installation and gotchas

Same pack install as everything else here:

cd ComfyUI/custom_nodes
git clone https://github.com/EnviralDesign/sam3d-body-comfyUI-camshottoolkit
python -m pip install -r sam3d-body-comfyUI-camshottoolkit/requirements.txt

Restart, then wire mesh_data and the original photo in. The two ways people trip: forgetting reference_image, which the node needs to define intrinsics (wire the same image you processed - it's required, so this is less a trap and more a "why won't it connect" moment), and expecting a photoreal render. This is a preview/blocking render, not a final beauty pass - it gets the camera right, and you take the camera_info out to a real renderer for the pretty version.

CategoryCamShotToolkit/visualization

Inputs (24)

NameTypeDefaultDescription
mesh_dataSAM3D_OUTPUTMesh data from SAM3DBodyProcess node
reference_imageIMAGEReference image used to define the original camera intrinsics
render_widthINT51264–4096—
render_heightINT51264–4096—
enable_viewerBOOLEANtrueMount the interactive preview viewer for this node.
use_interactive_viewBOOLEANtrueIf enabled, the browser viewer camera overrides the parameter-based camera when available.
autoBOOLEANfalseIgnore saved viewer camera state and align from the current SAM3D input on every run.
show_viewer_hudBOOLEANfalseShow the camera HUD overlay in the interactive viewer.
focal_scaleFLOAT1.000.1–4—
lighting_presetCOMBOstudioQuick lighting profile
ambient_intensityFLOAT0.350–3—
key_intensityFLOAT14.00–100—
key_yawFLOAT35.0-180–180—
key_pitchFLOAT35.0-89–89—
fill_intensityFLOAT6.00–100—
rim_intensityFLOAT8.00–100—
mesh_rINT2350–255—
mesh_gINT2350–255—
mesh_bINT2350–255—
bg_presetCOMBOmid_grayQuick background color preset
bg_rINT380–255—
bg_gINT380–255—
bg_bINT380–255—
interactive_stateSTRING{}Hidden interactive camera state managed by the viewer.

Outputs (2)

NameTypeDescription
rendered_imageIMAGE—
camera_infoSTRING—