Zaczęło się od pytania
Oglądałem film o Boids — algorytmie stadnym wymyślonym przez Craiga Reynoldsa w 1987 roku. Wizualizacja była piękna: setki wirtualnych ptaków pikujących i skręcających jak jeden organizm. Reguły były zwodniczo proste: separacja, wyrównanie, kohezja. Trzy siły — i otrzymujesz emergentne zachowanie, które wygląda jak żywe.
Pomyślałem: czy da się to zbudować w przeglądarce w jeden weekend?
Odpowiedź brzmiała: tak. W około dwanaście godzin kodowania, rozłożonych na sobotę i niedzielę, miałem działającą symulację Boids w Three.js z 500 agentami, płynnie działającą przy 60 FPS.
Symulacja Boids działa do dziś — znajdziesz ją pod adresem /boids/. Nadal używa mniej więcej tego samego hasza przestrzennego, który napisałem tamtego pierwszego weekendu.
Jedna staje się dwiema, potem wieloma
Problem z ukończeniem jednej symulacji polega na tym, że od razu podsuwa pomysł na kolejną. Boids skłoniły mnie do myślenia o Grze w Życie — kolejnym systemie „prostych reguł, złożonego wyniku". Gra w Życie skłoniła mnie do myślenia o reakcji-dyfuzji. Reakcja-dyfuzja skłoniła mnie do myślenia o dynamice płynów.
Zanim się obejrzałem, miałem folder simulations/ z
siedmioma pozycjami. Potem piętnastoma. Potem trzydziestoma.
Każda z nich nauczyła mnie czegoś, czego się nie spodziewałem:
- Boids — przyspieszenie za pomocą hasza przestrzennego, zachowanie emergentne
- Fluid — matematyka SPH, wąskie gardła CPU, dlaczego potrzebne są obliczenia na GPU
- Galaxy — InstancedMesh, własne shadery wierzchołków, minimalizacja wywołań rysowania
- Ocean — właściwy workflow GLSL, równania fal Gerstnera, Fresnel
- Tectonic Plates — geometria sferyczna, mapy przemieszczeń, mapowanie UV w Three.js
Dlaczego czysty HTML/JS — bez etapu budowania
Na wczesnym etapie podjąłem decyzję, która ukształtowała wszystko
później: żadnych bundlerów, żadnego npm, żadnego pipeline'u
budowania. Każda symulacja ładuje się bezpośrednio z
systemu plików przez znacznik <script> albo
działa jako zwykły URL file://.
Powód był częściowo lenistwem (nie chciałem konfigurować Webpacka), a częściowo filozofią. Platforma webowa jest wystarczająco potężna. Nowoczesne moduły ES działają natywnie. Three.js dostarcza build gotowy do użycia w przeglądarce. Otwierasz plik HTML i po prostu działa.
Okazało się to trafnym wyborem. Projekt jest banalnie przenośny —
spakuj go, przekaż komukolwiek, działa. Żadnego
node_modules. Żadnych plików lock. Żadnego „u mnie
działa".
Co napędza projekt dalej
Szczera odpowiedź? Ciekawość. Każda symulacja odpowiada na jedno pytanie i rodzi trzy kolejne.
Nieco mniej szczera odpowiedź: pętla informacji zwrotnej jest niezwykle krótka. Edytujesz shader, odświeżasz stronę, widzisz wynik — bez kompilacji, bez konfigurowania hot reloadu, bez błędów typów do naprawienia. To najszybszy możliwy cykl iteracji, i to właśnie czyni go uzależniającym.
Projekt rozrósł się w coś, czego pierwotnie nie planowałem: rodzaj interaktywnego podręcznika. Fizyka, biologia, matematyka, uczenie maszynowe — wszystko renderowane w czasie rzeczywistym w przeglądarce, za darmo i otwarcie, dla każdego, kto jest wystarczająco ciekawy, by spojrzeć.
Co dalej
Seria devlogów będzie opisywać poszczególne symulacje bardziej szczegółowo: matematykę stojącą za nimi, decyzje implementacyjne, błędy, na których wytropienie potrzeba było trzech dni.
Następny wpis: Devlog #2 — Płyn SPH: od Wikipedii do 60 FPS →