Skip to content

Shader

Applies shader transformations to its children using a WGSL shader. For more information on using shaders in Smelter, please visit Shaders documentation.

Reference

ShaderExample.tsx
import { Image, Shader } from "@swmansion/smelter";
import Smelter from "@swmansion/smelter-node";
// Adds red border to input texture
const RED_BORDER_SHADER = `
struct VertexInput {
@location(0) position: vec3<f32>,
43 collapsed lines
@location(1) tex_coords: vec2<f32>,
}
struct VertexOutput {
@builtin(position) position: vec4<f32>,
@location(0) tex_coords: vec2<f32>,
}
@group(0) @binding(0) var textures: binding_array<texture_2d<f32>, 16>;
@group(2) @binding(0) var sampler_: sampler;
struct BaseShaderParameters {
plane_id: i32,
time: f32,
output_resolution: vec2<u32>,
texture_count: u32,
}
var<push_constant> base_params: BaseShaderParameters;
@vertex
fn vs_main(input: VertexInput) -> VertexOutput {
var output: VertexOutput;
output.position = vec4(input.position.x, input.position.y, input.position.z, 1.0);
output.tex_coords = input.tex_coords;
return output;
}
@fragment
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
let sample = textureSample(textures[0], sampler_, input.tex_coords);
let border_size = 50.0;
// input.position is interpolated into ([0, output_width], [0, output_height], ..) range
// by wgpu between vertex shader output and fragment shader input
if (input.position.x > border_size && input.position.x < f32(base_params.output_resolution.x) - border_size) {
if (input.position.y > border_size && input.position.y < f32(base_params.output_resolution.y) - border_size) {
return sample;
}
}
return vec4(1.0, 0.0, 0.0, 1.0);
}
`;
function ExampleApp() {
return (
<Shader
shaderId="example_shader"
resolution={{ width: 1920, height: 1080 }}>
<Image source="https://mywebsite.com/example.svg" />
</Shader>
);
}
async function run() {
const smelter = new Smelter();
await smelter.init();
await smelter.registerShader("example_shader", {
source: RED_BORDER_SHADER,
});
await smelter.registerOutput("output", <ExampleApp />, {
18 collapsed lines
type: "mp4",
serverPath: "./output.mp4",
video: {
encoder: {
type: "ffmpeg_h264",
preset: "ultrafast",
},
resolution: {
width: 1920,
height: 1080,
},
},
audio: {
encoder: {
type: "aac",
channels: "stereo",
},
},
});
await smelter.start();
}
void run();
Type definitions

type ShaderProps = {
id?: string;
children?: ReactElement[];
shaderId: string;
shaderParam?: ShaderParam;
resolution: {
width: number;
height: number;
};
}

Props

shaderId

ID of a shader. It identifies a shader registered using a Smelter.registerShader method.

  • Type: string

children

A single child component to be transformed.

  • Type: ReactNode

id

ID of a component.

  • Type: string
  • Default value: Value produced by useId hook

shaderParam

Object that will be serialized into a struct and passed to the shader as @group(1) @binding(0) var<uniform>. ShaderParam object must match the structure defined in a shader source code.


resolution

Resolution of the texture where shader will be executed.

  • Type: { width: number; height: number;}

ShaderParam

type ShaderParam =
| { type: "f32"; value: f32; }
| { type: "u32"; value: u32; }
| { type: "i32"; value: i32; }
| { type: "list"; value: ShaderParam[]; }
| {
type: "struct";
value: ShaderParamStructField[];
}

ShaderParamStructField

type ShaderParamStructField =
| { field_name: string; type: "f32"; value: f32; }
| { field_name: string; type: "u32"; value: u32; }
| { field_name: string; type: "i32"; value: i32; }
| {
field_name: string;
type: "list";
value: ShaderParam[];
}
| {
field_name: string;
type: "struct";
value: ShaderParamStructField[];
}