Join our newsletter to stay up to date on our progress!
Join our newsletter to stay up to date on our progress!
React Shaders is our open source library for creating GLSL/WebGL shaders in React and Typescript, with support for modern shader bindings like those in Shadertoy and Rysana.
npm i react-shaders
import { Shader } from 'react-shaders'
import code from './example.glsl'
return (
<Shader fs={code} />
)
The <Shader />
component is a lightweight React component for creating responsive, full canvas shaders through WebGL to any react-dom
app. It supports the Shadertoy/Rysana GLSL syntax, as well as the classic GLSL syntax, allowing you to easily copy and paste shaders from Shadertoy or Rysana Shader Playground into your applications with no need to modify the code.
It also supports a wide range of built-in uniforms like playback time, resolution, mouse position, and even phone gyroscope position, and allows you to pass custom uniforms as props.
<Shader />
uses WebGL on a <canvas />
and renders a material on a full viewport quad composed of 2 triangles. The canvas size matches the CSS size of your element, by default it at 100% 100%
of your parent element size, but this can be changed by passing a custom CSS style={}
prop to your component. It also makes sure that anything that is not used in your shader is not activated in JavaScript to avoid useless event listeners, etc. so if you don't use the iMouse
uniform the mouse event listener will not be activated and the iMouse
uniform will not be added and passed to your shader.
We're working on a more direct playground for this library, but you can try out the underlying library on Rysana Shader Playground for the time being.
Here are a few built in react props you can pass to your component:
See the WebGL docs for details on custom context attributes, or clear color.
Built in uniforms are uniforms that are being passed automatically to your shader without having you doing anything. You can start using every single one of them without having to do anything. We are taking care of that for you.
uniform float iTime
-- Shader playback time (in seconds).uniform float iTimeDelta
-- Render time (in seconds).uniform int iFrame
-- Shader playback frame.uniform vec2 iResolution
-- Viewport resolution (in pixels).uniform vec4 iDate
-- (Year, month, day, time in seconds).uniform vec4 iMouse
-- Mouse pixel coords. xy: current (if MLB down), zw: click.uniform sampler2D iChannel^n
-- The textures input channel you've passed; numbered in the same order as the textures passed as prop in your react component.uniform vec3 iChannelResolution[n]
-- An array containing the texture channel resolution (in pixels).uniform vec4 iDeviceOrientation
-- Raw data from device orientation where respectively x: Alpha, y: Beta, z: Gamma and w: window.orientation.#define DPR 1.0
-- The canvas device pixel ratio (1.0 by default or props.devicePixelRatio).<Shader
fs={fs}
uniforms={{
// A single float
uScrollY: {type:'1f', value: scrollY},
// Five floats in an array
uTestArrayFloats: {type:'1fv', value:[.2,.4,.5,.5,.6]},
// Two vec2s in an array
uTestArrayVecs2: {type:'2fv', value:[.2,.4,.5,.5]},
// A single mat2
uTestMatrix: {type:'Matrix2fv', value:[0,1,2,3]},
}}
/>
You can pass an array of texture objects. A callback is available and called once all the textures are done loading. Each texture gets a uniform name iChannel{n}
following the same order that in the prop passed to the react component, you can then directly use iChannel{n}
in your shader.
import { Shader, LinearFilter, RepeatWrapping } from 'react-shaders'
return (
<Shader fs={fs} textures={[{ url:'./my-texture.png' }]} />
)
By default all of your textures are being squared if they aren't, then the default Texture Filtering and Wrapping are being applied to them, using react-shaders
you can apply your own filters. react-shaders
contains all the WebGL texture filtering constants and texture wrapping constants. So you can easily import them in your code and make sure to pass the right one to your texture options.
Available imports: ClampToEdgeWrapping
, LinearFilter
, LinearMipMapLinearFilter
, LinearMipMapNearestFilter
, MirroredRepeatWrapping
, NearestFilter
, NearestMipMapLinearFilter
, NearestMipMapNearestFilter
, RepeatWrapping
.
You can use these with the wrapS
, wrapT
, minFilter
, magFilter
options of your texture objects.
This library is possible thanks to the work of Morgan Villedieu, original creator of shadertoy-react
, Charlie Hoey, contributor to shadertoy-react
, Iñigo Quilez & Pol Jeremias, creators of Shadertoy and by extension the Shadertoy GL syntax, and the Rysana team, who wrote this library in Typescript after forking shadertoy-react
and maintain it.
vs?: string
devicePixelRatio?: number
fs: string
GLSL code for the fragment shader, this is the only required prop.
textures?: TexturePropsType[]
Textures to be passed to the shader - need to be squared or will be automatically resized.
uniforms?: Uniforms
Custom uniforms to be passed to the shader. See the section below.
clearColor?: Vector4
Color used when clearing the canvas. See the section below.
precision?: "highp" | "lowp" | "mediump"
GLSL precision qualifier. Defaults to highp
. Balance between performance and quality.
style?: CSSStyleDeclaration
Custom inline style for the canvas element.
contextAttributes?: Record<string, unknown>
Customize WebGL context attributes.
lerp?: number
Lerp value for iMouse
built-in uniform. Must be between 0 and 1.
onDoneLoadingTextures?: () => void
Useful if you want to do something like e.g. hide the canvas until textures are done loading.
onError?: (error: string) => void
Defaults to console.error
.
onWarning?: (warning: string) => void
Defaults to console.warn
.