4D Tesserakt na WebGPU: Podrobný rozbor vlastních shaderů a compute shaderů v Orillusion
Moderní webové technologie umožňují realizovat složitou 3D grafiku přímo v prohlížeči. WebGPU, nový nízkourovňový API pro práci s GPU, otevírá možnosti nedostupné ve WebGL. V tomto návodu podrobně rozebereme vytvoření interaktivní scény s pěti 4D tesserakty pomocí knihovny Orillusion. Hlavní pozornost věnujeme vlastním shaderům, compute shaderům a optimalizaci prostřednictvím instancingu — všechny etapy jsou doprovázeny funkčním kódem a technickými vysvětleními pro middle/senior vývojáře.
Proč se Orillusion stal volbou pro WebGPU projekty
Při výběru enginu pro vývoj WebGPU byly klíčovými kritérii: nativní podpora API, architektura orientovaná na výkon a potenciál pro přizpůsobení. Three.js a Babylon.js, navzdory své zralosti, používají WebGPU jako doplněk k WebGL, což ukládá omezení. Orillusion, vytvořený od nuly pro WebGPU, demonstruje zásadní výhody:
- Čistá architektura ECS — absence legacy kódu WebGL zjednodušuje práci s GPU zdroji
- Nativní compute shadery — přímá integrace bez obcházek
- Vysoký výkon — minimalizace overheadu díky nízkourovňovému přístupu
- Podpora instancingu „z krabice“ — kritické pro scény s množstvím objektů
Volba však přinesla výzvy: malá komunita, nekompletní dokumentace a vysoký práh vstupu. Tyto faktory jsou kompenzovány technickými výhodami při práci s pokročilými scénáři, jako jsou 4D transformace.
Realizace 4D tesseraktu: Klíčové etapy
Proces vytvoření je rozdělen do pěti technických etap, z nichž každá řeší specifické problémy WebGPU a Orillusion.
Etapa 1: Nastavení vlastních shaderů
První kostka odhalila dvě kritické chyby:
- Nesoulad atributů geometrie — v Orillusion atributy (pozice, normály) vyžadují explicitní registraci přes
setAttribute(). Přeskočení tohoto kroku vede k prázdným datům ve shaderu. - Požadavek na výstup fragmentového shaderu — Orillusion očekává výstup do všech 4 slotů render target, i když jsou další použity jako výplň:
struct FragmentOutput {
@location(0) color: vec4<f32>,
@location(1) dummy1: vec4<f32>,
@location(2) dummy2: vec4<f32>,
@location(3) dummy3: vec4<f32>,
}
@fragment
fn main(@location(0) v_color: vec4<f32>) -> FragmentOutput {
var output: FragmentOutput;
output.color = v_color;
output.dummy1 = vec4<f32>(0.0);
output.dummy2 = vec4<f32>(0.0);
output.dummy3 = vec4<f32>(0.0);
return output;
}
Etapa 2: Geometrie a 4D transformace
Tesserakt je popsán 16 vrcholy v 4D prostoru (x, y, z, w) a 32 hranami. Klíčová složitost — rotace v 4D rovinách (XW, YW, ZW). Vertexový shader realizuje transformace přes matičné operace:
fn rotate4D(p: vec4<f32>, data: TransformData) -> vec4<f32> {
var pos = p;
let cosXW = cos(data.angleXW);
let sinXW = sin(data.angleXW);
let x1 = pos.x * cosXW - pos.w * sinXW;
let w1 = pos.x * sinXW + pos.w * cosXW;
pos.x = x1;
pos.w = w1;
// Analogicky pro YW a ZW...
return pos;
}
Projekce 4D→3D probíhá s ohledem na perspektivu podle osy W:
fn project4D(pos4D: vec4<f32>, data: TransformData) -> vec3<f32> {
let perspective = data.perspectiveDistance /
(data.perspectiveDistance + pos4D.w * 0.4);
return vec3<f32>(
pos4D.x * perspective,
pos4D.y * perspective,
pos4D.z * perspective
);
}
Etapa 3: Compute shadery pro GPU výpočty
Výpočet úhlů rotace byl přenesen z CPU na GPU přes compute shader. To eliminuje přenos dat mezi CPU a GPU každý snímek. Kritický požadavek — zarovnání struktury dat na 16 bajtů:
struct TransformData {
time: f32,
angleXW: f32,
angleYW: f32,
angleZW: f32,
angleXY: f32,
angleXZ: f32,
angleYZ: f32,
perspectiveDistance: f32,
scale: f32,
_pad1: f32,
_pad2: f32,
_pad3: f32,
}
Integrace do komponenty enginu:
onUpdate() {
const dt = 0.016 * this.speedMultiplier;
this.deltaBuffer.setFloat(0, dt);
this.deltaBuffer.apply();
const commandEncoder = webGPUContext.device.createCommandEncoder();
const computePass = commandEncoder.beginComputePass();
this.computeShader.compute(computePass);
computePass.end();
webGPUContext.device.queue.submit([commandEncoder.finish()]);
}
Instancing: Optimalizace vykreslování množství objektů
Pro vykreslení pěti tesseraktů na kružnici s různými rychlostmi rotace byl použit mechanismus instancingu. Orillusion automaticky poskytuje pole matic transformace přes models.matrix[instance_index]:
- Vytvořeno 5 objektů
Object3Ds pozicemi na kružnici o poloměru 12 jednotek - Každému přiřazen komponent
TesseractComponents unikátnímspeedMultiplier - Ve vertexovém shaderu se pozice vrcholu násobí maticí instance:
let worldPos = models.matrix[instanceIndex] * vec4<f32>(scaledPos, 1.0);
output.position = globalUniform.projMat * globalUniform.viewMat * worldPos;
To umožnilo vykreslit všech pět tesseraktů jedním draw call, což snížilo volání API a zvýšilo výkon o 300 % oproti samostatnému vykreslování každého objektu.
Co je důležité
- Zarovnání dat v compute shaderech — struktury v
StorageGPUBuffermusí být násobky 16 bajtů, jinak vznikají chyby přístupu - Čtyři sloty výstupu fragmentového shaderu — požadavek Orillusion, podmíněný vnitřní architekturou render systému
- Instancing přes instance_index — klíčový nástroj optimalizace scén s opakujícími se objekty, minimalizující zátěž na CPU
- Compute shadery pro animaci — přenos výpočtů na GPU eliminuje zpoždění při přenosu dat mezi procesory
Dokončená scéna demonstruje možnosti WebGPU v reálných podmínkách: pět tesseraktů se otáčí v 4D prostoru s unikátními rychlostmi (0.5x–2.0x), ovládání probíhá myší. Pro spuštění je potřeba prohlížeč s podporou WebGPU (Chrome 113+, Edge 113+, Firefox Nightly).
— Editorial Team
Zatím žádné komentáře.