SPACE.LA
◀ music select
personal / tool / active

tish-shadertoy

A native Shadertoy player for Tish: tish:shadertoy runs any Shadertoy-style GLSL image pass full screen in an OpenGL 3.3 window (winit, glutin, glow). Full Shadertoy uniforms and mouse rules, WebGL-to-desktop compatibility fixes, image and procedural-noise texture channels, render scaling for heavy raymarchers, and Milkdrop-style hotkeys.

BPM
143
GRADE
S
LEVEL
4
RELEASES
0
YEARS
2026–2026
Five bundled shaders running in the native window
tish-shadertoy: A neon tunnel raymarcher
A neon tunnel raymarcher
tish-shadertoy: Raymarching primitives
Raymarching primitives
tish-shadertoy: Alien core
Alien core
tish-shadertoy: A kaleidoscope
A kaleidoscope
tish-shadertoy: Particles
Particles
tish-shadertoy: A forest scene
A forest scene
tish-shadertoy: A waving flag
A waving flag

Shaders In A Window

The prototype from September was two HTML files. Seven months later, on April 9, 2026, I built the idea properly and finished it in a day.

tish-shadertoy is a Rust binary that embeds the Tish evaluator, reads a local GLSL fragment shader written in Shadertoy's image pass style, and runs it in a native OpenGL 3.3 window through winit, glutin and glow. No editor, just point it at a file and watch. Hotkeys come from a hotkeys.toml in the working directory, Milkdrop style, and F3 toggles smoothed FPS in the title bar.

Most of the day went into performance. The window uses a fixed physical pixel size, 1280 by 720 by default, instead of a logical one, because on a HiDPI display a logical size renders two or three times the pixels and a heavy raymarcher drops under twenty frames a second. TISH_SHADER_RENDER_SCALE runs the expensive pass at a fraction of the window and upscales it, while iResolution and fragCoord still report the full size so ported Shadertoy code keeps working. You can turn off vsync to see the uncapped number, and the GL config picker avoids multisampling.

tish-shadertoy is a native Shadertoy player driven from Tish. Point it at a GLSL file written for Shadertoy — the usual mainImage image pass — and it runs it full screen in a native OpenGL 3.3 window, with no browser and no editor. From Tish it is one call: the tish:shadertoy module's run(code) opens the viewer, and the bundled script just reads a path from the command line with tish:fs and hands it over. Underneath is a small Rust crate on winit, glutin and glow, which Rust programs can also embed with a pumped event loop between other native work.

Real community shaders run unmodified. It supplies the full set of Shadertoy uniforms — resolution, time and time delta, frame and frame rate, mouse (with Shadertoy's own click-and-drag rules, so shaders that rotate with the mouse behave), date, sample rate and channel resolutions and times. It closes the gaps between WebGL and desktop GL that otherwise turn shaders black: it defines HW_PERFORMANCE when a shader expects the site to, and a compatibility pass zero-initializes the variables many shaders rely on being zero in a browser. Texture channels can be wired to image files through environment variables or a comment at the top of the shader, and a shader that samples an unset channel gets a procedural tiling noise texture automatically.

It is tuned for heavy raymarchers. The window renders at a fixed physical size so HiDPI screens do not quietly quadruple the work, an internal render scale lets the expensive pass run at a fraction of the resolution and upscale, multisampling is off by default, and vsync can be turned off to see uncapped frame rates. Hotkeys are Milkdrop-style bindings in a TOML file, starting with an FPS readout in the title bar. A folder of community shaders comes with it to try.

before this