Render GLSL fragments to PNG or standalone HTML using Puppeteer and WebGL2.
This tool is designed to facilitate an incremental development cycle for fragment shaders, allowing you to quickly iterate on your GLSL code and verify the results.
- glsl2png: Render a GLSL fragment shader to a PNG image.
- glsl2html: Generate a standalone, responsive HTML file that runs the shader in a browser.
- Headless & Visible: Supports headless rendering for CI/CD or visible mode for live preview.
- Multi-frame Support: Specify multiple time points to generate a sequence of images.
- WebGL2 Support: Built for modern GLSL (ES 300).
npm install -g @tir.jp/glsl2pngOr use it directly via npx:
npx @tir.jp/glsl2png --helpRender a shader to a PNG file.
glsl2png <fragment_shader_path> [options]Options:
--width <number>: Canvas width (default: 512).--height <number>: Canvas height (default: 512).--time <number>: Time value to pass asu_time. Can be specified multiple times for multiple outputs.--out <path>: Output PNG path (default:output.png).--no-headless: Launch browser in non-headless mode for live preview.
Example:
# Single image at time 1.0
glsl2png samples/basic.frag --time 1.0 --out result.png
# Multiple images (generates animation_0.png, animation_1.png, ...)
glsl2png samples/basic.frag --time 0.0 --time 0.5 --time 1.0 --out animation.pngGenerate a standalone HTML file. It is auxiliary tool for share glsl animation easily.
glsl2html <fragment_shader_path> [options]Options:
--width <number>: Canvas width (default: 512).--height <number>: Canvas height (default: 512).--out <path>: Output HTML path (default:output.html).
Example:
glsl2html samples/basic.frag --out preview.htmlYour fragment shaders should follow the WebGL2 (ES 300) specification:
- Header: Must include
#version 300 es. - Precision: Must define precision, e.g.,
precision highp float;. - Input: Use
in vec2 v_uv;to get the aspect-corrected vertex position (the shorter axis is in the range -1.0 to 1.0). - Output: Use
out vec4 fragColor;instead ofgl_FragColor. - Built-in Uniforms:
uniform vec2 u_resolution;: Viewport resolution (width, height) in pixels.uniform float u_time;: Current time in seconds.
#version 300 es
precision highp float;
in vec2 v_uv;
uniform vec2 u_resolution;
uniform float u_time;
out vec4 fragColor;
void main() {
// v_uv is already aspect-corrected.
// Map to 0.0-1.0 range (caution: range varies by aspect ratio)
vec2 uv = (v_uv + 1.0) * 0.5;
vec3 col = 0.5 + 0.5 * cos(u_time + uv.xyx + vec3(0, 2, 4));
fragColor = vec4(col, 1.0);
}And see samples/ directory.
glsl2png samples/fractal_kifs.frag --out img/fractal_kifs.png --time 1.0glsl2png samples/fractal_raymarching.frag --out img/fractal_raymarching.png --time 1.0glsl2png samples/nature.frag --out img/nature.png --time 1.0glsl2png samples/voronoi.frag --out img/voronoi.png --time 1.0-
3.0.0: 20260506
- Adjust aspect-ratio in vertexShader, not fragmentShader
-
2.0.0: 20260427
- Support
v_uv
- Support
Zlib License.



