Function

@shaders

A GLSL fragment shader rendered with WebGL, as a background image or as a live <canvas> with @content.

Syntax

  • @shaders(<fragment source>)
  • @shaders(fragment { ... } texture0 { <doodle code> })
  • @shaders<width>x<height>(...)

The body is either fragment shader source, or named sections: fragment { }, vertex { } and any number of texture… sections. A texture section holds a doodle which is rendered to an image and bound as a sampler2D of that name. The size suffix caps the raster size.

UniformValue
vec2 u_resolutioncanvas size in pixels
float u_timeseconds since the shader started
float u_timeDeltaseconds since the previous frame
int u_frameIndexframe counter
vec2 u_mousepointer position over the doodle, in pixels
vec2 u_seedtwo values derived from the seed and the cell

Write the output to FragColor or to gl_FragColor, both are accepted, and texture2D() is mapped to texture(). A Shadertoy-style mainImage() with iResolution, iTime, iMouse and iChannel0 works as is. A shader that reads u_time, u_timeDelta or u_frameIndex is redrawn every frame. // comments are allowed inside the body.

Examples

@grid: 1 / 60vmin;
background: @shaders(
  void main() {
    vec2 p = gl_FragCoord.xy / u_resolution.xy;
    FragColor = vec4(p.yx, .8, 1.);
  }
);

Animated, as a canvas:

@grid: 1 / 60vmin;
@content: @shaders(
  void main() {
    vec2 uv = (gl_FragCoord.xy / u_resolution - .5) * 2.;
    float a = atan(uv.y, uv.x);
    float r = length(uv);
    vec3 c = vec3(1., 2., 3.);
    c = .4 + .6 * cos(c + a*2. + r*6. - u_time);
    FragColor = vec4(c, 1.0);
  }
);

A doodle as a texture:

@grid: 1 / 60vmin;
@content: @shaders(
  fragment {
    void main() {
      vec2 uv = gl_FragCoord.xy / u_resolution;
      uv.x += sin(uv.y * 20. + u_time) * .02;
      FragColor = texture(texture0, uv);
    }
  }
  texture0 {
    @grid: 8 / 100%;
    background: @p(#000, #e6437d, #ebbf4d);
  }
);

See also