Geometry Nodes w Blenderze. Możliwości proceduralnego modelowania i programowania wizualnego w grafice 3D.
Proceduralność w najprostszym zarysie polega na budowaniu możliwie złożonych i jednocześnie różnorodnych geometrii za pomocą zestawów algorytmów, poleceń czy wzorów matematycznych. Proceduralność oraz często współwystępująca z nią przypadkowość (randomizacja), są niezwykle interesującymi zagadnieniami matematycznymi, kojarzonymi z takimi pojęciami jak, fraktale, samopowtarzalne geometrie, rekurencja, chaos itp.
Różnorodność często nie idzie w parze ze złożonością. Proceduralne budowanie grafiki 3D obecnie znane jest ze świata gier, z tytułów, jak choćby Minecraft czy też No Man Sky (NMS).
Złożona geometria samopowtarzalna może być niezmiernie nudna, niezmienna, aż po swoje nieskończone horyzonty. Różnorodność wymaga wprowadzenia nowych reguł i warunków zwiększających pulę argumentów generujących geometrię.
Doskonałym przykładem są obie wymienione wyżej gry. Świat Minecrafta, pomimo iż generowany jest proceduralnie, zawiera liczne biomy z całymi pakietami indywidualnych cech, które muszą być wprowadzane w formie bogatego zestawu warunków początkowych, a nawet szczątkowych predefiniowanych bloków geometrii.
No Man Sky to pejzaż niezliczonej ilości generowanych proceduralnie planet, gdzie w początkowej fazie rozwoju gry główną wadą tego uniwersum był właśnie brak różnorodności. Odwiedzenie kilku planet dawało obraz o niewyobrażalnej liczbie pozostałych systemów. Wraz z rozwojem gry twórcy NMS dokładali kolejne warunki, komplikując reguły generowania, ale wprowadzając za to w monotonny pejzaż różnorodność. W efekcie powstał wszechświat NMS, który poprzez balans pomiędzy czystą proceduralnością a elementami celowymi, dostarcza satysfakcji na setki godzin jego eksploracji.
Rys 1. Pejzaż NMS. Proceduralnie zbudowany świat z nałożonymi licznymi warunkami (geometrie, AI, foliage itp.) wspomagającymi proceduralność i dodającymi celową różnorodność. Źródło: hellogames.org
Czysto proceduralna grafika bazująca wyłącznie na wzorach i geometrycznych zależnościach, dobra jest z kolei do uzyskania ciekawych efektów tła, na przykład w reklamach. Nie jest jednak sama w sobie atrakcyjna do eksploracji. Nie zmienia to faktu, że sama w sobie może być końcowym produktem wizualnym 3D.
Rys. 2. Przykład produktu reklamowego, umieszczonego na tle estetycznej geometrii proceduralnej, zbudowanej w programie Houdini. Źródło: www.sidefx.com
Scattering – proceduralność warunkowana w codziennej praktyce grafika 3d
W powszechnej praktyce grafika 3D, najczęściej spotyka się zagadnienia proceduralności, w których trzeba urzyć jakiejś formy przestrzennego rozproszenia obiektów. Nieco rzadziej nałożyć trzeba do tego jakieś sztuczne, odgórne założenia. Przykładem takich procedur są powszechnie znane procedury scatteringu. Scattering jest to operacja rozpraszania obiektów. Najbardziej powszechnymi przykładami jest rozkładanie na scenie zieleni, w tym również klastrów geometrii trawy. Inny przykład to ułożenie geometrii odpowiadającej różnym formacjom skalnym i luźnych kamieni.
Rys 3. Plugin do scatteringu w silniku UE4, w sposób proceduralny rozmieszczający na scenie elementy nieożywione pejzażu i zieleń. Źródło: Army of One
Taki rodzaj scatteringu jest bardzo słabo warunkowany – wystarczają do tego proste modyfikatory zawierające jedynie parametryzację przypadkowości. Scattering może dotyczyć też komponowania pejzaży urbanistycznych – rozłożenia kominów na dachach, ludzi na chodnikach, samochodów, zabudowy. W tym przypadku zupełna przypadkowość nie wystarczy, kiedy urbanistyka zdradza już pewne cechy różnorodności i celowości. Proceduralność wymaga tutaj nałożenia pewnych warunków dodatkowych – ludzie muszą znajdować się na chodnikach, samochody na ulicach, kominy muszą być obrócone zgodnie z osiami budynków, budynki wzdłuż osi dróg. Skarajnym przypadkiem proceduralności warunkowej może być przykład rozkładania okien na budynkach czy zasłon za oknami. Wymagane tutaj są już ścisłe pozycje, orientacje i dodatkowe warunki (wyróżniające się piony fasad, które trzeba na przykład wykluczyć). W tym przypadku proceduralność, a właściwie już tylko randomowość, dotyczyć może koloryzacji lub tasowania kolekcji rozkładanych obiektów. Reszta ma w zasadzie ściśle określone parametry i postacie.
Mamy więc całe spektrum zadań proceduralnej geometrii. Najpierw pełna proceduralność matematyczna, nie obarczona żadnymi dodatkowymi warunkami, kontrolowana przez seedy i parametry randomizacji (efekty tła dla reklam, wzornictwo fraktalne i samopowtarzalne). W grafice praktycznej są to głównie zagadnienia scatteringu. Następnie proceduralność warunkowana zestawami dodatkowych reguł lub zaimplementowanymi elementami dodatkowymi (świat gier proceduralnych). Na koniec specjalistyczne zadania, które w praktyce jedynie wykorzystują algorytmy randomizacji – precyzyjny scattering, na przykład kominy na dachach lub okna w fasadach budynków.
Programowanie wizualne
Sztuka programowania często pozostaje poza możliwościami osób zajmujących się innymi branżami. Coraz częściej jednak zadania z różnych branży wymagają rozwiązań, które muszą być oparte na procesach warunkowych lub iteracyjnych. Często jest to kwestia poszerzenia swoich możliwości twórczych lub po prostu optymalizacji procesów produkowania zawartości cyfrowej. Bardzo dynamiczny rozwój systemów i interfejsów opartych na wizualnym programowaniu (visual programming system, VPL, VPS) otwiera nowe możliwości dla każdego. Gotowe całe bloki kodów zamykane są w pojedyncze węzły, które zawierają jedynie wejście i wyjście, a wewnątrz, jakby w zamknięciu przetwarzają dostarczone im dane. Bloki takie są łączone ze sobą ustanawiając drogę przepływu danych. Użytkownik, korzystający z takiego programowania nie musi znać składni kodu (a więc w praktyce języka). Musi jedynie rozumieć jakim procesom i w jakiej kolejności muszą być poddane jego dane, by uzyskać zadowalający efekt. Do procesów takich podłączyć można parametry, których zmienianie (stąd “zmienne”) na bieżąco formuje efekt końcowy. Programowanie wizualne spotkać można zaskakująco często w różnych programach, lub ich komponentach. Oprócz Geometry Nodes Blendera i Houdiniego, jego elementy występują na przykład w UE4 (blueprinty, shading), Substance Designer (przetwarzanie tekstur, pixel procesory), 3DS max (shading). Mogą to być przygotowane w ten sposób całe języki, jak w przypadku programu Scratch, który jest doskonałym, darmowym narzędziem do nauki programowania już od wczesnych lat szkolnych. Skrajnym ale bardzo ciekawym przykładem VPL są gry firmy Tomorrow Corporation takie jak, 7 Billion Humans lub Human Resource Machine.
Houdini vs Geometry Nodes w Blenderze
Dwadzieścia lat temu powstał program firmy Side Effect Software – Houdini. Jest to bardzo kompleksowy program, którego jedną z wyróżniających się cech jest możliwość budowania proceduralnych obrazów. W ciągu ostatnich lat popularność tego programu nieustannie wzrasta, zwłaszcza wśród profesjonalnych twórców animacji opartych na proceduralnych efektach. Program jest komercyjny, a jako jedną z jego głównych wad najczęściej wymieniany jest bardzo wysoki próg wejścia. Jego możliwości są praktycznie nieograniczone, ale obycie się z jego funkcjonalnością może stanowić znaczny koszt czasowy, często niewspółmierny do postawionego sobie celu. Houdini nie miał do tej pory żadnego powszechnie dostępnego zamiennika. Na początku 2021 roku, Blender poczynając od wersji 2.92 umieścił “silnik” – Geometry Nodes (GN), który między innymi jest próbą stworzenia substytutu trudnego i drogiego Houdiniego. Jego interfejs ma wiele cech systemów wizualnego programowania. Na wyjściu osiąga się modyfikatory, które nałożone na geometrię realizują swoje procesy. Na obecnym etapie (Blender 3.2) GN ciągle jest w ograniczonej formie jeśli chodzi o możliwości przetwarzania geometrii, ale jest stabilny, a kreatywna społeczność Blendera bardzo szybko zaczęła za jego pomocą tworzyć rzeczy, które nierzadko wychodzą nawet poza główne założenia funkcjonalności GN.
Czym jest i do czego służy GN
Geometry Nodes został stworzony do budowania za pomocą interfejsu typu VPL własnych modyfikatorów, które będą potrafiły przetwarzać wejściową geometrię za pomocą szeregu procesów zdefiniowanych przez użytkownika. Tak jak to robią klasyczne modyfikatory w 3DS Max lub Blender, z tym, że użytkownik ma bezpośredni wpływ na definiowanie procesów, którym geometria ma podlegać oraz sam decyduje, jakie elementy (parametry) takich procesów chciałby wprowadzić do modyfikatora, jako jego zmienne. Dwa główne nody – wejściowy i wyjściowy, pojawiają się przy założeniu modyfikatora typu GN. Pomiędzy nimi pojawia się pole bardzo przypominające pola shaderów Blendera (identyczne) czy shadingu w 3DS Max, lub choćby pola blueprintowe i shadingowe w silniku UE4. Wprowadzić można tutaj zestaw gotowych nodów, którym dedykowane są konkretne funkcje. Łączy się je następnie tworząc kierunki przepływu procesów przetwarzania geometrii. Brzmi to i wygląda bardzo prosto i rozsądnie.
Rys 4. Interfejs nowo otwartego modyfikatora GN. Widać trywialne połączenie pomiędzy inputem i outputem. Źródło: źródło własne
Obecna wersja GN wydaje się być jeszcze silnie ograniczona. Zestaw nodów chociaż jest już sklasyfikowany w grupy, nie jest tak imponujący jak to, co oferuje Houdini. Wbrew pozorom jednak możliwości nodów które już są, są bardzo wszechstronne. Są oczywiście główne zestawy operacji matematycznych – zarówno działań na skalarach jak i na wektorach. Są kwantyfikatory, selektory i sporo operacji “branżowych” – na teksturach, krzywych, i operacje związane z translacją oraz rotacją w przestrzenii. Spawnowanie obiektów podstawowych z doborem ich parametrów. Niestety mało rozwinięta pozostaje gałąź operacji na pojedynczym obiekcie. Brakuje nodów budujących geometrię za pomocą popularnych, gotowych operacji geometrycznych typu bevel, extrudów, insetów itp. Operacje te trzeba zdefiniować indywidualnie samemu, poprzez podstawowe translacje werteksów, które wcześniej należy przypisać do dość nieporęcznych werteks grup.
Jednak centrum Geometry Nodes pozostają dwie grupy nodów, związane z przetwarzaniem dużych ilości obiektów (instancji). Odnosi się wrażenie, że są one obecnie sercem całego silnika GN.
Pierwszą grupą są operacje skupione wokół nodu “Instances on Points”. Procesy z nią związane, to nieograniczone możliwości dystrybucji geometrii poprzez osadzenie jej na chmurach punktów, które same mogą być tworzone z obiektów podstawowych, szumu, geometrii celowych, czy jakkolwiek przetworzonej przestrzeni geometrycznej. Drugim ważnym rodzajem przetwarzania geometrii są operacje związane z nodem Raycast. Próbkuje on zadaną geometrię, i na podstawie uzyskanego wyniku pozwala na podjęcie decyzji o dalszych krokach w przetwarzaniu danych.
Zastosowanie GN w aspekcie dystrybucji instancji na chmurze punktów
Można teraz powrócić do grafiki proceduralnej, oraz takiej, której proceduralność jest ściśle ograniczona przez pożądane warunki dodatkowe. W przypadku wspomnianej dystrybucji instancji na punktach chmury, możliwe jest zbudowanie każdej z nich. W przypadku prostej proceduralności wystarczy zdefiniować punkty chmury. Może to być dowolna inna geometria tworząca przestrzeń punktów. Może być ona geometryczna, lub polem szumu, nadającym poczucie zupełnej losowości. Może powstać bezpośrednio z innego obiektu 3D, być czytana z tekstury lub wyliczana ze wzorów matematycznych. Osadzane na punktach takiej chmury obiekty same w sobie również stanowią spektrum możliwości – mogą to być ściśle określone geometrie, gotowe grafiki. Mogą to być również obiekty, które same interferują z przestrzenią, na której są rozkładane przy pomocy różnych zależności. Mogą w końcu same się zmieniać wedle odrębnych reguł, poczynając od prostych skalowań, translacji czy zwykłej zmianie orientacji. Tak powstałe obrazy, pozostają zadowalające estetycznie i są interesującym tłem do zastosowań w ściśle rozumianej grafice komputerowej, jako produkcie wizualnym.
Rys 5. Przykłady kreatywnego i estetycznego zastosowania GN bazującego w głównej mierze na dystrybucji obiektów na punktach chmur, pochodzących z większych przestrzeni geometrycznych. Źródło: Entagma
W wyspecjalizowanych zadaniach GN pozwala narzucać bogaty zestaw warunków, pozwalając automatyzować bardzo specjalistyczne zadania, z bardzo różnych dziedzin grafiki komputerowej. Poniższy przykład pokazuje do jak nieoczekiwanych zastosowań można użyć kompozycję nodów GN, skupiającą się na rozkładzie obiektów na chmurze punktów.
W tym przypadku, zadaniem jest automatyczne rozmieszczenie elementów aranżacji okien w budynku na potrzeby wizualizacji architektonicznych.
Rys 6. Automatyczne rozmieszczenie instancji zasłon, pobieranej z kolekcji Blendera, i ich pozycjonowanie na punktach chmury. Punkty chmury ustalone zostały z pozycji okien, z zachowaniem informacji o ich orientacjach i wielkości. Źródło: źródło własne
Na podstawie pozycji i orientacji okien budynku, GN rozprowadza kolekcję elementów (w tym przypadku zasłon, rolet) w pozycjach określonych przez pozycję i orientację okien. Okna przetwarzane są przez GN w punkty chmury, ale zachowana zostaje w nich informacja nie tylko o pozycji okien w przestrzeni 3D, lecz również ich orientacja. Na punktach chmury umieszczane są, wybierane losowo z przygotowanej kolekcji Blendera assety zasłon. Kolekcja zasłon rozciągana jest w pozycjach okien w zależności ich wielkości – informacja o wielkości okien (bounding box) została również przypisana do punktów chmury. Zasłonom przypisywane są przez GN rożne cechy przypadkowości – ich ilość, ich dobór, ich kolor, stopień pokrycia okna. W tym przypadku GN potrafi edytować informacje przypisywane do werteksów, trójkątów czy linii rozprowadzanych instancji. Może na przykład nadpisywać Vertex Color, który staje się w końcowym silniku UE4 cenną warstwą informacji, pozwalającą, na przykład podświetlać niektóre zasłony w nocy lub koloryzować ich barwę. Wszystko to dla osiągnięcia bardzo naturalnego wyglądu wizualizacji fasady. Poza tym, wiele zmiennych, które działają na dystrybucję kolekcji zasłon w tym przykładzie, wyciągniętych jest również jako parametry modyfikatora. Bezpośrednio w interfejsie modyfikatora można więc zmieniać stopień pokrycia okien instancjami zasłon, ich offsety w stosunku do okien, a nawet ważone proporcje pomiędzy poszczególnymi rodzajami zasłon.
Rys 7. Interfejs modyfikatora GN dla podanego wyżej przykładu. Wszystkie zmienne, które potrzeba parametryzować wyciągnięte zostały do output noda GN. Pozwala to zmieniać grafikę wyjściową bez potrzeby ingerencji w strukturę nodów GN. Źródło: źródło własne
Jest to przykład, jakie możliwości daje GN w wysoce specjalistycznych zastosowaniach, ułatwiając w tym przypadku jeden z szeregu czynności budujących większy produkt. Dedykowany modyfikator GN jest w pełni edytowalny, może być rozwijany o kolejne cechy. Pomimo, że GN został stworzony do proceduralnych zastosowań, można jak widać w jego ramy włożyć bardzo ścisłe ograniczenia (wielkość, pozycję i orientację zasłon), nadal korzystając z elementów przypadkowych (kolor, wagi dystrybucji, cześć zmiennych).
Rys 8. Ogólny wygląd struktury modyfikatora GN z powyższego przykładu. Centralnym nodem pozostaje tutaj węzeł zajmujący się dystrybucją kolecki (w tym przypadku zasłon) na chmurze punktów powstałych z informacji o oknach. Źródło: źródło własne
Zastosowanie GN w aspekcie raycastowym.
Mechanizm raycastingu w grafice 3D polega na projekcji linii w celu próbkowania obiektu, na który po drodze trafi. Obiekt emitujący takie linie próbkujące często jest ściśle zdefiniowany, podobnie jak gęstość i zasięg takiej emisji. Daje to różnego typu informacje zwrotne – czy na drodze coś się znajduje? Jaka jest normalna do powierzchni, na którą trays trafił? W jakiej odległości się znajduje? W GN za pomocą węzła Raycast można zbudować emiter takich traysów próbkujący geometrię, która jest nim “naświetlana”. Poniższy przykład pokazuje zastosowanie Racastu w kolejnym wyspecjalizowanym zadaniu, będącym elementem tworzonej większej całości geometrii 3D. Budowanie pejzaży miejskich, to cały dział grafiki komputerowej, z którą zmagał się każdy, kto wykonywał choćby wizualizacje inwestycji deweloperskich. Dość powiedzieć, że realistycznie wyglądający pejzaż miejski tworzy suma dużej ilości drobnych zagadnień. Jednym z nich jest, na przykład obecność kominów, które zagęszczają pole dachów i choć same mogą być prostymi geometriami, to ich ilość i rozłożenie dodaje dużej dozy poczucia realizmu w takim pejzażu. Kominy takie można by również rozprowadzić za pomocą jednego z modyfikatorów do scatteringu. Po co więc budować coś na bazie GN? Modyfikatory scatteringowe nie są w stanie na ogół uwzględnić charakter poligonu, na którym rozmieszczają obiekty. Raycast w GN oprócz informacji, czy trafił w dach, zwraca również informacje o normalnej takiego poligonu. Normalna taka, w przypadku dachów spadzistych może być przeliczana na kierunek, który skorelowany jest z jedną z osi dachu. Uzyskuje się więc informację, na podstawie której można ustawić oś komina w zgodności z wyróżnioną osią dachu.
Rys 9. Kominy rozmieszczone na dachach geometrii zabudowy miejskiej. Ich osie generalnie zgodnie są z wyróżnionymi osiami budynków. Taki efekt jest trudny do uzyskania w zwykłych modyfikatorach scatteringujących. Źródło: źródło własne
Daje to o wiele bardziej naturalny widok całości, niż kominy o jednym lub przypadkowej orientacji względem ustawienia samego budynku.
Rys 10. Fragment konstrukcji modyfikatora GN, którego centrum stanowi węzeł Raycastujący. Źródło: źródło własne
Rys 11. Pejzaż miejski, w którego skład wchodzą geometrie powstałe w oparciu o modyfikatory GN. Są tu geometrie oparte zarówno na dystrybucji instancji na chmurze (zasłony w inwestycji pierwszego planu) oraz geometrie powstałe za pomocą Raycasowania (pole kominów zabudowy dalszych planów. Źródło: źródło własne
Geometria samopowtarzalna i fraktalna
Jednym z najciekawszych efektów, które można otrzymać za pomocą GN są geometrie samopowtarzalne, a nawet same fraktale. Obiekty samopowtarzalne uzyskuje się za pomocą dwóch i więcej iteracji umieszczania instancji obiektów geometrycznych na chmurze punktów, wygenerowanej z elementów geometrycznych (werteksów, krawędzi), takich samych obiektów. Efekty są zadziwiające i podobnie, jak czysta proceduralna geometria, jako wizualizacje mogą same w sobie tworzyć gotowy produkt wizualny.
Rys 12. Przykłady prostych obiektów samopowtarzalnych oraz nietrywialnych zbiorów fraktalnych. Wszystkie powstały w Blenderze za pomocą GN lub czystego shadingu tekstur. Źródło: Blender Nation
Trudniejszym, ale też mniej trywialnym zagadnieniem, jest próba budowania za pomocą GN fraktali. Do tej pory można to było zrobić w Blenderze za pomocą shadingu na pikselach tekstur. Powstawały już w ten sposób piękne obrazy zbioru Mandelbrota czy słynnego zbioru Julii. Tymczasem, generowanie fraktali za pomocą GN pozwala na wizualizację geometryczną, a nie na wypalanie obrazu w rastrze. Można to zrobić w ten sposób, że zadaje się pewną płaszczyznę o określonej gęstości punktów (grid) i bada się przestrzeń 3D w jej obrębie pod kątem zbieżności ciągu sum (ściśle określonej w zależności od rodzaju zbioru fraktalnego). Dokładnie tak samo jak robi to się w metodzie shadingowej.
Rys 13. Zbiór Mandelbrota o postaci geometrycznej powstały jako modyfikator GN działający na płaszczyznę XY sceny 3D Blendera. Modyfikator pozwala wykonać kilkaset iteracji zbieżności sum oraz zagęścić próbkowanie powierzchni do dziesiątkach milionów punktów. Pozwala również zajrzeć w głąb zbioru praktycznie do granicy precyzji samej przestrzeni 3D Blendera. Źródło: źródło własne
Metoda ta wydaje się być jednak lepsza od budowania fraktali na teksturze. Można bowiem pokusić się o rozszerzenie badanej przestrzeni z płaskiej do w pełni trójwymiarowej. Obiektem próbkującym taką przestrzeń będzie wtedy nie płaszczyzna (grid), lecz wolumen (wycinek sześcienny przestrzeni 3D). W dalszym następstwie można w tak zbadanej przestrzeni fraktalnej umieścić kamerę i próbować wykonać różne projekcje tego co z jej pozycji widać. Nie wspominając o takich możliwościach, jak wprowadzenie tak zbudowanej przestrzeni fraktalnej do wirtualnej rzeczywistości i oglądanie jej osobiście za pomocą gogli VR.
Podsumowanie
Geometry nodes to zdecydowanie nowatorski silnik w obrębie Blendera. Wiele mu brakuje. Nie ma tam dobrych systemów iteracji czy czytelnych pętli warunkowych. Bardzo ograniczona wydaje się też możliwość przetwarzania pojedynczych obiektów za pomocą typowych operacji ze świata klasycznego modelowania 3D. Jednak jego początkowa faza paradoksalnie pozwala na szybkie opanowanie całego zakresu, jego operatorów i funkcjonowania. Takiej wygody nie mamy wchodząc w świat Houdiniego, gdzie ilość elementów jaką się dostaje na wejściu jest przytłaczająca i zniechęcająca, powodując że próg wejściowy Houdiniego jest tak wysoki. Nie można pominąć też faktu, że podobnie jak w innych dziedzinach Blender, tak jego GN w dziedzinie proceduralnego przetwarzania geometrii, tworzy kolejny darmowy zamiennik drogich rynkowych rozwiązań.
Na uwagę zasługuje również fakt, iż w tak krótkim czasie, od wypuszczenia pierwszej wersji GN, społeczność grafików, programistów i entuzjastów Blendera, natychmiast znalazła dla niego zastosowania, które nierzadko przekraczają początkowe założenia samych twórców. Dobrym przykładem jest tutaj możliwość używania GN do interesujących badań struktur fraktalnych w sposób, w jaki nie pozwala żaden innych popularny i dostępny dla każdego program, jakim jest Blender.