ComfyUI Node

3D Model Viewer

A 3D model viewer in ComfyUI that renders you a depth map too

By aesethtics·Created 11 months ago·Updated 11 months ago· 3
3D Model Viewer
    • rendered_image
    • depth_map
    model_path
    canvas_width512
    canvas_height512
    camera_x0.0
    camera_y0.0
    camera_z0.0
    lookat_x0.0
    lookat_y0.0
    lookat_z0.0
    camera_near0.10
    camera_far10
    focal_length50

    Most 3D work in ComfyUI happens the boring way: you load a depth map or a mesh in some other program, then bring the pixels in. The 3D Model Viewer node flips that. It embeds a real interactive Three.js viewport right inside a node, lets you spin a .glb model around with proper camera controls, and hands you two actual IMAGE tensors at the end - the color render and a normalized depth map. It's from the small beta pack aesethtics/comfyui-3d-model-viewer, and it's exactly what the description says: a personal-workflow tool with zero impressions to its name. Don't expect a polished product or rapid updates. Do expect the lowest-friction way to get a real GLB into your graph.

    How it actually works

    The mechanism is worth understanding because it explains the one gotcha that will absolutely trip you up. This is a frontend/backend split. You give the node a model_path, and on queue the Python side validates the file, copies it into ComfyUI/web/temp_models (with an md5-hashed filename so duplicates don't collide), and serves it over a local /temp_models/ route. The browser side - Three.js r170, loaded from a CDN - renders the model to a WebGL canvas.

    Then the clever part: it does a dual-pass render. Pass one draws the scene as you see it. Pass two re-renders into a WebGLRenderTarget with a real depth texture, runs a custom shader that inverts and normalizes it against your near/far planes so closer is brighter, and produces a clean grayscale depth map. Both passes are captured as base64 PNGs and POSTed back to /threejs_capture_image and /threejs_capture_depth, where ComfyUI-side handlers convert them into float image tensors and stash them in globals. The next time the workflow runs, the node returns those stored tensors.

    Which leads to the gotcha: the first run returns a blank black 512×512 image. There's nothing captured yet, so the node hands you torch.zeros. The intended flow is: set your path, hit the Initialize Preview button on the node, mouse around until the view is good, then queue - and the second run carries real pixels out through the outputs.

    The inputs that matter

    Eleven inputs, and honestly you'll set three of them most of the time:

    • model_path - the one that matters. A full absolute filepath to a .glb (or .gltf) file, no quotes. The README's example workflow points at assets/axis-checker-v02.glb.
    • canvas_width / canvas_height - output resolution, 512–2048. Pixel mapping is 1:1, so these match the output exactly.
    • focal_length - 10–200mm, default 50. That's 35mm-equivalent: wide angles show more scene, telephoto zooms in. The other sliders (camera_x/y/z, lookat_x/y/z, camera_near/far) are there when you need a specific angle or to fix a clipped depth range.

    Outputs

    Two IMAGE tensors: rendered_image (the color render) and depth_map (the normalized grayscale). Both wire straight into a Save Image node, or - the actually interesting part - depth_map feeds a ControlNet depth preprocessor for structure-preserving generation, or a parallax/displacement workflow. Getting a mesh-accurate depth map without any 2D depth-estimation model is this node's real selling point; a standard depth estimator has to guess at geometry, this one just reads the depth buffer.

    Install

    ComfyUI Manager is the easy path - search "3D Model Viewer" under this pack. Or manually:

    cd ComfyUI/custom_nodes
    git clone https://github.com/aesethtics/comfyui-3d-model-viewer.git
    pip install -r comfyui-3d-model-viewer/requirements.txt
    

    Restart ComfyUI and the node appears under aesethtics/3D. Dependencies are almost nothing: Pillow, numpy, torch - all things a working ComfyUI already has. The real requirement nobody warns you about is that Three.js loads from a CDN, so an offline ComfyUI instance renders nothing. And you supply your own GLB; there are no model downloads.

    Troubleshooting

    • First run is black - not broken, that's the capture cycle. Preview, then re-queue.
    • Nothing loads - GLB/GLTF only, and the path must be absolute. Also note the README's beta blurb says "GLB files only," so treat .gltf as the less-tested path even though the code accepts it.
    • View looks weird or broken - the README's fix is click Initialize Preview; it reloads the model and fixes most display issues.
    • Changing canvas size doesn't re-render - a known quirk; nudge any camera value (e.g. camera_near 0.10 → 0.11) to force it.

    It's a beta tool from a solo dev, so don't be shy about opening issues. And if you need transform gizmos, normal passes, and six render outputs, the bigger Three.js viewer packs are where the community has gone - but for "show me this GLB and hand me its depth map," this one stays surprisingly hard to beat for weight.

    Categoryaesethtics/3D

    Inputs (12)

    NameTypeDefaultDescription
    model_pathSTRING
    canvas_widthINT512512–2048
    canvas_heightINT512512–2048
    camera_xFLOAT0.0-50–50
    camera_yFLOAT0.0-50–50
    camera_zFLOAT0.0-50–50
    lookat_xFLOAT0.0-50–50
    lookat_yFLOAT0.0-50–50
    lookat_zFLOAT0.0-50–50
    camera_nearFLOAT0.100.01–10
    camera_farFLOAT101–100
    focal_lengthFLOAT5010–200

    Outputs (2)

    NameTypeDescription
    rendered_imageIMAGE
    depth_mapIMAGE