สร้างส่วนประกอบ Svelte ที่เรนเดอร์ GPU ด้วย WebGL และ WebGPU Fragment Shader
รองรับ Svelte 4 และ Svelte 5
ในระยะสั้น shader ชิ้นส่วน สามารถเขียนเป็นโปรแกรมที่ใช้พิกัดของพิกเซลบนหน้าจอและส่งคืนสีที่พิกเซลนี้ควรมี โปรแกรมนี้สามารถดำเนินการบน GPU เพื่อให้มั่นใจว่าการขนานและความเร็วขนาดใหญ่
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการเขียนเศษชิ้นส่วนให้ตรวจสอบหนังสือของ Shaders
ต่อไปนี้เป็นชุดของตัวอย่างทั้งหมดที่ทำโดยใช้ svader เวอร์ชันสดทั้งหมดของสิ่งเหล่านี้สามารถดูตัวอย่างบน svader.vercel.app และซอร์สโค้ดสามารถพบได้ใน src/routes/ Directory
# npm
npm i -D svader
# pnpm
pnpm i -D svader
# Bun
bun i -D svader
# Yarn
yarn add -D svaderในการใช้ส่วนประกอบ Shader Fragment คุณต้องตัดสินใจก่อนว่าจะใช้ WebGL หรือ WebGPU หากคุณไม่แน่ใจเกี่ยวกับสิ่งที่ใช้ให้ดูส่วน WebGL กับ WebGPU
ต่อไปนี้เป็นตัวอย่างที่น้อยที่สุดของส่วนประกอบ shader ชิ้นส่วน WebGL
ดูใน 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 >สิ่งนี้สร้างผลลัพธ์ต่อไปนี้:
ที่นี่ตัวแปร shaderCode เป็นสตริงที่มีรหัส GLES Shader เพื่อความเรียบง่ายสิ่งนี้จะถูกเก็บไว้เป็นสตริง แต่โดยทั่วไปแล้วจะถูกเก็บไว้ในไฟล์ myShader.frag แยกต่างหาก เมื่อโหลด shader จากไฟล์อาจเป็นประโยชน์ที่จะทราบว่าคุณสมบัติ code ยอมรับทั้ง string และ Promise<string>
รหัสนี้คืออะไร:
u_offset ที่กำหนดในพิกัด 2D ของพิกเซลที่กำหนดโดย gl_FragCoord.xyu_resolution เพื่อทำให้พิกัดเป็นมาตรฐานระหว่าง 0 ถึง 1x กลายเป็นช่องสีแดงและพิกัด y กลายเป็นช่องสีเขียว ช่องสีน้ำเงินถูกตั้งค่าเป็น 0 เสมอและช่องอัลฟ่า (ความทึบ) จะถูกตั้งค่าเป็น 1 เสมอ (ทึบแสงเต็ม) ใน Gles เครื่องแบบ เป็นอินพุตไปยังฟังก์ชั่นที่เหมือนกันสำหรับทุกพิกเซลบนหน้าจอ สิ่งเหล่านี้จำเป็นต้องส่งผ่านผ่านคุณสมบัติ parameters ของส่วนประกอบ <WebGlShader> ในกรณีนี้เราต้องผ่านสองชุด: u_resolution และ u_offset เนื่องจากพารามิเตอร์เฉพาะเหล่านี้ใช้กันทั่วไปจึงถูกนำไปใช้เป็นพิเศษใน SVADER เพื่อให้คุณสมบัติ value ของแต่ละพารามิเตอร์สามารถตั้งค่าเป็น "resolution" และ "offset" ตามลำดับ
สุดท้ายส่วนประกอบ <WebGlShader> ยอมรับสล็อตทางเลือกซึ่งแสดงผลเมื่อเบราว์เซอร์ไม่สามารถแสดงผลได้
คุณสมบัติ parameters คืออาร์เรย์ของวัตถุที่มีคุณสมบัติต่อไปนี้:
name : ชื่อของพารามิเตอร์เครื่องแบบเช่น "my_uniform" สิ่งนี้จะต้องตรงกับชื่อของพารามิเตอร์ในรหัส shader
type : ประเภทของพารามิเตอร์เครื่องแบบตามที่เขียนไว้ในรหัส shader เช่น "float" หากคุณสมบัติ value เป็นค่าในตัวเช่น "resolution" type จะถูกกำหนดโดยอัตโนมัติและไม่ควรตั้งค่า
value : ค่าของพารามิเตอร์เครื่องแบบหรือสตริงที่ระบุค่าในตัว หากไม่ใช่ค่าในตัวประเภทของคุณสมบัตินี้จะต้องสอดคล้องกับคุณสมบัติ type เช่นนั้น:
float , int , uint เป็น numbervecN , ivecN , uvecN เป็น number[] ที่มีความยาว N , เช่น vec2 -> [1.2, 3.4]matN คือ number[] ที่มีความยาว N * N , เช่น mat2 -> [1, 2, 3, 4] เครื่องแบบบางประเภทใช้บ่อยมาก สิ่งเหล่านี้ถูกนำไปใช้ใน Svader เองและเรียกว่า ค่าในตัว ในการใช้สิ่งเหล่านี้คุณสมบัติ value ของวัตถุพารามิเตอร์จะต้องตั้งค่าเป็นสตริงที่ตรงกับหนึ่งในต่อไปนี้:
"resolution" : A vec2 ของความกว้างและความสูงของผืนผ้าใบในพิกเซลอุปกรณ์ทางกายภาพ
"scale" : การ float ของอัตราส่วนระหว่างพิกเซล CSS และพิกเซลอุปกรณ์ทางกายภาพเช่นระดับซูม ตัวอย่างเช่นหากเบราว์เซอร์ถูกซูมเป็น 150%พารามิเตอร์ scale จะเป็น 1.5
"time" : float ของเวลาปัจจุบันในไม่กี่วินาที หมายเหตุ: การส่งพารามิเตอร์นี้ไปยัง shader จะทำให้อีกครั้งในทุกเฟรม
"offset" : A vec2 ที่จะเพิ่มลงใน gl_FragCoord.xy ของ Fragment Shader บางครั้งขนาดของผ้าใบถูก จำกัด ด้วยฮาร์ดแวร์ เพื่อชดเชยสิ่งนี้ Svader สร้างผืนผ้าใบเสมือนจริงด้วยการคัตเอาท์ขนาดเล็กที่ขยับไปมาเพื่อครอบคลุมหน้าจอ พารามิเตอร์ "resolution" จะถูกปรับโดยอัตโนมัติเพื่อให้ตรงกับขนาดของผืนผ้าใบเสมือนนี้ แต่ด้วยเหตุผลทางเทคนิค gl_FragCoord.xy ไม่สามารถปรับได้จากภายนอก ดังนั้นพารามิเตอร์ "offset" จึงถูกเพิ่มเข้ามาในพิกัดเหล่านี้ด้วยตนเอง
ต่อไปนี้เป็นตัวอย่างที่น้อยที่สุดขององค์ประกอบ shader ชิ้นส่วน WebGPU
ดูใน 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 >สิ่งนี้สร้างผลลัพธ์ต่อไปนี้:
ที่นี่ตัวแปร shaderCode เป็นสตริงที่มีรหัส WGSL Shader เพื่อความเรียบง่ายสิ่งนี้จะถูกเก็บไว้เป็นสตริง แต่โดยทั่วไปแล้วจะถูกเก็บไว้ในไฟล์ myShader.wgsl แยกต่างหาก เมื่อโหลด shader จากไฟล์อาจเป็นประโยชน์ที่จะทราบว่าคุณสมบัติ code ยอมรับทั้ง string และ Promise<string>
รหัสนี้คืออะไร:
offset ออฟเซ็ตที่ได้รับลงในพิกัด 2D ของพิกเซลที่กำหนดโดย raw_pos.xyresolution เพื่อทำให้พิกัดปกติระหว่าง 0 ถึง 1x กลายเป็นช่องสีแดงและพิกัด y กลายเป็นช่องสีเขียว ช่องสีน้ำเงินถูกตั้งค่าเป็น 0 เสมอและช่องอัลฟ่า (ความทึบ) จะถูกตั้งค่าเป็น 1 เสมอ (ทึบแสงเต็ม) ใน WGSL var<uniform> เหล่านี้เป็นวิธีหลักในการส่งผ่านพารามิเตอร์ไปยัง shader สิ่งเหล่านี้จำเป็นต้องส่งผ่านผ่านคุณสมบัติ parameters ของส่วนประกอบ <WebGpuShader> ในกรณีนี้เราต้องผ่านสองชุด: resolution และ offset เนื่องจากพารามิเตอร์เฉพาะเหล่านี้ใช้กันทั่วไปจึงถูกนำไปใช้เป็นพิเศษใน SVADER เพื่อให้คุณสมบัติ value ของแต่ละพารามิเตอร์สามารถตั้งค่าเป็น "resolution" และ "offset" ตามลำดับ
สุดท้ายส่วนประกอบ <WebGpuShader> ยอมรับช่องทางเลือกซึ่งแสดงผลเมื่อเบราว์เซอร์ไม่สามารถแสดงผลได้
คุณสมบัติ parameters คืออาร์เรย์ของวัตถุที่มีคุณสมบัติต่อไปนี้:
label : ชื่อของพารามิเตอร์ที่จะใช้สำหรับการดีบัก สิ่งนี้ไม่จำเป็นต้องสอดคล้องกับชื่อของพารามิเตอร์ในรหัส shader
binding : จำนวนเต็มที่ใช้เพื่อจับคู่พารามิเตอร์กับตัวแปรในรหัส shader สิ่งนี้จะต้องตรงกับคุณสมบัติ binding ของพารามิเตอร์ในรหัส shader เช่นสำหรับการประกาศตัวแปร
@ group ( 0 ) @ binding ( 42 ) var < uniform > my_variable : f32 ; คุณสมบัติ binding ควรเป็น 42
value : ค่าของพารามิเตอร์หรือสตริงที่ระบุค่าในตัว หากไม่ใช่ค่าในตัวพารามิเตอร์นี้ควรเป็น ArrayBuffer / ArrayBufferView ตัวอย่างเช่นในการส่งผ่านตัวเลขไปยังพารามิเตอร์ f32 สามารถสร้างได้เช่น new Float32Array([myNumberValue])
storage : [ตัวเลือก - ค่าเริ่มต้นเป็น false ] ว่าพารามิเตอร์เป็นตัวแปรที่เก็บข้อมูลมากกว่าตัวแปรที่สม่ำเสมอหรือไม่ สิ่งนี้จะต้องตรงกับการประกาศในรหัส shader เช่นสำหรับการประกาศตัวแปร
@ group ( 0 ) @ binding ( 0 ) var < uniform > my_variable : f32 ; คุณสมบัติ storage ควรเป็น false หรือละเว้นและสำหรับ
@ group ( 0 ) @ binding ( 0 ) var < storage , read > my_variable : f32 ; มันควรจะเป็น true โปรดทราบว่าปัจจุบัน svader รองรับ var<storage, read> และไม่ใช่ var<storage, read_write>
อินพุตบางประเภทใช้บ่อยมาก สิ่งเหล่านี้ถูกนำไปใช้ใน Svader เองและเรียกว่า ค่าในตัว ในการใช้สิ่งเหล่านี้คุณสมบัติ value ของวัตถุพารามิเตอร์จะต้องตั้งค่าเป็นสตริงที่ตรงกับหนึ่งในต่อไปนี้:
"resolution" : vec2f ของความกว้างและความสูงของผ้าใบในพิกเซลอุปกรณ์ทางกายภาพ
"scale" : อัตราส่วน f32 ระหว่างพิกเซล CSS และพิกเซลอุปกรณ์ทางกายภาพเช่นระดับซูม ตัวอย่างเช่นหากเบราว์เซอร์ถูกซูมเป็น 150%พารามิเตอร์ scale จะเป็น 1.5
"time" : f32 ของเวลาปัจจุบันในไม่กี่วินาที หมายเหตุ: การส่งพารามิเตอร์นี้ไปยัง shader จะทำให้อีกครั้งในทุกเฟรม
"offset" : A vec2f ที่จะเพิ่มลงใน @builtin(position) ของ shader ชิ้นส่วน บางครั้งขนาดของผ้าใบถูก จำกัด ด้วยฮาร์ดแวร์ เพื่อชดเชยสิ่งนี้ Svader สร้างผืนผ้าใบเสมือนจริงด้วยการคัตเอาท์ขนาดเล็กที่ขยับไปมาเพื่อครอบคลุมหน้าจอ พารามิเตอร์ "resolution" จะถูกปรับโดยอัตโนมัติเพื่อให้ตรงกับขนาดของผืนผ้าใบเสมือนนี้ แต่ด้วยเหตุผลทางเทคนิค @builtin(position) ไม่สามารถปรับได้จากภายนอก ดังนั้นพารามิเตอร์ "offset" จึงถูกเพิ่มเข้ามาในพิกัดเหล่านี้ด้วยตนเอง
สำหรับแอปพลิเคชันที่ใช้งานได้จริงให้ใช้ WebGL
WebGL และ WebGPU เป็นทั้ง APIs ที่ให้เว็บแอปพลิเคชันสามารถแสดงผลกราฟิกที่เร่งด้วย GPU
WebGL เป็นผู้สูงอายุของทั้งสองและได้รับการสนับสนุนจากเบราว์เซอร์ที่ทันสมัยทั้งหมด
WebGPU ยังอยู่ในขั้นตอนการทดลองและได้รับการสนับสนุนในเบราว์เซอร์เพียงไม่กี่ตัวเท่านั้น อย่างไรก็ตามรองรับคุณสมบัติบางอย่างที่ WebGL ไม่ได้ ตัวอย่างเช่นในการเขียน WebGL ใน Google Chrome รองรับการมี 8 ผืนที่ใช้งานอยู่ในเอกสารพร้อมกันในขณะที่ WebGPU รองรับหมายเลขไม่ จำกัด
Svader ได้รับใบอนุญาตภายใต้ใบอนุญาต MIT