Crie componentes esbeltos renderizados por GPU com shaders de fragmentos WebGL e WebGPU.
Suporta SVELTE 4 e SVELE 5.
Em suma, um shader de fragmento pode ser escrito como um programa que pega as coordenadas de um pixel na tela e retorna a cor que esse pixel deve ter. Este programa pode ser executado na GPU, garantindo paralelismo e velocidade maciços.
Para saber mais sobre como escrever shaders de fragmentos, confira o livro dos shaders.
A seguir, é apresentada uma coleção de exemplos feitos usando Svader. A versão ao vivo de tudo isso pode ser visualizada no svader.vercel.app, e o código -fonte pode ser encontrado no diretório src/routes/ .
# npm
npm i -D svader
# pnpm
pnpm i -D svader
# Bun
bun i -D svader
# Yarn
yarn add -D svaderPara usar um componente de shader do fragmento, você primeiro precisa decidir se deve usar o WebGL ou o WebGPU. Se você não tiver certeza sobre o que usar, consulte a seção WebGL vs. WebGPU.
A seguir, é um exemplo mínimo de um componente do shader do Fragment WebGL.
Vista em repl
< 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 >Isso produz a seguinte saída:
Aqui, a variável shaderCode é uma string que contém o código do shader gles. Por simplicidade, isso é armazenado como uma string, mas normalmente seria armazenado em um arquivo myShader.frag separado. Ao carregar o shader de um arquivo, pode ser útil saber que a propriedade code aceita uma string e uma Promise<string> .
O que este código faz é:
u_offset dado às coordenadas 2D do pixel fornecido por gl_FragCoord.xy .u_resolution para normalizar as coordenadas entre 0 e 1.x se torne o canal vermelho e a coordenada y se torna o canal verde. O canal azul é sempre definido como 0 e o canal alfa (opacidade) é sempre definido como 1 (totalmente opaco). Em GLES, os uniformes são insumos para a função, que são iguais para cada pixel na tela. Eles precisam ser transmitidos através da propriedade parameters do componente <WebGlShader> . Nesse caso, precisamos passar em dois uniformes: u_resolution e u_offset . Como esses parâmetros específicos são muito usados, eles são especialmente implementados no SVADER, de modo que a propriedade value de cada parâmetro possa ser simplesmente definida como "resolution" e "offset" respectivamente.
Por fim, o componente <WebGlShader> aceita um slot de fallback, que é renderizado quando o navegador não pode renderizar o shader.
A propriedade parameters é uma variedade de objetos com as seguintes propriedades:
name : O nome do parâmetro uniforme, por exemplo "my_uniform" . Isso deve corresponder ao nome do parâmetro no código do shader.
type : o tipo do parâmetro uniforme, como está escrito no código do shader, por exemplo, "float" . Se a propriedade value for um valor interno, como "resolution" , o type será determinado automaticamente e não deverá ser definido.
value : o valor do parâmetro uniforme ou uma string especificando um valor interno. Se não for um valor interno, o tipo dessa propriedade deve corresponder à propriedade type , de modo que:
float , int , uint é um number ,vecN , ivecN , uvecN é um number[] com um comprimento de N , por exemplo, vec2 -> [1.2, 3.4] .matN é um number[] com um comprimento de N * N , por exemplo, mat2 -> [1, 2, 3, 4] . Alguns tipos de uniformes são usados com muita frequência. Eles são implementados no próprio Svader e chamados de valores internos . Para usá -los, a propriedade value do objeto Parâmetro deve ser definida como uma string que corresponda a um dos seguintes:
"resolution" : um vec2 da largura e altura da tela em pixels de dispositivo físico.
"scale" : uma float da proporção entre os pixels CSS e os pixels de dispositivo físico, ou seja, o nível de zoom. Por exemplo, se o navegador tiver sido ampliado para 150%, o parâmetro scale será 1.5 .
"time" : um float do horário atual em segundos. NOTA: Passar este parâmetro para o shader fará com que ele reenda todos os quadros.
"offset" : um vec2 a ser adicionado ao gl_FragCoord.xy do shader do fragmento. Às vezes, o tamanho da tela é limitado pelo hardware. Para compensar isso, o Svader cria uma tela virtual com um recorte menor mudando para cobrir a tela. O parâmetro "resolution" é ajustado automaticamente para corresponder ao tamanho dessa tela virtual, mas por razões técnicas, o gl_FragCoord.xy não pode ser ajustado de fora. Portanto, o parâmetro "offset" é fornecido para ser adicionado manualmente a essas coordenadas.
A seguir, é um exemplo mínimo de um componente de shader do fragmento WebGPU.
Vista em repl
< 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 >Isso produz a seguinte saída:
Aqui, a variável shaderCode é uma string que contém o código do shader WGSL. Por simplicidade, isso é armazenado como uma string, mas normalmente seria armazenado em um arquivo myShader.wgsl separado. Ao carregar o shader de um arquivo, pode ser útil saber que a propriedade code aceita uma string e uma Promise<string> .
O que este código faz é:
offset fornecida às coordenadas 2D do pixel dado por raw_pos.xy .resolution para normalizar as coordenadas entre 0 e 1.x se torne o canal vermelho e a coordenada y se torna o canal verde. O canal azul é sempre definido como 0 e o canal alfa (opacidade) é sempre definido como 1 (totalmente opaco). No WGSL, esses var<uniform> são a principal maneira de passar nos parâmetros para o shader. Eles precisam ser transmitidos através da propriedade parameters do componente <WebGpuShader> . Nesse caso, precisamos passar em dois uniformes: resolution e offset . Como esses parâmetros específicos são muito usados, eles são especialmente implementados no SVADER, de modo que a propriedade value de cada parâmetro possa ser simplesmente definida como "resolution" e "offset" respectivamente.
Por fim, o componente <WebGpuShader> aceita um slot de fallback, que é renderizado quando o navegador não pode renderizar o shader.
A propriedade parameters é uma variedade de objetos com as seguintes propriedades:
label : o nome do parâmetro a ser usado para depuração. Isso não precisa corresponder ao nome do parâmetro no código do shader.
binding : um número inteiro usado para corresponder ao parâmetro com a variável no código do shader. Isso deve corresponder à propriedade binding do parâmetro no código do shader, por exemplo, para a declaração variável
@ group ( 0 ) @ binding ( 42 ) var < uniform > my_variable : f32 ; A propriedade binding deve ser 42 .
value : o valor do parâmetro ou uma string especificando um valor interno. Se não for um valor interno, esse parâmetro deve ser um ArrayBuffer / ArrayBufferView . Por exemplo, para passar em um número para um parâmetro f32 , ele pode ser construído como new Float32Array([myNumberValue]) .
storage : [Opcional - Padrões para false ] Se o parâmetro é uma variável de armazenamento em vez de uma variável uniforme. Isso deve corresponder à declaração no código do shader, por exemplo, para a declaração variável
@ group ( 0 ) @ binding ( 0 ) var < uniform > my_variable : f32 ; A propriedade storage deve ser false ou omitida e para
@ group ( 0 ) @ binding ( 0 ) var < storage , read > my_variable : f32 ; deve ser true . Observe que atualmente o Svader suporta apenas var<storage, read> e não var<storage, read_write> .
Alguns tipos de insumos são usados com muita frequência. Eles são implementados no próprio Svader e chamados de valores internos . Para usá -los, a propriedade value do objeto Parâmetro deve ser definida como uma string que corresponda a um dos seguintes:
"resolution" : um vec2f da largura e altura da tela em pixels de dispositivo físico.
"scale" : um f32 da proporção entre pixels CSS e pixels de dispositivo físico, ou seja, o nível de zoom. Por exemplo, se o navegador tiver sido ampliado para 150%, o parâmetro scale será 1.5 .
"time" : um f32 do horário atual em segundos. NOTA: Passar este parâmetro para o shader fará com que ele reenda todos os quadros.
"offset" : um vec2f a ser adicionado ao @builtin(position) do shader do fragmento. Às vezes, o tamanho da tela é limitado pelo hardware. Para compensar isso, o Svader cria uma tela virtual com um recorte menor mudando para cobrir a tela. O parâmetro "resolution" é ajustado automaticamente para corresponder ao tamanho dessa tela virtual, mas por razões técnicas, o @builtin(position) não pode ser ajustado de fora. Portanto, o parâmetro "offset" é fornecido para ser adicionado manualmente a essas coordenadas.
Para aplicações práticas, padrão use o WebGL.
WebGL e WebGPU estão renderizando APIs que permitem que os aplicativos da Web renderizem gráficos acelerados por GPU.
O WebGL é o mais antigo dos dois e é apoiado por todos os navegadores modernos.
O WebGPU ainda está no estágio experimental e só é suportado em alguns navegadores. No entanto, ele suporta certos recursos que o WebGL não. Por exemplo, até a redação, o WebGL no Google Chrome suporta apenas 8 telas ativas no documento de uma só vez, enquanto o WebGPU suporta um número praticamente ilimitado.
O Svader está licenciado sob a licença do MIT.