Nodes/GLSL Nodes/glslViewer
ComfyUI Node

glslViewer

Run GLSL shaders inside ComfyUI (with real video out)

By patriciogonzalezvivo·Created 2 years ago·Updated about a year ago· 246
glslViewer
  • fragment_code
  • uniforms
  • images
  • mask
  • buffers
width512
height512
frames1
fps30

This is the node the whole pack exists for. glslViewer takes a fragment shader, compiles it with OpenGL through moderngl, and renders it straight to an image tensor you can feed into the rest of your workflow. No model involved, no sampling pass - you're programming the GPU directly, the way Shadertoy does, except the output is a real ComfyUI IMAGE instead of a browser canvas.

Why would you reach for this? Because ComfyUI is a node graph, and a shader is a fast, deterministic, GPU-parallel function from pixel coordinates to colors. That's a huge toolbox for anything that isn't "ask a diffusion model for pixels": procedural textures, depth-of-field and edge-detection post-processing, LUTs, SDF raymarching, optical-flow visualization, dithering, and mask generation. The pack ships examples for all of those, and people have used this node for realtime-style effects that would otherwise be pure Python and slow.

How it works

Give it a GLSL_CODE (from a glslEditor or glslEditorPro node), a width and height, and it renders a full-screen quad with your fragment shader on an offscreen framebuffer. It sets the standard uniforms for you: u_resolution, u_time, u_frame, u_delta, u_fps, and u_date. Those are the exact same uniforms the author's standalone glslViewer tool uses, so shader code ported from there, from glslCanvas, or from the LYGIA ecosystem mostly just works.

The frames and fps inputs are the video trick. With frames: 1 you get a single still. Crank frames to 90 and fps to 30 and it runs the render loop - u_time advances as frame / fps, u_frame counts up - and you get a batched IMAGE sequence out. That output wires straight into VHS_VideoCombine from VideoHelperSuite, which is how people turn a shader into an actual mp4. The pack's own raymarch_buffers and video_flow examples do exactly this.

The three outputs are worth understanding before you wire things up:

  • images (IMAGE) - the RGB of every rendered frame.
  • mask (MASK) - the alpha channel of the same render. If you want a mask out of your shader, write it to gl_FragColor.a. That's the whole mechanism, and it's the reason a lot of masking workflows use this pack.
  • buffers (GLSL_BUFFERS) - the intermediate passes. Feed this into a glslBuffers node to pull individual #ifdef BUFFER_X passes out as their own images.

The optional uniforms input takes a GLSL_CONTEXT from glslUniforms, which caches your textures and values so they don't reload every time you edit code.

Install

The usual two ways:

  • ComfyUI Manager → search "GLSL Nodes" → install, then restart.
  • Manual: cd ComfyUI/custom_nodes && git clone https://github.com/patriciogonzalezvivo/comfyui_glslnodes, then restart. First startup pip-installs moderngl, numpy, and snowy (the last one is optional, used to generate signed-distance fields from masks).

Gotchas

This is a GLSL/OpenGL node, so your box needs a real GPU with a working OpenGL context. On Linux the pack creates a standalone EGL context, so it runs headless - but if you're on a machine with no GPU or a broken driver, shaders won't compile and you'll get errors in the ComfyUI console, not a nice red message in the graph.

Speaking of the console: shader compile errors show up there, with line numbers mapped back to your code. And remember the alpha channel isn't decoration - if you render a shader with alpha: 0.0 everywhere, your mask output will be solid black and that's expected, not a bug.

CategoryGLSL

Inputs (6)

NameTypeDefaultDescription
fragment_codeGLSL_CODE
widthINT512
heightINT512
framesINT1
fpsINT30
uniformsoptGLSL_CONTEXT

Outputs (3)

NameTypeDescription
imagesIMAGE
maskMASK
buffersGLSL_BUFFERS