Cree componentes SVELTE renderizados con GPU con WebGL y WebGPU Fragment Shaders.
Apoya a Svelte 4 y Svelte 5.
En resumen, un sombreador de fragmentos se puede escribir como un programa que toma las coordenadas de un píxel en la pantalla y devuelve el color que este píxel debería tener. Este programa se puede ejecutar en la GPU, asegurando un paralelismo masivo y la velocidad.
Para obtener más información sobre cómo escribir sombreadores de fragmentos, consulte el Libro de los Shaders.
La siguiente es una colección de ejemplos todos hechos con Svader. La versión en vivo de todos estos se puede ver previamente en svader.vercel.app, y el código fuente se puede encontrar en el directorio src/routes/ .
# npm
npm i -D svader
# pnpm
pnpm i -D svader
# Bun
bun i -D svader
# Yarn
yarn add -D svaderPara usar un componente de sombreador de fragmentos, primero debe decidir si usar WebGL o WebGPU. Si no está seguro de qué usar, consulte la sección WebGL vs. WebGPU.
El siguiente es un ejemplo mínimo de un componente de sombreador de fragmento WebGL.
Ver en replica
< 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 >Esto produce la siguiente salida:
Aquí, la variable shaderCode es una cadena que contiene el código GLES Shader. Para simplificar, esto se almacena como una cadena, pero generalmente se almacenaría en un archivo myShader.frag separado. Al cargar el sombreador de un archivo, puede ser útil saber que la propiedad code acepta una string y una Promise<string> .
Lo que hace este código es:
u_offset dado a las coordenadas 2D del píxel dada por gl_FragCoord.xy .u_resolution para normalizar las coordenadas entre 0 y 1.x se convierte en el canal rojo y la y se convierte en el canal verde. El canal azul siempre se establece en 0, y el canal alfa (opacidad) siempre se establece en 1 (completamente opaco). En GLES, los uniformes son entradas a la función, que son las mismas para cada píxel en la pantalla. Estos deben pasar a través de la propiedad parameters del componente <WebGlShader> . En este caso, necesitamos pasar en dos uniformes: u_resolution y u_offset . Dado que estos parámetros específicos se usan muy comúnmente, se implementan especialmente en Svader de modo que la propiedad value de cada parámetro se puede establecer simplemente en "resolution" y "offset" respectivamente.
Por último, el componente <WebGlShader> acepta una ranura para alternativa, que se representa cuando el navegador no puede representar el sombreador.
La propiedad parameters es una matriz de objetos con las siguientes propiedades:
name : El nombre del parámetro uniforme, por ejemplo "my_uniform" . Esto debe coincidir con el nombre del parámetro en el código del sombreador.
type : el tipo de parámetro uniforme tal como está escrito en el código del sombreador, por ejemplo, "float" . Si la propiedad value es un valor incorporado, como "resolution" , el type se determinará automáticamente y no debe establecerse.
value : el valor del parámetro uniforme, o una cadena que especifica un valor incorporado. Si no es un valor incorporado, el tipo de esta propiedad debe corresponder a la propiedad type , de modo que:
float , int , uint es un numbervecN , ivecN , uvecN es un number[] con una longitud de N , por ejemplo, vec2 -> [1.2, 3.4] .matN es un number[] con una longitud de N * N , por ejemplo, mat2 -> [1, 2, 3, 4] . Algunos tipos de uniformes se usan muy a menudo. Estos se implementan en el propio Svader y se denominan valores incorporados . Para usarlos, la propiedad value del objeto de parámetro debe establecerse en una cadena que coincida con una de las siguientes opciones:
"resolution" : un vec2 del ancho de lienzo y la altura en los píxeles del dispositivo físico.
"scale" : un float de la relación entre los píxeles CSS y los píxeles de dispositivo físico, es decir, el nivel de zoom. Por ejemplo, si el navegador se ha acercado al 150%, el parámetro scale será 1.5 .
"time" : un float de la hora actual en segundos. Nota: pasar este parámetro al sombreador hará que se repite en cada cuadro.
"offset" : un vec2 que se agregará al gl_FragCoord.xy del sombreador de fragmentos. A veces, el tamaño del lienzo está limitado por el hardware. Para compensar esto, Svader crea un lienzo virtual con un corte de corte más pequeño para cubrir la pantalla. El parámetro de "resolution" se ajusta automáticamente para que coincida con el tamaño de este lienzo virtual, pero por razones técnicas, el gl_FragCoord.xy no se puede ajustar desde el exterior. Por lo tanto, se proporciona el parámetro "offset" para agregar manualmente a estas coordenadas.
El siguiente es un ejemplo mínimo de un componente de sombreador de fragmento webGPU.
Ver en replica
< 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 >Esto produce la siguiente salida:
Aquí, la variable shaderCode es una cadena que contiene el código de sombreador WGSL. Para simplificar, esto se almacena como una cadena, pero generalmente se almacenaría en un archivo myShader.wgsl separado. Al cargar el sombreador de un archivo, puede ser útil saber que la propiedad code acepta una string y una Promise<string> .
Lo que hace este código es:
offset dada a las coordenadas 2D del píxel dada por raw_pos.xy .resolution para normalizar las coordenadas entre 0 y 1.x se convierte en el canal rojo y la y se convierte en el canal verde. El canal azul siempre se establece en 0, y el canal alfa (opacidad) siempre se establece en 1 (completamente opaco). En WGSL, estos var<uniform> s son la forma principal de pasar en los parámetros al sombreador. Estos deben pasar a través de la propiedad parameters del componente <WebGpuShader> . En este caso, necesitamos pasar dos uniformes: resolution y offset . Dado que estos parámetros específicos se usan muy comúnmente, se implementan especialmente en Svader de modo que la propiedad value de cada parámetro se puede establecer simplemente en "resolution" y "offset" respectivamente.
Por último, el componente <WebGpuShader> acepta una ranura respirada, que se representa cuando el navegador no puede representar el sombreador.
La propiedad parameters es una matriz de objetos con las siguientes propiedades:
label : el nombre del parámetro que se utilizará para la depuración. Esto no tiene que corresponder al nombre del parámetro en el código del sombreador.
binding : un entero utilizado para hacer coincidir el parámetro con la variable en el código sombreador. Esto tiene que coincidir con la propiedad binding del parámetro en el código del sombreador, por ejemplo, para la declaración variable
@ group ( 0 ) @ binding ( 42 ) var < uniform > my_variable : f32 ; La propiedad binding debe ser 42 .
value : el valor del parámetro o una cadena que especifica un valor incorporado. Si no es un valor incorporado, este parámetro debe ser un ArrayBuffer / ArrayBufferView . Por ejemplo, para pasar un número a un parámetro f32 , se puede construir como new Float32Array([myNumberValue]) .
storage : [Opcional: predeterminado es false ] si el parámetro es una variable de almacenamiento en lugar de una variable uniforme. Esto tiene que coincidir con la declaración en el código del sombreador, por ejemplo, para la declaración variable
@ group ( 0 ) @ binding ( 0 ) var < uniform > my_variable : f32 ; la propiedad storage debe ser false u omitida, y para
@ group ( 0 ) @ binding ( 0 ) var < storage , read > my_variable : f32 ; Debería ser true . Tenga en cuenta que SVADER actualmente solo admite var<storage, read> y no var<storage, read_write> .
Algunos tipos de entradas se usan muy a menudo. Estos se implementan en el propio Svader y se denominan valores incorporados . Para usarlos, la propiedad value del objeto de parámetro debe establecerse en una cadena que coincida con una de las siguientes opciones:
"resolution" : un vec2f del ancho y la altura del lienzo en los píxeles del dispositivo físico.
"scale" : un f32 de la relación entre los píxeles CSS y los píxeles del dispositivo físico, es decir, el nivel de zoom. Por ejemplo, si el navegador se ha acercado al 150%, el parámetro scale será 1.5 .
"time" : un f32 de la hora actual en segundos. Nota: pasar este parámetro al sombreador hará que se repite en cada cuadro.
"offset" : un vec2f que se agregará al @builtin(position) del sombreador de fragmentos. A veces, el tamaño del lienzo está limitado por el hardware. Para compensar esto, Svader crea un lienzo virtual con un corte de corte más pequeño para cubrir la pantalla. El parámetro de "resolution" se ajusta automáticamente para que coincida con el tamaño de este lienzo virtual, pero por razones técnicas, la @builtin(position) no se puede ajustar desde el exterior. Por lo tanto, se proporciona el parámetro "offset" para agregar manualmente a estas coordenadas.
Para aplicaciones prácticas, predeterminada con WebGL.
WebGL y WebGPU están representando API que permiten que las aplicaciones web rinden gráficos acelerados por GPU.
WebGL es el mayor de los dos y es compatible con todos los navegadores modernos.
WebGPU todavía está en la etapa experimental y solo es compatible con algunos navegadores. Sin embargo, admite ciertas características que WebGL no. Por ejemplo, a partir de la escritura, WebGL en Google Chrome solo admite tener 8 lienzos activos en el documento a la vez, mientras que WebGPU admite un número prácticamente ilimitado.
Svader tiene licencia bajo la licencia MIT.