Render shaders from the command line
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Build Status Go Report Card

Shady is a nifty CLI tool for rendering GLSL fragment shaders for easy development and hacking.



go get -u

Writing Shaders

The basic setup is a single fragment shader, like a regular fragments shader, calculates the color for each pixel. But instead of receiving vertex and normal and transformation information from the vertex shader, it defines it's own algorithm for shapes.

GLSL Sandbox

Besides gl_FragCoord, the following inputs are available:

  • uniform float time: the time since startup in seconds
  • uniform vec2 resolution: the resolution of the display in pixels
  • uniform sampler2D backbuffer: a texture storing the previously rendered image
  • varying vec2 surfacePosition: the panning position. For backwards compatibility
  • varying vec2 surfaceSize: the resolution after zooming. For backwards compatibility
  • uniform vec2 mouse: the position of the mouse cursor relative to the bottom left corner. Shady is a CLI application so this will never be fully supported. However, the value is set to the center of the display.

Check out example.glsl to see what a shader for this website looks like.


Currently, the iTime, iTimeDelta, iFrame, iDate, iMouse, and iResolution, iChannelResolution uniforms are supported. Other uniforms are defined but not initialized.

It is possible use resources like images, videos and audio from shaders in this environment by using the iChannelX samplers. On the website, one can select this resource input mapping using dialogs. This implementation requires these mappings to be specified in the shader source. When this is done, the uniform is declared automatically.

Mappings are declared in a special directive that is parsed by shady. These are typically inserted at the top of the file. It's format is:

#pragma map <uniform name>=<namespace>:<value>

uniform name is the name of the sampler uniform that is inserted into the source of the fragment shader. namespace specifies how value should be interpreted. The builtin namespace gives access to the presets that can be found on ShaderToy. Setting the namespace to image interprets the value as a path relative to the shader source file to use as texture.

Accepted values for builtin are:

  • Back Buffer
  • RGBA Noise Small
  • RGBA Noise Medium

Example: Enable the sampler named iChannel0 as a texture with the builtin "RGBA Noise Medium" preset:

#pragma map iChannel0=builtin:RGBA Noise Medium

Example: Map iChannel1 to an image referenced by a path relative to the shader source file. Image files become sampler2D type uniforms.

#pragma map iChannel1=image:image.png

Example: Map iChannel2 to the audio output of MPD. Audio sources become sampler2D type uniforms two pixels high. The top row is the spectrum, the bottom is the signal.

#pragma map iChannel2=audio:~/.mpd/mpd.fifo;22000:1:s16le

See also for info on how to write shaders for ShaderToy.


Ledcat is a program that can be used to control lots of LEDs over lots of protocols. Shady can be combined with Ledcat to bring the fireworks to your LED-displays!

It can be installed like this when you have the Rust Language:

cargo install ledcat

To aid development, Ledcat can be used to simulate a display in a terminal like this:

# LEDCAT_GEOMETRY is a special env var that Ledcat and Shady use to set the
# display size. It is also possible to use the -g flag on both programs.
export LEDCAT_GEOMETRY=128x128

shady -i example.glsl -ofmt rgb24 -framerate 20 | ledcat --framerate 20 show


FFmpeg may be used to render to video files:

# Render at 1024x768 at 20 fps and show it, the same as using `-ofmt x11`:
shady -i example.glsl -ofmt rgb24 -g 1024x768 -framerate 20 \
  | ffplay -f rawvideo -pixel_format rgb24 -video_size 1024x768 -framerate 20 -

# The same, but render 12 seconds to an MP4 file
shady -i example.glsl -ofmt rgb24 -g 1024x768 -framerate 10 \
  | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 1024x768 \
    -framerate 10 -t 12 -i - example.mp4

Kinect depth image

If Shady was compiled using the kinect build tag, it is possible to use a Kinect's RGB and depth image in shaders. Just pass -tags kinect to go build when building and use #pragma map kinect=kinect:on to create a sampler2D of the Kinect's video stream. The alpha channel holds the depth image.

Internally, libfreenect is used which only supports the earlier Kinect versions for the XBox 360.


My performance is really bad

Some shaders can really ask a lot from a system, in these cases it may not be possible to animate real time. If it is acceptable to have the animation be of finite length and restart after a while, write a series of frame to a file, and load them in a loop.

# Render a 20 second loop to a file:
shady -i example.glsl -g 64x64 -framerate 60 -numframes $((20*60)) -ofmt rgb24 -o ./my-animation.bin

# Play the animation repeatedly:
while true; do
    cat ./my-animation.bin | ledcat -g 64x64 -f 60 show

Optionally, you could use something like gzip to reduce the file size.

EGL is not initialized, or could not be initialized

Headless rendering is possible. If $DISPLAY is unset because X11 is not running, try running shady with the EGL_PLATFORM env var set to surfaceless or drm.

If you still are not able to get shady to run headless, animate to a file and play from that file in real time. See above.


Error compiling fragment shader:
0:2(1): error: syntax error, unexpected NEW_IDENTIFIER

The above error could be caused by a precision mediump float; being present. Because this is an OpenGL ES directive, it is not supported. Try removing it or wrapping with a preprocessor macro:

#ifdef GL_ES
precision mediump float;


Galaxy Space Thingy Tunnel Wolfenstein