Skip to content

HenriqueStelzer/glsl-helpers-react

 
 

Repository files navigation

glsl-helpers-react

npm version gzip size MIT Licence

roadmap roadmap specs changelog migration 2.0 textures multi-pass uniforms troubleshooting contributing issues playground demo demo sandbox

React GLSL canvas with Shadertoy-compatible uniforms and extended helpers.

Fork notice: This project is a maintained fork of mvilledieu/shadertoy-react. The prior npm package for this fork was shadertoy-react-19. Version 2.x ships as glsl-helpers-react with a new primary API (GlslCanvas) while keeping a deprecated ShadertoyReact alias.

What's new in 2.x

  • GlslCanvas — new primary component export
  • WebGL2 / GLSL 3.00 — auto-detect or force via webgl="auto" | "1" | "2"
  • React 19 support
  • TypeScript definitions — props IntelliSense via index.d.ts
  • Reactive propstextures, fs, defines, and shader schema updates without remounting
  • defines prop — inject #define constants from React
  • srcSet textures — responsive image density like <img srcSet />
  • iChannelTime — per-channel playback time (videos sync to currentTime)
  • Extended textures — camera, data, cube maps, keyboard input
  • Multi-pass rendering — Shadertoy-style buffer passes via passes prop
  • persistentTime — opt-in iPersistentTime uniform that survives page refresh

Documentation

Install

npm install glsl-helpers-react

Quick start

import React from "react";
import GlslCanvas from "glsl-helpers-react";

const fs = `
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
  vec2 uv = fragCoord / iResolution.xy;
  fragColor = vec4(0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0.0, 2.0, 4.0)), 1.0);
}
`;

export default function App() {
  return (
    <div style={{ width: "100vw", height: "100vh" }}>
      <GlslCanvas fs={fs} />
    </div>
  );
}

Playground

One shader, zero clone — edit an annotated .frag in the browser (Shadertoy syntax, built-in uniforms, iPersistentTime).

Source: sandbox/playground

Demo

Full 15-tile demo grid (expanded from upstream examples/) — mouse, textures, multi-pass, camera, keyboard, …

Deploy after examples/ changes: npm run publish-demo (see CONTRIBUTING). Run locally: npm start in the repo root.

Demo sandbox

Fullscreen router demo matching upstream CodeSandbox Demos+ More menu, one shader per route (Basic, Textures, Custom Uniforms, built-in uniform showcases).

Source: sandbox/demo-sandbox

Migration from shadertoy-react

Before After
import X from 'shadertoy-react' import GlslCanvas from 'glsl-helpers-react'
<ShadertoyReact fs={fs} /> <GlslCanvas fs={fs} />
npm: shadertoy-react-19 npm: glsl-helpers-react

Legacy import (deprecated):

import { ShadertoyReact } from "glsl-helpers-react";

Props

Prop Type Description
fs string Fragment shader (Shadertoy or classic GLSL syntax)
vs string Optional vertex shader
passes PassProps[] Multi-pass pipeline (see below)
textures TextureProps[] Input channels (iChannel0, …)
uniforms object Custom uniforms
defines object #define constants injected into the shader
clearColor [r,g,b,a] WebGL clear color (default [0,0,0,1])
precision lowp | mediump | highp GLSL float precision
devicePixelRatio number Canvas pixel density (default 1)
webgl auto | 1 | 2 WebGL version selection
lerp 0–1 Mouse position smoothing
style CSSProperties Canvas inline style
contextAttributes WebGLContextAttributes Passed to getContext
onDoneLoadingTextures function Called when all textures are loaded
persistentTime boolean | object Opt-in epoch time via iPersistentTime (survives refresh)

Built-in uniforms

Shadertoy-compatible uniforms are injected automatically when referenced in your shader:

  • iTime, iTimeDelta, iFrame, iResolution, iDate, iMouse
  • iChannel0iChannelN, iChannelResolution, iChannelTime
  • iDeviceOrientation (extension)
  • iPersistentTime (extension; requires persistentTime prop)
  • #define DPR from devicePixelRatio

Unused uniforms skip event listeners and GPU uploads.

Persistent time (persistentTime)

// Continues across page refresh (localStorage)
<GlslCanvas fs={fs} persistentTime />

// Custom epoch and shared storage key
<GlslCanvas
  fs={fs}
  persistentTime={{
    epoch: "2026-01-01T00:00:00Z",
    storageKey: "my-app:shader-clock",
    shared: true,
  }}
/>

Use iPersistentTime in the shader for wall-clock phase; iTime remains session time since mount. See Uniforms.

Custom uniforms

<GlslCanvas
  fs={fs}
  uniforms={{
    uScroll: { type: "1f", value: scrollY },
    uMatrix: { type: "Matrix2fv", value: [0, 1, 2, 3] },
  }}
/>

Supported types: 1f, 2f, 3f, 4f, 1fv4fv, 1i4i, 1iv4iv, Matrix2fv, Matrix3fv, Matrix4fv.

#define from props

<GlslCanvas fs={fs} defines={{ PI: "3.14159", FEATURE_FLAG: 1 }} />

Textures

// Image or video URL
{ url: "./texture.png" }

// Responsive srcSet (1x, 2x, 3x)
{ url: "./a.png", srcSet: { 1: "./a.png", 2: "./a@2x.png", 3: "./a@3x.png" } }
// or: srcSet: "a.png 1x, a@2x.png 2x"

// Camera feed (requires HTTPS and user permission)
{ type: "camera", facingMode: "user", width: 640, height: 480 }

// Raw data texture (rgba32f requires WebGL2 or OES_texture_float)
{ type: "data", width: 256, height: 256, data: uint8Array, format: "rgba8" }

// Cube map (6 face URLs: +X, -X, +Y, -Y, +Z, -Z)
{ type: "cube", urls: [px, nx, py, ny, pz, nz] }

// Keyboard input (Shadertoy-style 256×3 data texture)
{ type: "keyboard" }

Import filter/wrap constants:

import GlslCanvas, { LinearFilter, RepeatWrapping } from "glsl-helpers-react";

Multi-pass rendering

<GlslCanvas
  passes={[
    { fs: bufferShaderA, target: "bufferA" },
    { fs: bufferShaderB, inputs: ["bufferA"], target: "bufferB" },
    { fs: finalShader, inputs: ["bufferA", "bufferB"] },
  ]}
/>

Each pass renders to an internal framebuffer (target) or to the screen (last pass). Buffer outputs are wired to iChannel0, iChannel1, … in subsequent passes via inputs.

Limitations: One framebuffer per target name (no automatic ping-pong). Self-feedback shaders read the previous frame's buffer. See Multi-pass.

WebGL2 / GLSL 3.00

Set webgl="2" or webgl="auto" (default). Shadertoy syntax is rewritten automatically (gl_FragColorfragColor, texture2Dtexture). You can also author shaders with #version 300 es directly.

How it works

A full-viewport quad is rendered with WebGL. Canvas size follows the parent element (100% × 100% by default, overridable via style). Uniforms and textures referenced in the shader source are detected at compile time — unused inputs do not register listeners or GPU state.

Roadmap status

Current line: 2.1.2 on test/sandbox-playground — pending merge to main and npm publish. Full backlog: roadmap · spec index.

Shipped (2.x)

Feature Status
Module / props IntelliSense Done (2.x)
Dynamic texture reload on prop change Done (2.x)
Responsive srcSet textures Done (2.x)
#define from props Done (2.x)
Camera feed texture Done (2.x)
Data texture Done (2.x)
WebGL2 / GLSL 3.00 Done (2.x)
Keyboard input texture Done (2.x)
iChannelTime Done (2.x)
Cube texture Done (2.x)
Multi-pass rendering Done (2.x)
Persistent time (iPersistentTime) Done (2.x)
Demo grid scroll UX + jump nav Done (2.1.0)
Three-tier demos (playground / sandbox / grid) Done (2.1.1–2.1.2)
Canvas sizing + texture flipY + multi-pass channels Done (2.1.2, branch)
Playwright visual regression CI Done (2.1.2, branch)

Next

Version Feature Review spec
2.1.2 Release merge + npm + GitHub Pages release review · changelog 2.1.2
2.1.3 SECURITY.md review
2.1.3 Deprecate shadertoy-react-19 on npm review
2.1.3 ESM exports map review
2.1.4 Dependabot + changelog CI guard Dependabot review
2.1.4 Unit tests (shader preprocessor) review
2.1.5 Framework cookbooks (Next/Vite/Remix) review
2.2.0 Framework-agnostic core review

License

MIT — see LICENSE. Original work © Morgan Villedieu; fork maintenance © Henrique Stelzer de Oliveira.

Shader examples in examples/src/shaders/ may carry separate licenses (e.g. CC BY-NC-SA from Shadertoy) noted in file headers. Those licenses apply to shader source only, not the npm package.

Attribution

Based on shadertoy-react by Morgan Villedieu. Shadertoy uniform conventions follow Shadertoy.

About

Shadertoy-like React component for rendering fragment shaders in your web apps — WebGL, uniforms, and channels handled for you.

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages