Nodes/ComfyUI-ToyShaders/👾 ToyShader Render
ComfyUI Node

👾 ToyShader Render

Run real Shadertoy GLSL shaders inside your ComfyUI graph

By jav12z·Created 9 months ago·Updated 8 months ago· 5
👾 ToyShader Render
  • iChannel0
  • iChannel1
  • iChannel2
  • iChannel3
  • IMAGE
  • DEPTH
width512
height512
frame_count24
fps24
preset
speed1.0
scale1.0
depth_var
depth_scale0.100
invert_depthfalse
tex_0_builtin
tex_1_builtin
tex_2_builtin
tex_3_builtin
main_code
buffer_a_code

The name is accurate for once: this is a toy. But it's a genuinely fun one. ToyShader Render is a ComfyUI node that compiles and runs Shadertoy-style GLSL shaders on your GPU, then hands you back an animated image batch - plus, experimentally, a depth map. No diffusion model involved, no API, no key. If you've ever watched a Shadertoy demo of a kaleidoscope or a burning city and wished you could drop it into a workflow as a background plate or a moving texture, this is the pack for that.

Because it renders into the ComfyUI graph, its output plugs into everything else: feed the frames to a video-combine node for a loop file, or use them as a source for compositing. It's procedural, not generative - a different tool for a different job.

How it works

This isn't WebGL in a browser and it isn't CPU emulation. It renders with moderngl, a real OpenGL 3.3+ binding, into an offscreen framebuffer. The interesting part is the compatibility wrapper: for each frame the node injects Shadertoy's standard uniforms (iTime, iResolution, iFrame, iChannel03), defines a mainImage(...) entry point, and - the clever bit - wraps pow, smoothstep, and clamp in overloads that tolerate the sloppy mixed-vector calls that normally fail compilation. The upshot: copy a Shadertoy shader, paste it, and it usually just compiles. The pack ships 26 presets (clouds, fire, ocean, city flythroughs, "Zippy Zaps") so you can see it work before you touch any code.

The inputs that matter

  • preset - a dropdown built from the .glsl and .txt files in the pack's shaders/ folder. Drop your own files in there and they show up (after a restart, see below).
  • main_code and buffer_a_code - optional strings you can type into or wire in (Shader Code Input is made for this). main_code overrides the preset. buffer_a_code is the multipass trick: its shader renders first into a texture that becomes iChannel0 for the main pass.
  • frame_count and fps - the animation's length; time advances as frame/fps.
  • speed and scale - speed multiplies iTime; scale zooms the fragment coordinate around screen center.
  • depth_var, depth_scale, invert_depth - the experimental depth feature. depth_var is the name of a variable in your shader holding depth (say d). The node injects code that encodes that value into the alpha channel, then pulls it out as a grayscale map; depth_scale tunes the response and invert_depth flips it.
  • tex_0_builtintex_3_builtin and iChannel0iChannel3 - texture sources for the channels. Priority: an external image input wins, then a builtin procedural texture (noise, clouds, wood, checkerboard…), then a white fallback.

Outputs

Two of them, IMAGE and DEPTH - and both are batches of frame_count frames, not single images. That's the most common beginner stumble: the IMAGE output is a video, which is why the node also saves an animated WebP preview to its own thumbnail so you see the loop without doing anything. To get a file, wire IMAGE into a video combine (VHS Video Combine, or a Save Animated WebP node). DEPTH is the same frames as 3-channel grayscale.

Install

In ComfyUI Manager, search "ToyShaders", or by hand:

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

Restart ComfyUI. The dependency that actually matters is moderngl (the rest of requirements.txt is just numpy and Pillow).

Common issues

  1. OpenGL context errors - the real one. Moderngl needs an OpenGL 3.3+ context. On a desktop machine with a GPU you're fine. On a headless Linux server you'll get a context-creation failure; the renderer tries a standalone context, then an EGL backend, and if both fail every frame comes back black. If you're headless, install Mesa EGL or run under xvfb.
  2. New shader files don't appear in preset. The list is scanned when the node loads, so restart ComfyUI (or reload the workflow) after dropping a file into shaders/.
  3. Depth output all black. depth_var must exactly match a variable in your shader, and this feature genuinely doesn't work with every shader - it's flagged experimental in the README for a reason.
  4. Wired-in main_code silently ignored. If the string is under about ten characters the node treats it as empty and falls back to the preset. An empty or stub box does nothing.
  5. Watch the resolution math. frame_count × width × height is a lot of GPU work. 24 frames at 512² is smooth; don't expect 4096² for hundreds of frames to be instant.

ToyShader is a hobby project - the author announced it on r/comfyui in late 2025 and built it with heavy help from an AI coding assistant, and it shows in the best way: small, single-purpose, generous with presets, honest about its experimental bits. One reminder before you ship anything: the engine is MIT-licensed, but shader code lifted from Shadertoy is usually CC BY-NC-SA, so respect the original artists if you go commercial.

CategoryToyShaders

Inputs (20)

NameTypeDefaultDescription
widthINT51264–4096
heightINT51264–4096
frame_countINT24
fpsINT24
presetCOMBO26 options: 301's Fire Shader - Remix 3 , Cloud Ten, Kelp Forest_fishes, Oceanic , Tiled Gilded Rainbow Tunnel, Tokyo , +20
speedFLOAT1.0
scaleFLOAT1.0
depth_varSTRING
depth_scaleFLOAT0.1000.001–10
invert_depthBOOLEANfalse
tex_0_builtinCOMBO9 options: none, Noise White (Mono), Noise White (RGB), Noise Blue (Approx), Bayer 8x8 (Dithering), Clouds (Organic), +3
tex_1_builtinCOMBO9 options: none, Noise White (Mono), Noise White (RGB), Noise Blue (Approx), Bayer 8x8 (Dithering), Clouds (Organic), +3
tex_2_builtinCOMBO9 options: none, Noise White (Mono), Noise White (RGB), Noise Blue (Approx), Bayer 8x8 (Dithering), Clouds (Organic), +3
tex_3_builtinCOMBO9 options: none, Noise White (Mono), Noise White (RGB), Noise Blue (Approx), Bayer 8x8 (Dithering), Clouds (Organic), +3
main_codeoptSTRING
buffer_a_codeoptSTRING
iChannel0optIMAGE
iChannel1optIMAGE
iChannel2optIMAGE
iChannel3optIMAGE

Outputs (2)

NameTypeDescription
IMAGEIMAGE
DEPTHIMAGE