@shader-core/engine
v1.2.0
Published
WebGL2 renderer and layer compositor for Shader Core. Zero runtime dependencies.
Maintainers
Readme
@shader-core/engine
The renderer and layer compositor behind Shader Core. WebGL2 and GLSL ES 3.0. Zero runtime dependencies.
import { compose, createRenderer } from '@shader-core/engine';
import { primitives } from '@shader-core/layers/primitives';
import { definition as gradient } from '@shader-core/layers/gradient';
import { definition as grain } from '@shader-core/layers/grain';
const renderer = createRenderer({
canvas: document.querySelector('canvas')!,
stack: [{ layer: gradient }, { layer: grain, blend: 'multiply' }],
prelude: primitives,
values: [{ colors: { colorA: '#05070d', colorB: '#4338ca' } }, { params: { intensity: 0.3 } }],
});
renderer.setValues([{}, { params: { intensity: 0.6 } }]); // a uniform; no recompile
renderer.dispose(); // releases the GL context, not just its objectsrenderer.ready resolves once the first frame has been drawn — await it before
fading out a poster or placeholder held over the canvas, and the fade can never
uncover an empty one:
renderer.ready.then(() => poster.classList.add('faded'));compile: 'parallel' moves shader compilation off the main thread
(KHR_parallel_shader_compile). The call returns at once, the canvas holds its
last frame until the new program is ready, and compile errors arrive through
onError instead of throwing — so pair it with ready. On a cold cache a
large stack is over 100 ms of main-thread stall on a fast laptop under the
default sync, and none under parallel.
const renderer = createRenderer({ canvas, stack, prelude: primitives, compile: 'parallel', onError });
await renderer.ready; // compiled in the background, first frame drawnA stack of layers becomes one program in one pass — no framebuffers. The program cache is keyed on the stack's shape, so changing a value never recompiles and returning to a shape you have used is free.
What it does for you
It runs inside other people's products, so most of the work is not drawing:
- Pauses off-screen and while the tab is hidden.
prefers-reduced-motionrenders exactly one frame and never animates.- Honours
Save-Data; caps device pixel ratio and total pixels on modest hardware. - Trades resolution for frame rate on a device that cannot keep pace — 2×, 1.5×, 1×, 0.75× the CSS size — and holds a still frame only if even the smallest is below 30fps.
dispose()releases the GL context itself viaWEBGL_lose_context, not only its objects — browsers cap live contexts at roughly 8–16.- Compile errors are reported against the layer file and line you wrote, not against the generated program.
Colours are converted to linear space on the way in, so blending is correct by
construction. #808080 uploads as 0.216, not 0.502.
Licence
Free to use, including commercially. The credit comment stays in shader source you copy. See LICENSE.md.
