Writing a sketch

A GLSL sketch

One folder, one sketch.glsl, no page and no loop.

sketch.glsl, the shape this page describes · moved by a pulse here; in Sialk, by the room

One folder, one sketch.glsl. No page, no render loop, no boilerplate - Sialk supplies all of that, and the audio as uniforms.

my-shader/
  sketch.glsl

Drag the folder onto Sialk. Dragging the .glsl file in directly works too; the folder is incidental.

The smallest one that works

void main() {
  vec2 uv = gl_FragCoord.xy / sialkResolution;
  fragColor = vec4(uv.x, uv.y, sialkLevel, 1.0);
}

Nothing is imported, declared or polled. The values are simply there, updated once per composited frame.

Both dialects

Sialk accepts GLSL ES 3.00 and GLSL ES 1.00, and works out which one you wrote from what is in it - gl_FragColor and texture2D mean 1.00.

Most shaders on the internet are still 1.00, and they should simply run:

precision highp float;

void main() {
  vec2 uv = gl_FragCoord.xy / sialkResolution;
  gl_FragColor = vec4(uv, sialkBass, 1.0);
}

Note that ES 1.00 requires constant loop bounds. That is the language, not Sialk.

What Sialk gives you

Every one of these is supplied as a uniform. They carry the same meanings as the audio contract, which is where the detail lives.

Uniform Type
sialkResolution vec2 The surface being composited, in pixels.
sialkTime float Show transport position, in seconds.
sialkDelta float Seconds since the previous frame.
sialkFrame float Frames since this sketch loaded.
sialkLevel float Broadband loudness, 0-1.
sialkBass sialkMid sialkHigh float The three bands, 0-1.
sialkHits float Onset counter.
sialkOnBeat float 1 on the beat, decaying.
sialkBeatPhase float Ramps 0 → 1 between beats.
sialkBpm sialkBpmConfidence float Tempo, and how much to trust it.
sialkSilent float 1 when the input has been quiet for a second.
sialkSpectrum sampler2D 64 bins as a texture.
sialkLevelTrail sampler2D 128 frames of level as a texture.

Two helpers save you the texture lookup, in both dialects:

float sialkBand(float t);   // t 0..1 across the spectrum
float sialkTrail(float t);  // t 0..1 back through the level trail

#define SIALK_CONTRACT 1 is set, so a shader can compile both inside Sialk and outside it.

A shader you wrote for Shadertoy

iTime, iResolution, iFrame and iMouse are defined, so a shader you wrote in that dialect yourself should run as it is. iMouse is a constant zero, pointer input arrives with v1.

Making it react

The whole point. Instead of a constant, reach for a band:

float radius = 0.2 + sialkBass * 0.3;

Leave headroom, see the audio for why a value that saturates at 0.9 makes a loud room and a very loud room look identical.

sialkBeatPhase is usually better than sialkOnBeat for anything that should decay: 1.0 - sialkBeatPhase is a fall that is in time with the music rather than with a number you picked.

Cost

GLSL cares about pixels, and about nothing else. A loop that always runs to the end costs its full length at every pixel, at 4K that is 8.3 million times. A distance field that converges early is cheap; step count alone tells you very little.

If a shader collapses at 4K but is fine at 720p, that is the shape of the problem, and it is not something Sialk can fix for you.