Shading Language
Skia provides a shading language. You can play with it here. The syntax is very similar to GLSL. If you're already familiar with GLSL, or are looking to convert a GLSL shader to SKSL, you can view a list of their differences here.
The first step is to create a shader and compile it using RuntimeEffect.Make
.
tsx
import {Skia } from "@shopify/react-native-skia";constsource =Skia .RuntimeEffect .Make (`vec4 main(vec2 pos) {// The canvas is 256x256vec2 canvas = vec2(256);// normalized x,y values go from 0 to 1vec2 normalized = pos/canvas;return vec4(normalized.x, normalized.y, 0.5, 1);}`);if (!source ) {throw newError ("Couldn't compile the shader")}
tsx
import {Skia } from "@shopify/react-native-skia";constsource =Skia .RuntimeEffect .Make (`vec4 main(vec2 pos) {// The canvas is 256x256vec2 canvas = vec2(256);// normalized x,y values go from 0 to 1vec2 normalized = pos/canvas;return vec4(normalized.x, normalized.y, 0.5, 1);}`);if (!source ) {throw newError ("Couldn't compile the shader")}
Shader
Creates a shader from source. Shaders can be nested with one another.
Name | Type | Description |
---|---|---|
source | RuntimeEffect | Compiled shaders |
uniforms | { [name: string]: number | Vector | Vector[] | number[] | number[][] } | uniform values |
children | Shader | Shaders to be used as uniform |
Simple Shader
tsx
import {Skia ,Canvas ,Shader ,Fill } from "@shopify/react-native-skia";constsource =Skia .RuntimeEffect .Make (`vec4 main(vec2 pos) {// normalized x,y values go from 0 to 1, the canvas is 256x256vec2 normalized = pos/vec2(256);return vec4(normalized.x, normalized.y, 0.5, 1);}`)!;constSimpleShader = () => {return (<Canvas style ={{width : 256,height : 256 }}><Fill ><Shader source ={source } /></Fill ></Canvas >);};
tsx
import {Skia ,Canvas ,Shader ,Fill } from "@shopify/react-native-skia";constsource =Skia .RuntimeEffect .Make (`vec4 main(vec2 pos) {// normalized x,y values go from 0 to 1, the canvas is 256x256vec2 normalized = pos/vec2(256);return vec4(normalized.x, normalized.y, 0.5, 1);}`)!;constSimpleShader = () => {return (<Canvas style ={{width : 256,height : 256 }}><Fill ><Shader source ={source } /></Fill ></Canvas >);};
Using Uniforms
Uniforms are variables used to parametrize shaders.
The following uniform types are supported: float
, float2
, float3
, float4
, float2x2
, float3x3
, float4x4
, int
, int2
, int3
and, int4
.
The types can also be used as arrays, e.g. uniform float3 colors[12]
.
tsx
import {Canvas ,Skia ,Shader ,Fill ,vec } from "@shopify/react-native-skia";constsource =Skia .RuntimeEffect .Make (`uniform vec2 c;uniform float r;uniform float blue;vec4 main(vec2 pos) {vec2 normalized = pos/vec2(2 * r);return distance(pos, c) > r ? vec4(1) : vec4(normalized, blue, 1);}`)!;constUniformShader = () => {constr = 128;constc =vec (2 *r ,r );constblue = 1.0;return (<Canvas style ={{width : 256,height : 256 }}><Fill ><Shader source ={source }uniforms ={{c ,r ,blue }} /></Fill ></Canvas >);};
tsx
import {Canvas ,Skia ,Shader ,Fill ,vec } from "@shopify/react-native-skia";constsource =Skia .RuntimeEffect .Make (`uniform vec2 c;uniform float r;uniform float blue;vec4 main(vec2 pos) {vec2 normalized = pos/vec2(2 * r);return distance(pos, c) > r ? vec4(1) : vec4(normalized, blue, 1);}`)!;constUniformShader = () => {constr = 128;constc =vec (2 *r ,r );constblue = 1.0;return (<Canvas style ={{width : 256,height : 256 }}><Fill ><Shader source ={source }uniforms ={{c ,r ,blue }} /></Fill ></Canvas >);};
Nested Shaders
tsx
import {Canvas ,Skia ,ImageShader ,Shader ,Fill ,useImage } from "@shopify/react-native-skia";constsource =Skia .RuntimeEffect .Make (`uniform shader image;half4 main(float2 xy) {xy.x += sin(xy.y / 3) * 4;return image.eval(xy).rbga;}`)!;constNestedShader = () => {constimage =useImage (require ("./assets/oslo.jpg"));if (!image ) {return null;}return (<Canvas style ={{width : 256,height : 256 }}><Fill ><Shader source ={source }><ImageShader image ={image }fit ="cover"rect ={{x : 0,y : 0,width : 256,height : 256 }}/></Shader ></Fill ></Canvas >);};
tsx
import {Canvas ,Skia ,ImageShader ,Shader ,Fill ,useImage } from "@shopify/react-native-skia";constsource =Skia .RuntimeEffect .Make (`uniform shader image;half4 main(float2 xy) {xy.x += sin(xy.y / 3) * 4;return image.eval(xy).rbga;}`)!;constNestedShader = () => {constimage =useImage (require ("./assets/oslo.jpg"));if (!image ) {return null;}return (<Canvas style ={{width : 256,height : 256 }}><Fill ><Shader source ={source }><ImageShader image ={image }fit ="cover"rect ={{x : 0,y : 0,width : 256,height : 256 }}/></Shader ></Fill ></Canvas >);};