跳到主要内容

着色语言

Skia 提供了一种着色语言。你可以在这里进行尝试。它的语法与 GLSL 非常相似。如果你已经熟悉 GLSL,或者想将 GLSL 着色器转换为 SKSL,你可以在这里查看它们的差异列表。

第一步是创建着色器并使用 RuntimeEffect.Make 编译它。

tsx
import {Skia} from "@shopify/react-native-skia";
 
const source = Skia.RuntimeEffect.Make(`
vec4 main(vec2 pos) {
// The canvas is 256x256
vec2 canvas = vec2(256);
// normalized x,y values go from 0 to 1
vec2 normalized = pos/canvas;
return vec4(normalized.x, normalized.y, 0.5, 1);
}`);
 
if (!source) {
throw new Error("Couldn't compile the shader")
}
tsx
import {Skia} from "@shopify/react-native-skia";
 
const source = Skia.RuntimeEffect.Make(`
vec4 main(vec2 pos) {
// The canvas is 256x256
vec2 canvas = vec2(256);
// normalized x,y values go from 0 to 1
vec2 normalized = pos/canvas;
return vec4(normalized.x, normalized.y, 0.5, 1);
}`);
 
if (!source) {
throw new Error("Couldn't compile the shader")
}

着色器

从源代码创建着色器。着色器可以相互嵌套。

名称类型描述
sourceRuntimeEffect已编译的着色器
uniforms{ [name: string]: number|矢量|矢量[]|数字[]|数字[][] }uniform 值
children着色器用作 uniform 的着色器

简单着色器

tsx
import {Skia, Canvas, Shader, Fill} from "@shopify/react-native-skia";
 
const source = Skia.RuntimeEffect.Make(`
vec4 main(vec2 pos) {
// normalized x,y values go from 0 to 1, the canvas is 256x256
vec2 normalized = pos/vec2(256);
return vec4(normalized.x, normalized.y, 0.5, 1);
}`)!;
 
const SimpleShader = () => {
return (
<Canvas style={{ width: 256, height: 256 }}>
<Fill>
<Shader source={source} />
</Fill>
</Canvas>
);
};
tsx
import {Skia, Canvas, Shader, Fill} from "@shopify/react-native-skia";
 
const source = Skia.RuntimeEffect.Make(`
vec4 main(vec2 pos) {
// normalized x,y values go from 0 to 1, the canvas is 256x256
vec2 normalized = pos/vec2(256);
return vec4(normalized.x, normalized.y, 0.5, 1);
}`)!;
 
const SimpleShader = () => {
return (
<Canvas style={{ width: 256, height: 256 }}>
<Fill>
<Shader source={source} />
</Fill>
</Canvas>
);
};

Simple Shader

使用 Uniforms

Uniforms 是用于参数化着色器的变量。支持以下 uniform 类型:floatfloat2float3float4float2x2float3x3float4x4intint2int3int4。这些类型也可以用作数组,例如 uniform float3 colors[12]

tsx
import {Canvas, Skia, Shader, Fill, vec} from "@shopify/react-native-skia";
 
const source = 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);
}`)!;
 
const UniformShader = () => {
const r = 128;
const c = vec(2 * r, r);
const blue = 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";
 
const source = 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);
}`)!;
 
const UniformShader = () => {
const r = 128;
const c = vec(2 * r, r);
const blue = 1.0;
return (
<Canvas style={{ width: 256, height: 256 }}>
<Fill>
<Shader source={source} uniforms={{ c, r, blue }} />
</Fill>
</Canvas>
);
};

Simple Shader

嵌套着色器

tsx
import {Canvas, Skia, ImageShader, Shader, Fill, useImage} from "@shopify/react-native-skia";
 
const source = Skia.RuntimeEffect.Make(`
uniform shader image;
 
half4 main(float2 xy) {
xy.x += sin(xy.y / 3) * 4;
return image.eval(xy).rbga;
}`)!;
 
const NestedShader = () => {
const image = 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";
 
const source = Skia.RuntimeEffect.Make(`
uniform shader image;
 
half4 main(float2 xy) {
xy.x += sin(xy.y / 3) * 4;
return image.eval(xy).rbga;
}`)!;
 
const NestedShader = () => {
const image = 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>
);
};

Simple Shader