Wsparcie skryptowe w środowiskach grafiki 3D. Jak rozpocząć jego naukę?
Grafika 3D – dziś łatwiejsza niż się wydaje
Po dynamicznym w ostatnich latach rozwoju programu Blender, będącego darmowym programem do tworzenia grafiki 3D, jego najnowsze wersje uzyskały wyjątkowo przyjazny interfejs, stabilność, lekkość oraz spójność instalacji.
Dziedzina grafiki komputerowej w swojej postaci 3D uzyskała dzięki temu „niski próg wejścia” dla wszystkich chętnych, chcących spróbować swoich sił w tej branży produktów cyfrowych. Sprzyja temu również dynamiczny wzrost ilości materiałów szkoleniowych i dobrej dokumentacji ze strony środowisk z Blenderem związanych. Nie bez znaczenia jest tutaj też osiągnięcie statusu zamiennika dla drogiego (aczkolwiek ciągle królującego na wielu polach wśród środowisk 3D) programu 3ds Max.
Do uzyskania niskiego progu wejścia dla grafiki 3D przyczynił się również powszechnie lubiany program firmy Trimble — Sketchup (niegdyś zupełnie darmowy produkt Google, dziś skomercjalizowany), którego podstawowy interfejs składa się dosłownie z kilkunastu ikon, a budowanie w nim grafiki to czysta zabawa i przyjemność.
Trzecim ważnym produktem jest wspomniany 3ds Max firmy Autodesk. Jest ciągle powszechnie uważany za najbardziej zaawansowany program do tworzenia grafiki 3D. Ze względu na jego olbrzymią cenę (roczna subskrypcja to ponad 10 tys. PLN) oraz z drugiej strony atrakcyjność i funkcjonalna zamienność Blendera, coraz więcej użytkowników i całych firm odchodzi dziś od 3ds Max na korzyść tego drugiego. Nie zmienia to faktu, że proces tworzenia grafiki w tym narzędziu jest bardzo intuicyjny i wygodny, a w niektórych aspektach nawet prostszy od analogicznych czynności i procesów wykonywanych w Blenderze.
Istnieje szereg innych programów pozwalających na budowanie grafiki 3D, na przykład Rhino, Solidworks, Vectorworks, ZBrush, Mudbox czy Maya. Są one często bardziej wyspecjalizowane — jedne nadają się do tworzenia modeli biżuterii, inne geometrii organicznej, wreszcie jeszcze inne trafiają na pogranicze zastosowań inżynierskich, są ściśle CADowe i ze wsparciem charakterystyk fizycznych tworzyw i materiałów. Mimo to również i one najczęściej posiadają swoje własne (często nawet skrajnie od siebie odmienne) ergonomiczne interfejsy, pozwalające opanować procesy tworzenia trójwymiarowej grafiki w relatywnie krótkim czasie.
Tworzenie grafiki 3D samo w sobie należy do procesów, które zwyczajowo określić można mianem “easy to learn, hard to master”. Próg wejścia w ten świat jest dziś dostępny praktycznie dla każdego, kto tylko będzie miał chęć poświęcenia odrobiny czasu, by poznać nieco teorii i zapoznać się z interfejsem któregoś z tego typu programów.
Niestety ma to też swoje ujemne strony. Graficy 3D operujący w sposób podstawowy którymś z wymienionych programów, stanowią niestety dość liczną grupę. Specjalizacja ta na podstawowym poziomie nie wymaga ukończenia studiów ani kierunkowych szkół. Mimo że coraz więcej branży potrzebuje grafików 3D (rynek produktowy, rynek reklamowy, rynek deweloperski czy gamedev), duża podaż podstawowych umiejętności w tej dziedzinie przenosi się na potencjalnie mniejsze zarobki (w porównaniu na przykład ze ścisłym programowaniem). Osoba wykonująca zawód grafika, pomimo że sprawnie operuje środowiskiem 3D, szybko dociera do granic możliwości zawartych w operacjach swojego narzędzia. Zaczynają pojawiać się zadania i przeszkody, które wykraczają poza możliwości podstawowej wersji oprogramowania. Wtedy w grę wchodzi pojęcie skryptowania. Jest ono nie tylko sposobem na podniesienie kwalifikacji grafika 3D, tym samym wywindowania wręcz jego gaży, ale przede wszystkim procesem, którego opanowanie pozwala pokonać wszelkie bariery i niedogodności stawiane przez sam program graficzny. Nierzadko bariery stawiane przez samego pracodawcę.
Skryptowanie w środowisku grafiki 3D
Skryptowanie jest programowaniem. Za pomocą jednego z języków programowania pisze się kod, którego kompilacja/interpretacja wykonuje określone czynności w środowisku graficznym, w którym jest realizowana (w konkretnym sofcie). W zasadzie więc skryptowanie jest niczym innym niż zadaniem dla programisty władającego sprawnie którymś z języków programowych, którego kompilacja (lub interpretacja, czego rozróżnienie jest nieistotne w dalszym toku rozumowanie) jest rozumiana przez konkretny program graficzny. Na tym etapie można pomyśleć, że grafik 3D nie będzie tutaj miał nic do roboty. Niekoniecznie. Po pierwsze programiści najczęściej nie są grafikami 3D. Nie rozumieją potrzeb i zadań, a przede wszystkim procesów rządzących tworzeniem grafiki 3D. Programista sprawnie operuję językiem programowania, ale nie rozeznaje się w pojęciach takich jak operacje na werteksach, trójkątach, poligonach. Nie wie czym jest unwrap lub tekstura. Nie wie, jakie dodatkowe informacje można przenosić w pojedynczych obiektach 3D (na przykład za pomocą vertex painting`u, w kanałach UV itd.). Z drugiej strony, pisanie skryptów na ogół nie odbywa się „bez pomocy” od strony samego programu. Znaczy to, że grafik nie pozostaje pozostawiony sam sobie z pustym edytorem tekstowym, a niektóre programy posiadają wbudowany system do tłumaczenia pożądanych operacji bezpośrednio na język skryptowy oraz co ważniejsze, posiadają biblioteki (tak zwane API) będące gotowymi funkcjami wykonującymi konkretne operacje na obiektach 3D (i nie tylko).
Czym jest API
Każde oprogramowanie zawierające środowisko przyjazne do skryptowania/modowania zawiera swoją bibliotekę API. Interfejs programowania aplikacji (API — application programming interface), to ze względu na swoją uniwersalność szerokie pojęcie z dziedziny programowania. Na potrzeby skryptowania w programach do grafiki 3D wystarczy wiedzieć, że jest to coś pod postacią interfejsu — fizycznie i w przenośni, pozwalającego użytkownikowi pośredniczyć pomiędzy czystym kodem języka programowania, a bardziej uogólnionymi operacjami i interakcjami, na przykład z przestrzenią obiektów 3D. Oto prosty przykład. Potrzebny jest proces stworzenia w przestrzeni 3D obiektu typu (mesh) o kształcie sześcianu. Jest to na tyle prosta i podstawowa operacja, że jej wykonanie jest szybkie na poziomie interfejsu każdego programu 3D. Jakby to wyglądało dla programisty? Byłby to skomplikowany problem. Musiałby znaleźć dostęp do przestrzeni 3D, w której musiałby potrafić zdefiniować 8 werteksów. Dla każdego z nich zdefiniować pozycję, ale również dodatkowe informacje, które może ze sobą graficzny werteks nieść. Na przykład ustalić kierunki ich normalnych, wartości koloru (vertex painting), dodatkowe informacje w przestrzeni UV w przypadku potrzeby mapowania tekstur na takim obiekcie, itd. Werteksy to nie koniec. Należałoby zdefiniować kolejność rozpinania trójkątów budujących poligony na sześcianie. W tym przypadku 12 trójkątów przypisanych do 8 werteksów, których rozpięcie musiałoby być określane na nich jeden po drugim. Zestaw werteksów i rozpiętych na nich trójkątów mógłby stworzyć sześcian, ale wyzwaniem pozostanie “spawnowanie” czyli pojawienie się jego składników jako obiektów w przestrzeni 3D.
Co jeśli trzeba by było za pomocą programowania ruszyć takim obiektem, lub jeszcze gorzej – obrócić nim? Definiowanie translacji dla ruchu lub orientacji (dla obrotów) w czystym programowaniu to operacje matematyczne często odwołujące się do dość trudnej algebry macierzy i trygonometrii. Nie tylko grafik nie musi się na tym znać, ale i programista niebędący matematykiem może mieć z tym kłopot, zwłaszcza jeśli nie rozumie samej idei spawnowania i translacji mesha – sześcianu w przestrzeni 3D (idei tak bliskiej dla każdego grafika). Tutaj z pomocą przychodzi API. Zawiera ono między innymi określone polecenia, operatory czy funkcje, które przetwarzają z pozoru proste komendy (“spawnuj box”, “wykonaj unwrap projekcyjny” itd.) na wbudowany w sobie, podstawowy kod języka programowania. Skrypty na ogół mają na celu wykonanie bardziej zaawansowanych operacji. Sześcian można stworzyć pojedynczym kliknięciem interfejs programu. Co jeśli na przykład potrzeba rozmieścić ich setki w przestrzeni 3D w sposób zupełnie przypadkowy? Znowu, z punktu widzenia czystego programowania definiowanie “przypadkowości” jest gruntownie nietrywialnym zagadnieniem. Tymczasem możemy od API uzyskać gotowe funkcje randomizujące bez wnikania w sposób, w jaki ich przypadkowość jest definiowana. A co jeśli do każdego tak stworzonego obiektu chcielibyśmy doczepić, zespawnować inny obiekt w ściśle określony sposób? Za pomocą API możemy uzyskać informacje o pozycji i orientacji wszystkich obiektów na scenie już się znajdujących, i wykorzystać ją do spawnowania nowych, w określonych zależnościach geometrycznych i przestrzennych w stosunku do siebie. API pozwala nam zacieśnić zagadnienie składni kodu, omijając potrzebę pisania wszystkiego na nowo, skupiając się jedynie na budowaniu operacji wyższego rzędu, które są zrozumiałe i istotne dla grafika. API jest dla użytkownika niebędącego programistą czymś na kształt czarnej skrzynki. Użytkownik nie musi wiedzieć, co się w środku określonej funkcji znajduje. Grafik 3D wie, co potrzebuje – określa sobie intuicyjne operacje, szukając do ich realizacji w API odpowiedniej czarnej skrzynki, która na wyjściu mu daje pożądany rezultat, bez potrzeby wnikania jak w środku żądanie to zostało przetworzone.
[Rys 1. Fragment dokumentacji API Blendera. W tym przypadku operatory mapujące geometrię 3D]
Macro Recorder
Co jeśli API jest zbyt złożone? Paradoksalnie im środowisko jest bardziej przygotowanie na pisanie skryptów, tym API jest większą i trudniejszą do ogarnięcia biblioteką. Jego przeglądanie, zapamiętywanie czy nauka obsługi, już samo w sobie może być trudną lekcją. W takiej sytuacji z pomocą przychodzą kolejne ułatwienia w skryptowaniu, oferowane przez programy graficzne (przynajmniej w przypadku Blendera i 3ds Max). Są to macro recorder`y. Macro recorder nie jest pojęciem sztywnym. Może być wbudowanym narzędziem (jak w przypadku 3ds Max), może to być zwykłe listowanie aktualnie wykonywanych operacji na przestrzeni 3D (jak w przypadku Blendera). Mogą to być również osobne zewnętrzne skrypty, które wykonują zapis lub interpretują czynności wykonywane w programie, na język programowania uwzględniający API. Idea jednak zawsze pozostaje taka sama — użytkownik wykonuje pożądane operacje w sposób ręczny, na scenie 3D, a recorder przetwarza to na kod.
[Rys 2. 3ds Max. Macro recorder rejestrujący w oknie skryptowym zapis ręcznej operacji translacji i zmiany orientacji sześcianu]
Taki kod można potem zamknąć w skrypt i odtwarzać go otrzymując ciąg operacji, co do których nie istnieją pojedyncze przyciski natywnych interfejsów programu.
Przykład. Wykonanie na obiekcie mapowania z projekcji, z sześcianu o wielkości 2 m. W przypadku 3ds Max czynność taka jest bardzo prosta i podstawowa, ale wymaga wykonania szeregu kliknięć. Trzeba wyszukać i nałożyć modyfikator mapowania, wybrać projekcję sześcienną, wprowadzić jej wielkość dla każdej osi, skolapsować modyfikator. Czynność taką można zapisać przy pomocy recordera jednorazowo. Uzyskany od recordera kod można od razu zapisać i uruchomić jako skrypt. Jeszcze lepiej — taki skrypt można dołączyć do natywnego interfejsu jako dodatkowy przycisk (można nawet wyedytować jego wygląd i opis). Od tej pory szereg operacji staje się stałym elementem interfejsu programu 3D. Przykład był bardzo prosty, ale zawarł wszystkie wspomniane do tej pory elementy. Użyty został język programowania, w którym na pewno zawarte zostały elementy API. Recorder pozwolił przetłumaczyć ręczne czynności wykonywane na scenie, na bloki kodu, i to bez konieczności jakiejkolwiek znajomości programowania, ani nawet elementów API. Grafik pozostał w zakresie sobie znanych operacji i zagadnień, bez wnikania w podstawy programowania, tworząc jednocześnie skrypt, który zwiększył jego efektywność i komfort pracy.
[Rys 3. Blender. Ręczna operacja translacji i zmiany operacji wywołuje automatyczny zapis tych operacji w ujęciu API Blendera (dwa dolne zapisy po jednym na operacje przesunięcia i obrotu)]
Przykłady skryptów wspierających grafikę 3D
Zakres wsparcia, który można określić mianem skryptowania, stanowi ciągle spektrum pod względem złożoności i zastosowań. Najprostsze przykłady skryptów to takie, które wykonują kilka operacji na budowanej grafice, czy też ingerują wyłącznie w wygląd samego interfejsu. Takie skrypty są najłatwiejsze do wykonania, często za pomocą samych recorderów macro lub podczas nauki, przy poznawaniu pojedynczych operacji API, lub składni języka programowania. Często są one ulepszeniem gotowych funkcjonalności programu (na przykład skrypty automatycznie kolapsujące modyfikatory) lub poprawiają ergonomię pracy (na przykład dodawanie do interfejsu przycisków z poleceniem, które natywnie nie znajduje się na przestrzeni roboczej programu). Już po krótkim czasie użytkowania programu, grafik szybko orientuje się, że niektóre czynności, które same w sobie nie zajmują dużo czasu, przy częstym wykonywaniu sumarycznie stają się uciążliwe i właśnie czasowo obciążające pracę. Prostym przykładem jest polecenie eksportu selekcji obiektów ze sceny. W przypadku 3ds Max, taki eksport dokonuje się przez dodatkową opcję rozwijaną w menu. W przypadku blendera to, dodatkowe odhaczenie opcji, również po wywołaniu okna z menu. W obu przypadkach prosty skrypt podłączony pod przycisk bezpośrednio znajdujący się na pulpicie programu czyni wielką różnicę. Takie najprostsze ulepszenia są jednocześnie najlepszym tematem do rozpoczęcia nauki skryptowania.
Nieco bardziej skomplikowane skrypty mogą wykonywać dłuższy szereg czynności lub grupę powiązanych ze sobą operacji. Często wymagają one stworzenia jakieś prostego interfejsu obsługującego żądane operacje. Interfejs taki składa się wtedy z zaprojektowanych przycisków, okien, opisów, i wszystkiego, co może stanowić elementy GUI. Skrypty takie uzupełniają luki funkcjonalności podstawowego programu (w tym przypadku wprowadzają nowe funkcjonalności) lub porządkują i ułatwiają dostęp do funkcjonalności już obecnych (w takim przypadku poprawiają jedynie ergonomię pracy). Przykładem takiego nieco bardziej zaawansowanego skryptu może być na przykład bardzo dobry skrypt do randomizacji vertex painting`u (Random Vertex Painter) w 3ds Max. Nadawanie losowych barw dla poligonów lub co ważniejsze — całych subobiektów mesh`u, wychodzi poza standardowe operacje 3ds Max. Operacja ta ma jednak duże znaczenia przy przetwarzaniu obiektów w silnikach graficznych. Materiały Unreal`a lub Unity mogą zawierać moduły rozpoznające vertex painting w geometrii 3D i na jego podstawie dodawać różne parametryczne cechy (dekoloryzacja, zmienność natężenia emissive itp.). Nadanie losowych kolorów złożonemu obiektowi 3D w programie graficznym staje się operacją trudną i czasochłonną w przypadku braku do tego celu natywnego narzędzia.
[Rys 4. 3ds Max. Skrypt (plugin) z własnym, rozbudowanym GUI do losowego przypisywania wartości barw obiektom 3D]
Skrypty do vertex paintingu (Blender posiada również swój odpowiednik) potrafią przy okazji wykonywać opcjonalne operacje na poszczególnych kanałach RGB (każdy oddzielny kanał to wbrew pozorom potencjalnie istotny nośnik informacji w materiale silnika graficznego) lub dowolnie obcinać zakresy nadawanym kolorom.
[Rys 5. Blender. Analogiczny do “Random Vertex Painting” Skrypt pozwalający na nadanie wartości barw (w tym losowych) obiektom 3D w Blenderze]
Innym przykładem skryptu, którego zastosowanie wychodzi poza funkcjonalność programu może być skrypt oczyszczający splainy (lub krawędzie poligonów) z werteksów nietworzących kątów różnych od zera. Jest to dość klasyczny problem przetwarzania geometrii importowanej z Open Street Map na potrzeby budowy scen z prawdziwą urbanistyką miejską. Taka surowa geometria zawiera niezliczoną ilość dodatkowych werteksów, które nie tworząc kątów, nie wnoszą żadnej informacji, a same przyczyniają się do znacznego wzrostu polycountu obiektu. Skrypt eliminujący je jest dość prostym zagadnieniem programistycznym (w teorii). Wystarczy przeiterować wszystkie werteksy, sprawdzić ich oba sąsiedztwa i ocenić kąt, jaki tworzą między sobą. Jeśli jest równy zeru (lub zbliżony do zera z zadanym parametrycznym progiem) wtedy zostaje eliminowany. To przykład dobrego połączenia myślenia programistycznego (iteracja, selekcja “if”) z potrzebą wykorzystania API (czytanie sceny, przegląd werteksów, ich usuwanie). Dodatkowo skrypt taki obramowany powinien być swoim interfejsem zawierającym przyciski go egzekwujące i okna dla wprowadzenia parametrów progów.
[Rys 6. 3ds Max. Bardzo prosty interfejs do użytecznego skryptu eliminującego nadmiarowe werteksy]
Przykładem dobrego skryptu, który dodaje nieco nowej funkcjonalności, ale przede wszystkim porządkuje już gotową, jest PolyUnwrapper (3ds Max). Jest to skrypt uruchamiający się po włączeniu edytora UnwrapUVW. Wyświetla swoje gui z dziesiątkami poukładanych ikon wykonujących praktycznie wszystkie możliwe do pomyślenia operacje na mapowaniach geometrii 3D. Korespondującym przykładem dla Blendera jest skrypt „UV Toolkit”. Jest o tyle praktycznym przykładem, że czynności związane z mapowaniem obiektowo 3D w Blenderze mają o wiele trudniejsze i mniej intuicyjnie rozwiązana niż analogiczne operacje w 3ds Max.
[Rys 7. 3ds Max. Przykład rozbudowanego i estetycznego GUI dla skryptu obsługującego cały szereg operacji mapujących obiekty 3D]
[Rys 8. Blender. Fragment gui do skryptu “UV Toolkit” pozwalającego na o wiele swobodniejsze mapowanie geometrii, niż zapewniają to natywne narzędzia Blendera]
Ciekawym przykładem może być skrypt Artisan do Sketchup`a. Narzędzie te, jest zdecydowanie najbardziej intuicyjnym pośród wszystkich programów 3D. Jest doskonały do rysunków technicznych i do architektury. Świetny do rozpoczęcia nauki i przygody ze światem modelowania 3D. Ma jednak jedną wadę — kompletnie nie nadaje się do tworzenia rysunków organicznych, które nie posiadają symetrii, ani regularnej geometrii. Skrypt Artisan wychodzi temu naprzeciw, pozwalając za pomocą operacji subdivision, wizualizacji normalnie niewidocznych w Sketchupie werteksów, czy za pomocą narzędzi „rzeźbiarskich” typowych dla modyfikowania grafiki organicznej, budować miękkie formy geometrii tego typuj. Jest to więc skrypt, który potrafi całkowicie przedefiniować użytkowość natywnego programu. Przykładów skryptów ja te powyżej można wymieniać najwięcej. Na nie właśnie jest największe zapotrzebowanie, i umiejętność ich tworzenia jest dla grafika 3D najlepszą trampoliną do podniesienia własnych kwalifikacji, wykraczających daleko poza standardowe umiejętności obsługi programu.
[Rys 9. Sketchup. Silnie oskryptowany interfejs Sketchupa. W tym GUI pochodzące od Aritsana, skryptu potrafiącego przedefiniować użytkowość Sketchupa wprowadzając do niego możliwość tworzenia geometrii miękkich]
Ostatnim rodzajem skryptów są te najbardziej skomplikowane. Duże kombajny zajmujące się wykonywaniem całych odrębnych procesów, często wręcz „na boku” w stosunku do podstawowej funkcjonalności programu. Skrypty takie zawierają nie tylko swoje własne interfejsy, ale również edytory, biblioteki, komunikują się z programami zewnętrznymi. Trudno właściwie mówić o nich ciągle jako o skryptach. Używa się dla nich najczęściej określenia plugin. Różnica pomiędzy skryptem, a pluginem jest dość rozmyta. Skrypt z definicji powinien wręcz pozostawać jedynie kodem, który jest uruchamiany przez interpreter programu graficznego. Jest czymś bardzo prostym w swojej formie. Plugin to coś, co często zawiera swój instalator, jest często programem już skompilowanym, posiada o wiele większą złożoność i szerszą funkcjonalność. Pomiędzy tymi dwiema skrajnościami istnieje najszersza sfera skryptów/pluginów, co do których można używać tych określeń zamiennie.
Przykładem bardzo skomplikowanego skryptu (właściwie to już stricte pluginu), może być Railclone firmy iToo Software. To skrypt do tworzenia geometrii opartej na powtarzalności. Railingi, specjalnie rozmieszczone obiekty, kondygnacje architektoniczne itp. Zwłaszcza kiedy takie rozmieszczenie potrzebuje być dodatkowo sparametryzowane o jakieś elementy przypadkowych transformacji lub dodatkowych struktur geometrycznych (na przykład rozprowadzanie elementów posiadających swoje definicje rozprowadzonych obiektów zagnieżdżonych). Railclone posiada swój własny edytor, w którym można za pomocą węzłów zdefiniować swoje własne pętle. Posiada również biblioteki, gdzie można zapisywać swoje lub pobierać zewnętrzne rozwiązania.
[Rys 10. 3ds Max. Interfejs edytora Railclona, jako przykład bardzo rozbudowanego skryptu posiadającego swoje wewnętrzne generatory o szerokich możliwościach parametryzacji]
Dobrym przykładem wysoce wyspecjalizowanego pluginu jest też RayFire produkcji RayFire Studios. Jest to plugin łączący cechy fizyki obsługiwanej przez 3ds Max z zagadnieniami fragmentacji obiektów, tworząc potężne narzędzie do tworzenia efektów typu destruction. Przykład o tyle interesujący, że napisany został przez praktycznie jedną osobę, a używany jest obecnie przez największe wytwórnie i produkcje zajmujące się animacjami komputerowymi. Chociaż sam w sobie zawiera bardzo ubogi jak na swoje możliwości interfejs i nieco topornie się go obsługuje, to efekty końcowe jakie mogą być przez niego wykonane, są wręcz spektakularne.
[Rys. 11. 3ds Max. Fragment spektakularnej animacji z użyciem efektów typu destruction, wykonanych przy pomocy skryptów RayFire]
Nauka skryptowania. W jaki sposób myśleć o zadaniach nadających się do oskryptowania
Są dwie szkoły uczenia się skryptowania. Pierwsza, to nauka na przykładach, często rozpoczynająca się od fundamentów typu „Hello World!”. Zaletą takiego podejścia jest fakt uczenia się od początku, czyli przy najniższym progu wejścia w świat programowania. Wadą jest to, że ćwiczenia i zadania na ogół wybiegają poza dość wąski krąg zainteresowania i specjalizacji się uczącego. Są więc niepraktyczne, oderwane od bieżących, często pilnych potrzeb. Minusem jest tutaj również zdecydowanie większy czas potrzebny na taką naukę.
Drugi rodzaj uczenia się polega na rzuceniu się w nieco głębsze wody i wkroczeniu bezpośrednio we własny obszar potrzeb i zadań. W takim przypadku zadania są jednocześnie rozwiązaniami bieżących przeszkód spotykanych w pracy. Ogromnym plusem jest to, iż nauka nie wykracza tutaj poza praktyczne zastosowania i aktualne potrzeby. Minusem jest o wiele wyższy próg wejścia. W takim przypadku, od razu wskakuje się na wyższy poziom, gdzie na przykład, trzeba dobrać materiał, który, mimo że realizuje swoje zadania — nie zawsze jest zrozumiały w swoich podstawach.
Przy takiej metodzie jest też o wiele trudniej z dostępem do dokumentacji. Zadania na starcie często są zbyt specjalistycznie określone. Złoty środek jak zawsze, leży pośrodku. Nie należy się porywać na złożone, trudne zadania. Nie powinno się również siadać do tutoriali podstawowych i tracić czas na realizację zadań niezwiązanych z pracą. Proste zadania przynosi sama praca. Na początek dobre są drobne rozwiązania optymalizujące pracę, poprawiające jej ergonomię, usuwające denerwujące niedogodności. Definiowanie prostych przycisków wykonujących pojedyncze, ale często powtarzane operacje to najlepszy początek. Na początek robienie tego za pomocą recorderów macro. Próbowanie stworzenia i podpięcia prostych GUI to kolejny krok. Blender posiada niezwykle przyjazne środowisko do tworzenia interfejsów, dodawania elementów do menu, pasków, przycisków i wszystkiego, wszędzie co tylko jest tam do pomyślenia.
Kolejnym krokiem jest stawianie sobie zadań, które można ująć w konkretne ramy programistyczne. Spróbować proste algorytmy przełożyć na język programowy i za pomocą API operować wynikami na scenie 3D.
Przykład. Zajmując się modelowaniem miast, wyobraź sobie zagadnienie budowy dachów dla obszarów rezydencjalnych, dla których istnieją obrysy podstaw wyciągnięte z eksportera Open Street Map. Wchodzi tutaj w grę problem masowego wykonania setek dachów dla dość przypadkowych kształtów ich płaskich podstaw. Zarówno w rzeczywistości, jak i w grafice komputerowej sprawdza się do tego algorytm tzw. Straight Skeleton. Jego postać matematyczną, a nawet semi-programistyczną można łatwo znaleźć w internecie.
[Rys 12. Przykład próby ujęcia w ramy szkicu obliczeń dla algorytmu Straight Skeleton”]
Czy łatwo jest go przełożyć na kod? Jak wpleść w to scenę 3D? Jakich funkcji API należy użyć? Jeśli poszukać głębiej, można znaleźć na to gotowy kod, na przykład w języku C++, a nawet w Pythonie, ale czy coś to ułatwia? Jak implementować gotowe bloki obcego kodu — zwłaszcza kiedy nie wszystkie jego elementy są zrozumiałe? Kiedy to wszystko już się uda, zabawa dopiero się zaczyna. Skoro są już poprawnie wygenerowane dachy dla setek podstaw, to czy nie sparametryzować ich niektórych cech? Wysokość dachów jako uwikłane parametry tempa schodzenia się brzegów i wzrostu osi wysokości. To daje większą kontrolę. Żeby było bardziej realistycznie, należałoby nadać przypadkowości dla takich parametrów. W grę wchodzą znowu generatory randomowych liczb i vertex painting, a to również wymaga dodatkowych skryptów. Co wtedy z kominami? Może stworzyć ich bibliotekę, z której by były brane i umieszczane na dachach? To dalsze, dodatkowe skrypty, elementy gui, dalsze zgłębianie się w API. Co to znaczy w ogóle umieścić kominy na dachach? Jak określić jego granice? Jakie przyjąć warunki brzegowe i marginesy, jakie wyjątki? To wszystko to tylko jeden przykład, na którego przykładzie, można by stworzyć skrypt nie tylko o szerokim zastosowaniu. Byłby to skrypt, który rozwiązałby wiele problemów ratując dziesiątki godzin grafikowi zajmującemu się budową takich scen. To również przykład skryptu, na który czekaliby inni użytkownicy na całym świecie, gotowi za niego również zapłacić, zyskując drogę do szybszej i efektywniejszej pracy.
Programowanie
Czy wobec tego wszystkiego nie trzeba się uczyć programowania w ogóle? Niestety nie. Do prostych skryptów zapisanych przy pomocy recorderów macro nie trzeba, ale jeśli tylko chce się skryptować w nieco głębszy sposób, należy poświęcić pewien czas również na zapoznanie się z elementami programowania. Ponieważ w zasadzie użytkownik graficznego softu obraca się tutaj głównie w obszarze API, nauka może wydawać się nawet trochę trudniejsza. To znaczy, jeśli przysiąść do opanowania składni jakiegoś języka programowania, już podczas używania API okazać się może, że poruszać się trzeba również po zupełnie nowych pojęciach niewystępujących w składni poznanego języka. O ile językiem programowania skryptów Blendera powinien być Python, o tyle na przykład 3ds Max posiada swój własny język MaxScript, którego znajomość składni poza tym programem jest bezużyteczna (od jakiegoś czasu można tutaj jednak pisać również w języku Python). Zagadnienie sprowadza się więc do pytania: w jakim stopniu właściwie trzeba umieć programować, by potrafić za pomocą na przykład Pythona powiązać ze sobą operatory API, by stworzyć skrypt? Na pewno warto znać jakiekolwiek podstawy programowania. Fundamenty pozwalające zrozumieć czym są iteracje, warunki, zmienne, funkcje i ich definiowanie, to wiedza bardzo uniwersalna. Można tego się nauczyć w bardzo przyjemny sposób na przykład za pomocą pewnego specyficznego zbioru gier. Dla tych, którzy wcześniej nie mieli zupełnie styczności z programowaniem, można polecić gry firmy „Tomorrow Corporation” z dwoma tytułami: „7 Billion Humans” oraz „Human Resource Machine”. Oba tytuły w zabawny sposób uczą struktury programowania. O wiele poważniejszymi tytułami są gry firmy Zachtronics. Wszystkie gry tej firmy są w zasadzie o programowaniu. Na czele wysuwają się jednak dwa tytuły „TIS-100” oraz „Shenzhen I/O”. W obu przypadkach, oprócz dochodzenia do rozwiązania, gracz spotyka się z realnymi problemami programistycznymi, które trzeba pokonać przy pomocy właściwej składni kodu. W prawdzie użyty do tego jest język niskiego poziomu — assembler (i to raczej w wersji pseudo), nie zmienia to faktu, że daje doskonały pogląd na proces pisania kodu i zasady programowania.
[Rys 13. Interfejs TIS-100. Gra z interfejsem w stylu retro. Operuje się w niej składnią pseudo-assemblera, bardzo zbliżoną do poleceń oryginalnego języka]
Po tych krokach należy przejść do nauki podstawowej składni konkretnego języka. Tutaj w przypadku skryptowania dla grafiki 3D prawie w każdym przypadku powinien to być Python. Najbardziej przystosowany do skryptowania program, jakim obecnie jest Blender, można powiedzieć, że jest programem zbudowanym na Pythonie. Po drugie, 3ds Max również posiada już support tego języka. Po trzecie — jest to coraz bardziej popularny i ceniony język programowania. Jego nauka w żadnym przypadku nie będzie stratą czasu. Wyjątkiem jest sytuacja, kiedy grafik chce pozostać w jakimś programie, którego konsola i API nie jest obsługiwana przez Pythona. Naturalnym językiem dla Sketchupa jest na przykład język Ruby, ale i tu można znaleźć jakieś Python’owe obejścia. Pytanie, jak bardzo, trzeba znać język programowania, pozostaje pytaniem otwartym. Nie wszystko w adaptowanych blokach kodów trzeba rozumieć. Nie cały kod, który wypluję recorder macro trzeba rozumieć. Wiele rzeczy pozostaje w gestii intuicji. Jeśli rozpozna się operator API, potrafiący odczytać ze sceny wymiary obiektów, to bardzo szybko będzie się potrafić odczytać ze sceny również inne parametry tych obiektów — ich pozycję, orientację, nazwę itp. Z drugiej strony, nigdy nie można powiedzieć, że programować potrafi się już wystarczająco dobrze. To zawsze zależy od postawionego sobie zadania do oskryptowania.