b2KIT

WebGL Shader Playground

Write GLSL vertex and fragment shaders with real-time WebGL rendering and uniform controls.

Tested tool guide Tested browser tools Checked August 16, 2026

What WebGL Shader Playground does, with a checked example

Write GLSL in the editor and the tool compiles it into a WebGL program drawn to a full-screen quad in real time. Uniforms you declare in the shader become controls on the page, so values can be tuned without editing code. The surprise for most newcomers: a fragment shader runs once per pixel, knows nothing about neighboring pixels, and receives coordinates in raw pixels with the origin at the bottom-left, not a tidy 0-to-1 space. Code lifted from desktop GLSL tutorials often fails to compile, because the dialect here is GLSL ES 1.00, not desktop GLSL.

Worked example

A concrete input and expected output from the current implementation.

Input

precision mediump float;
void main() {
  vec2 cell = floor(gl_FragCoord.xy / 32.0);
  float check = mod(cell.x + cell.y, 2.0);
  gl_FragColor = vec4(vec3(check), 1.0);
}

Expected output

A checkerboard of 32-pixel squares covering the whole canvas: black in the bottom-left corner, white in every horizontally or vertically adjacent square, alternating out across the full screen. The pattern is independent of the canvas size, so it looks the same whether the preview window is small or full screen.

Pasted into the fragment editor with the tool's default full-screen-quad vertex shader, this compiles and renders. gl_FragCoord.xy is the current pixel's position in pixels, so dividing by 32 and flooring groups pixels into 32-by-32 cells, and mod() of the sum of cell coordinates alternates between 0.0 (black) and 1.0 (white) from cell to cell; the 0.5-pixel offset of pixel centers never changes the cell index.

How the result is produced

1

Compile, link, render loop

With every change the tool runs the vertex and fragment stages through the shader compiler, checks the error log, and links them into a program; a failing compile surfaces the compiler message with the offending line. A linked program then draws one full-screen quad every animation frame, invoking the fragment shader once per pixel on the GPU.

2

Uniforms become controls

Uniform variables declared in the shader source are read by the tool and exposed as controls matched to their type. Before each frame the tool writes the control values into the running program, so adjusting a control re-renders instantly without recompiling the shader; a uniform is one value shared by every pixel of that frame.

Good uses

  • Prototyping an effect for a larger WebGL project - a gradient, grid, glow, or distortion - and using the uniform controls to find good parameter ranges before porting the final source.
  • Debugging a shader that fails to compile inside another codebase: paste the source here and read the compiler log with its line number, away from unrelated console noise and build tooling.
  • Learning GLSL from scratch by altering one expression and seeing the pixel-level result instantly, which is far faster than a rebuild cycle in a framework or game engine.

Limits and checks

  • A shader that links can still render black, white, or garbage: division by zero is silent and produces NaN, which poisons every pixel, and any uniform the effect depends on that never receives a value stays at its default of 0.
  • Coordinates arrive as raw pixels with the origin at the bottom-left of the canvas, so the same shader looks different at other canvas sizes and effects built for a top-left origin render mirrored. Divide by the canvas resolution to get stable normalized coordinates.
  • The compiler reports at most one error per stage, so a failing shader needs repeated fix-and-rerun rounds, and code written for desktop GLSL or WebGL2 - texture() calls, out variables, missing precision qualifiers - generally will not compile unchanged.

Common questions

The shader compiles but the canvas stays black. What should I check?

In order of likelihood: a uniform the shader uses is not receiving a value and reads as 0; an expression divides by zero or produces NaN, which shows as black or garbage; or the alpha channel is written as 0, letting the background show through. Add a constant-color test case first, then verify each uniform name and value.

Can I paste a Shadertoy shader directly?

Not unchanged. Shadertoy code expects built-in iTime, iResolution, and iMouse values; here you declare your own uniforms for time and resolution and update every reference to them. WebGL2-style code also needs rewriting, since this dialect uses gl_FragColor, texture2D, and an explicit default precision. The adaptation usually takes a few minutes.

References and verification

The example and behavioral notes were checked against the browser implementation. Standards and primary references below define the relevant format, formula, or platform behavior.

Related Tools