Nodes/ComfyUI_3DGaussianSplatting/3DGS Preview (2 Images)
ComfyUI Node

3DGS Preview (2 Images)

Two photos → a 3D Gaussian splat, minus the CUDA torture

By bemoregt·Created 6 months ago·Updated 6 months ago· 0
3DGS Preview (2 Images)
  • image1
  • image2
  • rendered_preview
render_width512
render_height512
max_gaussians1000
gaussian_scale0.025
novel_view_yaw15
novel_view_pitch-5
background_colordark

Here's the thing about 3D Gaussian Splatting in ComfyUI: the serious implementations are a pain to install. Compiled C++/CUDA rasterizers, a CUDA toolkit that has to match your driver exactly, strict numpy version pinning, 16 GB of VRAM, and training runs measured in minutes. People spend an afternoon just getting the node to appear in the menu. Then there's this one.

3DGS Preview (2 Images) takes two photographs of the same scene and renders a novel-view preview using Gaussian Splatting - no pretrained model, no CUDA extensions, no optimization loop. It's pure Python (torch + OpenCV) with a CPU fallback - the opposite end of the effort spectrum from every other 3DGS node you'll find. And the README is refreshingly honest about what you get: with only two images the scene reconstructs as a sparse point cloud, so the output is an informative structural preview, not a dense photorealistic render. Think "sketch with parallax," not "Nerf replacement."

How it works

Despite the buzzword title, this is classical structure-from-motion under the hood. Reading the source (gs_preview_node.py): SIFT keypoints in both images (falling back to ORB if SIFT isn't available) get matched with a Lowe ratio test, then an essential matrix computed via RANSAC is decomposed into the relative camera pose. That pose lets it triangulate the matched points into a sparse 3D cloud, which gets filtered for junk and normalized to unit scale.

Then the splatting part. Each surviving 3D point becomes one isotropic Gaussian, colored by sampling image 1 at the feature pixel. A virtual camera sits at z = −2.5, rotated by your yaw and pitch, projects the Gaussians through a pinhole model, sorts them back-to-front, and does batched weighted-additive splatting on torch tensors before compositing over a background color. A real splatter, just a deliberately simple one.

If reconstruction fails - too few keypoints, bad matches, degenerate pose - the node falls back to a side-by-side of your two inputs rather than erroring. You always get an image out, which makes it painless to test.

The inputs that actually matter

Only two inputs are required: image1 and image2 - two photos of the same scene from a slightly different angle. Everything else is optional, and really only three of them matter:

  • novel_view_yaw / novel_view_pitch - where the virtual camera looks from. The defaults (15°, −5°) give a hint of parallax. Crank yaw toward ±90 and few or no points end up in front of the camera - a blank render is the tell.
  • max_gaussians - the cap on triangulated points used as Gaussian centers (100–5000, default 1000). More = denser preview and a slower render.
  • gaussian_scale - size of each Gaussian relative to focal length. Too low and you get barely-visible specks; too high and everything turns to mush. The README's 0.01–0.08 band is the sweet spot.

render_width/render_height set output resolution (64–2048, default 512); background_color picks the fill behind the splat. Output is a single IMAGE, rendered_preview - wire it into a Save Image or PreviewImage.

Installing it

No model files to download, no CUDA toolkit, no compiled submodules - just the usual clone-and-install:

cd ComfyUI/custom_nodes
git clone https://github.com/bemoregt/ComfyUI_3DGaussianSplatting
pip install -r ComfyUI_3DGaussianSplatting/requirements.txt

Then restart ComfyUI and look for "3DGS Preview (2 Images)" under 3D / Gaussian Splatting (ComfyUI Manager can find it too). torch, numpy, and Pillow you already have from ComfyUI itself; opencv-python >= 4.7 is the one genuinely new dependency, so make sure it lands in the same Python environment as ComfyUI. GPU is used automatically when present, CPU otherwise.

When it's good, and when it lies to you

The inputs are the single biggest lever: the two photos should show the same textured scene from about 10–40° apart. Flat walls, blank sky, and textureless surfaces give SIFT nothing to grab, and you'll get the side-by-side fallback instead of a splat. If the result is too sparse, raise max_gaussians or feed higher-resolution images. Blobs too big? Drop gaussian_scale. Barely visible? Raise it.

Two things worth knowing before you blame yourself. The focal length is guessed as max(H, W) × 1.2 rather than measured, so heavily distorted or fisheye lenses degrade the reconstruction. And black output was a real bug here once - the repo's single commit is literally "Fix black output: camera position was behind the scene" - so a blank frame at an extreme angle is usually points rotating behind the camera, not a broken install.

So where does this fit? If you're blocked on installing one of the heavyweight 3DGS wrappers, or you just want to sanity-check whether two views have enough overlap to bother with the full photogrammetry rig, this is a zero-friction on-ramp. It won't produce portfolio-grade results, and it isn't trying to. It just also won't compile CUDA in your sleep.

Category3D/Gaussian Splatting

Inputs (9)

NameTypeDefaultDescription
image1IMAGE
image2IMAGE
render_widthoptINT51264–2048
render_heightoptINT51264–2048
max_gaussiansoptINT1000100–5000Triangulated points used as Gaussian centers
gaussian_scaleoptFLOAT0.0250.001–0.3Gaussian size relative to focal length
novel_view_yawoptFLOAT15-90–90Horizontal rotation of novel viewpoint (degrees)
novel_view_pitchoptFLOAT-5-45–45Vertical tilt of novel viewpoint (degrees)
background_coloroptCOMBOdark4 options: dark, white, black, transparent

Outputs (1)

NameTypeDescription
rendered_previewIMAGE