Sommaren 2011 rullade en våg in i webbläsaren. Breaking Waves var ett WebGL-experiment som visade en brytande våg med skum och stänk. Projektet byggdes i three.js av den svenska utvecklaren Einar Öberg. Han använde projektet för att lära sig shaders på djupet.
- Original
- Einar Öbergs eget experiment
- År
- 2011, blogginlägget publicerades i augusti 2011
- Teknik
- WebGL, three.js, vertex och fragment shaders, modell från 3D Studio Max
- Status i dag
- Inte längre tillgänglig online på den gamla adressen
Den här sidan beskriver experimentet och tekniken bakom det, men redaktionen har inte byggt originalet. Beskrivningen bygger på Öbergs eget blogginlägg och på arkiverade versioner av sidan.
Vad var Breaking Waves?
Experimentet visade en enda stor våg som bröt mot betraktaren, med ett lugnare hav bakom. Enligt Öberg var målet att förstå shaders bättre genom att helt enkelt pröva sig fram. Han skrev att det kanske var nybörjarnivå för erfarna grafikprogrammerare, men att samma frågor dyker upp gång på gång inom området.
Vatten var ett återkommande tema för honom. I ett tidigare experiment, Waterfall, byggde han ett vattenfall i Flash med Away3D och brus.
Så fungerade det
Det fanns ingen fysisk simulering bakom. Det var en fast 3D-modell som fick liv av två shaders. Den första flyttade hörnen och den andra rörde texturerna. Det är ett vanligt sätt att få vatten att se levande ut utan att räkna på strömningar.
Modellen och färgerna
Vågen och ett enkelt plan för havet längre bort modellerades i 3D Studio Max. Öberg målade vågen med hörnfärger som shadern använde för att efterlikna hur ljus lyser igenom tunt vatten. En riktig ljusspridning under ytan hade varit mer korrekt men den enkla lösningen räckte. Ovanpå lades en normalkarta med upprepat brus för krusningar och en skumtextur av vitt Perlinbrus.
Rörelse i vertex shadern
Själva nätet var statiskt. Gungningen kom från vertex shadern, där varje hörns höjd ändrades med en sinusfunktion av hörnets position plus ett tidsvärde. Sinus ger ett värde mellan minus ett och ett. Multiplicerat med en faktor flyttar värdet hörnen upp och ned. En rörelse i sidled gav mindre krusningar.
Rörelse i fragment shadern
Vågen själv flyttade sig aldrig framåt. Det var texturkoordinaterna som sköts fram med samma tidsvärde. Vid den brytande toppen skulle vattnet röra sig åt motsatt håll, så där vreds texturen ett halvt varv. Skarven syntes bara om man tittade över vågkanten.
Djupbuffert, stänk och skum
Öberg fick problem med flimmer där ytor låg nära varandra, så kallad z-fighting. Lösningen var att placera kamerans närmaste plan så långt bort som möjligt, eftersom djupbufferten har mest precision nära kameran. Dimma och stänk ritades som sprites, det vill säga platta bilder som alltid är vända mot kameran. De återanvändes ur en pool i stället för att skapas på nytt.
Går det att göra likadant i 2026?
Ja. Verktygen är bättre i dag. Det klassiska sättet att beskriva hav i realtid är att lägga ihop flera vågor. Mark Finch beskrev 2004 i GPU Gems hur summor av sinusvågor och Gerstnervågor ger vassare toppar och bredare dalar. three.js har ett färdigt exempel med hav att utgå från.
En brytande våg som rullar över är svårare att återskapa. Den kräver antingen en modellerad form som i Breaking Waves eller en riktig vätskesimulering, som fortfarande är tung att köra i en webbläsare. Någon källkod till originalet har inte hittats på Öbergs GitHub.
Bygg något liknande
1. Ytan
Skapa ett plan med många segment så att det finns hörn att flytta.
2. Vågorna
Lägg ihop tre eller fyra sinusvågor med olika riktning och våglängd i vertex shadern.
3. Krusningarna
Låt två normalkartor glida åt olika håll i fragment shadern för att skapa små krusningar.
4. Skummet
Blanda in en vit brustextur där vågen är som högst och ställ in kamerans närmaste plan med omsorg.
Vill du veta mer om brus kan du läsa Ridged Perlin noise. Grunderna i 3D finns i A brief introduction to 3D.
Vad du kan lära dig av experimentet
Breaking Waves visar hur mycket som kan fuskas fram med enkla medel. En statisk modell, en sinusvåg och en glidande textur räckte för att lura ögat. Ingen fysikmotor behövdes för att vågen skulle kännas levande.
Lärdomen om djupbufferten är lika nyttig. Flimmer mellan ytor beror ofta på kamerans inställningar och inte på modellen, något många nybörjare upptäcker först efter lång tids felsökning.
Vanliga frågor om Breaking Waves
Vem skapade Breaking Waves?
Den svenska utvecklaren Einar Öberg gjorde experimentet och beskrev det på sin blogg i augusti 2011.
Var vågen en riktig vattensimulering?
Nej. Vågen var en modell från 3D Studio Max som animerades med shaders. Hörnens rörelse styrdes av en sinusfunktion medan texturen gled framåt.
Hur skapar man vågor i three.js i dag?
Det vanligaste är att lägga ihop flera sinusvågor eller Gerstnervågor i en vertex shader. Små krusningar läggs till med normalkartor som rör sig.
Vad orsakade flimret på ytorna?
Båda ytorna fick samma värde i djupbufferten. Problemet löstes genom att flytta kamerans närmaste plan längre bort.
Källor
- Wayback Machine: blogginlägget Breaking waves in 3D, augusti 2011
- Wayback Machine: inear.se/breaking_waves/, 9 december 2011
- NVIDIA GPU Gems: Effective Water Simulation from Physical Models
- three.js: exempel med hav
Uppgifterna kontrollerades 20 oktober 2026.

