Shaders
Runtime SkSL shaders and uniforms.
1import { Canvas, Fill, Shader } from 'react-native-tgfx'
2const rings = `uniform float2 uSize;
3uniform float uRings;
4half4 main(float2 pos) {
5 float2 uv = pos / uSize;
6 float k = 0.8 + 0.2 * cos(length(uv - 0.5) * uRings);
7 return half4(half3(uv.x, uv.y * 0.5, 0.9) * k, 1.0);
8}`
9
10<Canvas style={{ width: 402, height: 600 }}>
11 <Fill>
12 <Shader source={rings} uniforms={{
13 uRings: ,
14 uSize: [402, 600],
15 }} />
16 </Fill>
17</Canvas>
9:41
Shader runs tgfx's SkSL subset
(ShaderProps). main gets local coordinates and
returns premultiplied half4.
import { Canvas, Fill, Shader } from 'react-native-tgfx'
const source = `
uniform float2 uSize;
half4 main(float2 pos) {
float2 uv = pos / uSize;
return half4(uv.x, uv.y, 0.6, 1.0);
}
`
<Canvas style={{ width: 300, height: 140 }}>
<Fill>
<Shader source={source} uniforms={{ uSize: [300, 140] }} />
</Fill>
</Canvas>Declarations must come before main().
Animated uniforms
Uniforms accept a SharedValue. useClock counts
seconds.
const t = useClock()
<Fill>
<Shader source={source} uniforms={{ uTime: t, uSize: [width, height] }} />
</Fill>Shader inputs
One shader child per uniform shader, in order.
const source = `
uniform shader img;
uniform float uShift;
half4 main(float2 pos) {
half4 base = img.eval(pos);
half4 red = img.eval(pos + float2(uShift, 0.0));
half4 blue = sample(img, pos - float2(uShift, 0.0));
return half4(red.r, base.g, blue.b, base.a);
}
`
<Shader source={source} uniforms={{ uShift: 4 }}>
<ImageShader image={image} fit="cover" rect={{ x: 0, y: 0, width: 300, height: 200 }} />
</Shader>Inputs can be any shader:
<Shader source={banded}>
<LinearGradient start={{ x: 0, y: 0 }} end={{ x: 300, y: 0 }} colors={['#2b6cff', '#ff3b6b']} />
</Shader>A count mismatch throws:
[tgfx] shader: the source declares 1 'uniform shader' (img) but 0 shader children
were given - pass one shader child per declaration, in order