Créez des composants Svelte rendues par GPU avec des shaders de fragments WebGL et WebGPU.
Prend en charge Svelte 4 et Svelte 5.
En bref, un shader de fragment peut être écrit comme un programme qui prend les coordonnées d'un pixel à l'écran et renvoie la couleur que ce pixel devrait avoir. Ce programme peut être exécuté sur le GPU, garantissant un parallélisme et une vitesse massifs.
Pour en savoir plus sur la façon d'écrire des shaders de fragments, consultez le livre des shaders.
Ce qui suit est une collection d'exemples tous fabriqués à l'aide de Svader. La version en direct de tous ces éléments peut être prévisualisée sur svader.vercel.app, et le code source peut être trouvé dans le src/routes/ Directory.
# npm
npm i -D svader
# pnpm
pnpm i -D svader
# Bun
bun i -D svader
# Yarn
yarn add -D svaderPour utiliser un composant Shader Fragment, vous devez d'abord décider d'utiliser WebGL ou WebGPU. Si vous n'êtes pas sûr de savoir quoi utiliser, consultez la section WebGL vs WebGPU.
Ce qui suit est un exemple minimal de composant de shader de fragment WebGL.
Voir dans REP
< script >
import { WebGlShader } from " svader " ;
const shaderCode = ` #version 300 es
precision mediump float;
out vec4 fragColor;
uniform vec2 u_resolution;
uniform vec2 u_offset;
void main() {
vec2 pos = gl_FragCoord.xy + u_offset;
vec2 st = pos / u_resolution;
fragColor = vec4(st, 0.0, 1.0);
}
` ;
</ script >
< WebGlShader
width = " 500px "
height = " 500px "
code ={ shaderCode }
parameters ={[
{
name: " u_resolution " ,
value: " resolution " ,
},
{
name: " u_offset " ,
value: " offset " ,
},
]}
>
< div class = " fallback " >WebGL not supported in this environment.</ div >
</ WebGlShader >Cela produit la sortie suivante:
Ici, la variable shaderCode est une chaîne contenant le code de shader GLES. Pour plus de simplicité, celle-ci est stockée sous forme de chaîne, mais elle serait généralement stockée dans un fichier myShader.frag distinct. Lors du chargement du shader à partir d'un fichier, il peut être utile de savoir que la propriété code accepte à la fois une string et une Promise<string> .
Ce que fait ce code est:
u_offset donné aux coordonnées 2D du pixel donné par gl_FragCoord.xy .u_resolution pour normaliser les coordonnées entre 0 et 1.x devient le canal rouge et que la coordonnée y devient le canal vert. Le canal bleu est toujours réglé sur 0 et le canal alpha (opacité) est toujours défini sur 1 (entièrement opaque). Dans GLES, les uniformes sont des entrées de la fonction, qui sont les mêmes pour chaque pixel à l'écran. Ceux-ci doivent être transmis via la propriété parameters du composant <WebGlShader> . Dans ce cas, nous devons passer en deux uniformes: u_resolution et u_offset . Étant donné que ces paramètres spécifiques sont très couramment utilisés, ils sont spécialement mis en œuvre dans SVADER de sorte que la propriété value de chaque paramètre peut simplement être définie respectivement sur "resolution" et "offset" .
Enfin, le composant <WebGlShader> accepte un emplacement de secours, qui est rendu lorsque le navigateur ne peut pas rendre le shader.
La propriété parameters est un tableau d'objets avec les propriétés suivantes:
name : le nom du paramètre uniforme, par exemple "my_uniform" . Cela doit correspondre au nom du paramètre dans le code du shader.
type : Le type du paramètre uniforme tel qu'il est écrit dans le code du shader, par exemple "float" . Si la propriété value est une valeur intégrée, telle que "resolution" , le type sera déterminé automatiquement et ne doit pas être défini.
value : la valeur du paramètre uniforme ou une chaîne spécifiant une valeur intégrée. Si ce n'est pas une valeur intégrée, le type de cette propriété doit correspondre à la propriété type , telle que:
float , int , uint est un number ,vecN , ivecN , uvecN est un number[] avec une longueur de N , par exemple vec2 -> [1.2, 3.4] .matN est un number[] avec une longueur de N * N , par exemple mat2 -> [1, 2, 3, 4] . Certains types d'uniformes sont utilisés très souvent. Ceux-ci sont mis en œuvre dans Svader lui-même et appelés valeurs intégrées . Pour les utiliser, la propriété value de l'objet Paramètre doit être définie sur une chaîne correspondant à l'une des éléments suivants:
"resolution" : un vec2 de la largeur et de la hauteur de la toile dans les pixels de l'appareil physique.
"scale" : un float du rapport entre les pixels CSS et les pixels de l'appareil physique, c'est-à-dire le niveau de zoom. Par exemple, si le navigateur a été zoomé à 150%, le paramètre scale sera 1.5 .
"time" : un float de l'heure actuelle en secondes. Remarque: le passage de ce paramètre au shader le fera repenser chaque trame.
"offset" : un vec2 à ajouter au gl_FragCoord.xy du shader de fragment. Parfois, la taille de la toile est limitée par le matériel. Pour compenser cela, Svader crée une toile virtuelle avec une découpe plus petite se déplaçant pour couvrir l'écran. Le paramètre "resolution" est automatiquement ajusté pour correspondre à la taille de cette toile virtuelle, mais pour des raisons techniques, le gl_FragCoord.xy ne peut pas être ajusté de l'extérieur. Par conséquent, le paramètre "offset" est fourni pour être ajouté manuellement à ces coordonnées.
Ce qui suit est un exemple minimal d'un composant de shader de fragment WebGPU.
Voir dans REP
< script >
import { WebGpuShader } from " svader " ;
const shaderCode = `
@group(0) @binding(0) var<uniform> resolution: vec2f;
@group(0) @binding(1) var<uniform> offset: vec2f;
@fragment
fn main(@builtin(position) raw_pos: vec4f) -> @location(0) vec4f {
let pos = raw_pos.xy + offset;
let st = pos / resolution;
return vec4f(st, 0.0, 1.0);
}
` ;
</ script >
< WebGpuShader
width = " 500px "
height = " 500px "
code ={ shaderCode }
parameters ={[
{
label: " Resolution " ,
binding: 0 ,
value: " resolution " ,
},
{
label: " Offset " ,
binding: 1 ,
value: " offset " ,
},
]}
>
< div class = " fallback " >WebGPU not supported in this environment.</ div >
</ WebGpuShader >Cela produit la sortie suivante:
Ici, la variable shaderCode est une chaîne contenant le code WGSL Shader. Pour plus de simplicité, celle-ci est stockée en tant que chaîne, mais elle serait généralement stockée dans un fichier distinct myShader.wgsl . Lors du chargement du shader à partir d'un fichier, il peut être utile de savoir que la propriété code accepte à la fois une string et une Promise<string> .
Ce que fait ce code est:
offset donné aux coordonnées 2D du pixel donné par raw_pos.xy .resolution pour normaliser les coordonnées entre 0 et 1.x devient le canal rouge et que la coordonnée y devient le canal vert. Le canal bleu est toujours réglé sur 0 et le canal alpha (opacité) est toujours défini sur 1 (entièrement opaque). Dans WGSL, ces var<uniform> sont le principal moyen de passer par des paramètres au shader. Ceux-ci doivent être transmis via la propriété parameters du composant <WebGpuShader> . Dans ce cas, nous devons passer en deux uniformes: resolution et offset . Étant donné que ces paramètres spécifiques sont très couramment utilisés, ils sont spécialement mis en œuvre dans SVADER de sorte que la propriété value de chaque paramètre peut simplement être définie respectivement sur "resolution" et "offset" .
Enfin, le composant <WebGpuShader> accepte un emplacement de secours, qui est rendu lorsque le navigateur ne peut pas rendre le shader.
La propriété parameters est un tableau d'objets avec les propriétés suivantes:
label : le nom du paramètre à utiliser pour le débogage. Cela ne doit pas correspondre au nom du paramètre dans le code de shader.
binding : un entier utilisé pour faire correspondre le paramètre à la variable du code de shader. Cela doit correspondre à la propriété binding du paramètre dans le code de shader, par exemple pour la déclaration variable
@ group ( 0 ) @ binding ( 42 ) var < uniform > my_variable : f32 ; La propriété binding doit être 42 .
value : la valeur du paramètre ou une chaîne spécifiant une valeur intégrée. Si ce n'est pas une valeur intégrée, ce paramètre doit être un ArrayBuffer / ArrayBufferView . Par exemple, pour passer un nombre à un paramètre f32 , il peut être construit comme new Float32Array([myNumberValue]) .
storage : [Facultatif - par défaut est false ] si le paramètre est une variable de stockage plutôt qu'une variable uniforme. Cela doit correspondre à la déclaration dans le code Shader, par exemple pour la déclaration variable
@ group ( 0 ) @ binding ( 0 ) var < uniform > my_variable : f32 ; la propriété storage doit être false ou omise, et pour
@ group ( 0 ) @ binding ( 0 ) var < storage , read > my_variable : f32 ; ça devrait être true . Notez que Svader ne prend actuellement en charge var<storage, read> et non var<storage, read_write> .
Certains types d'entrées sont utilisés très souvent. Ceux-ci sont mis en œuvre dans Svader lui-même et appelés valeurs intégrées . Pour les utiliser, la propriété value de l'objet Paramètre doit être définie sur une chaîne correspondant à l'une des éléments suivants:
"resolution" : un vec2f de la largeur et de la hauteur de la toile dans les pixels de l'appareil physique.
"scale" : un f32 du rapport entre les pixels CSS et les pixels de l'appareil physique, c'est-à-dire le niveau de zoom. Par exemple, si le navigateur a été zoomé à 150%, le paramètre scale sera 1.5 .
"time" : un f32 de l'heure actuelle en secondes. Remarque: le passage de ce paramètre au shader le fera repenser chaque trame.
"offset" : un vec2f à ajouter au @builtin(position) du shader de fragment. Parfois, la taille de la toile est limitée par le matériel. Pour compenser cela, Svader crée une toile virtuelle avec une découpe plus petite se déplaçant pour couvrir l'écran. Le paramètre "resolution" est automatiquement ajusté pour correspondre à la taille de cette toile virtuelle, mais pour des raisons techniques, le @builtin(position) ne peut pas être ajusté de l'extérieur. Par conséquent, le paramètre "offset" est fourni pour être ajouté manuellement à ces coordonnées.
Pour les applications pratiques, utilisez par défaut WebGL.
WebGL et WebGPU rendent tous deux des API qui permettent aux applications Web de rendre des graphiques accélérés par le GPU.
WebGL est l'ancien des deux et est soutenu par tous les navigateurs modernes.
WebGPU est toujours au stade expérimental et n'est pris en charge que dans quelques navigateurs. Cependant, il prend en charge certaines fonctionnalités que WebGL ne fait pas. Par exemple, au cours de la rédaction, WebGL dans Google Chrome ne prend en charge que 8 toiles actives dans le document à la fois, tandis que WebGPU prend en charge un numéro pratiquement illimité.
Svader est autorisé sous la licence du MIT.