Svgtex to wtyczka (plugin) do Blendera, umożliwiająca użycie plików *.svg jako tekstur.
Svgtex w pełni wykorzystuje wektorowy zapis obrazu, jakim jest format SVG.
Umożliwia uzyskanie w Blenderze tekstur, które nawet w największym zbliżeniu nie tracą ostrości.
Kod źródłowy komponentu jest udostępniony na zasadach GPL. Obecna wersja — 1.0 — współpracuje poprawnie
z Blenderem od wersji 2.46 do wersji 2.49.
Do pobrania:
Skompilowany plik dla Win32
— wtyczka i program do podglądu (sprawdzania) obrazów SVG (0.4 MB, wyłącznie dla Windows, 32-bit);
Kod źródłowy
— opcjonalny: jeżeli chcesz sam komponent skompilować/coś w nim zmienić;
Jeżeli chcesz powtórzyć operacje pokazane poniżej, pobierz
przykładowy model (12 MB) — model P-40B, wraz z teksturami, używany w tym tekście;
Wtyczka to plik svgtex.dll. Znajdzesz go w spakowanym
pliku *.zip.
Zawartość rozpakuj i umieść w jakimś istotnym folderze (np. w katalogu plugins/texture Blendera).
Aby skorzystać z wtyczki, zmień najpierw typ tekstury
na Plugin (Fig. 1.1):
|
Fig. 1.1 Zmiana typu tekstury — z rastrowej (Image) na „wtyczkę” (Plugin) |
Spowoduje to zmianę układu paneli: znikną panele obrazu rastrowego, zastąpione przez panel o nazwie Plugin.
Początkowo znajduje się na niej tylko przycisk Load Plugin. Naciśnij go (Fig. 1.2):
|
Fig. 1.2 Początkowy układ paneli Plugin |
W oknie wyboru plików wskaż plik wtyczki: svgtex.dll. Koniecznie wyłącz ścieżki względne
(Relative Paths - por. Fig. 1.3). Gdy ta opcja jest włączona, Blender nie będzie w stanie go załadować!
|
Fig. 1.3 Wskazanie pliku wtyczki |
Jeżeli wtyczka załadowała się poprawnie, powinna wyświetlić w panelu Plugin dodatkowe kontrolki (Fig. 1.4):
|
Fig. 1.4 Załadowana wtyczka svgtex |
Konieczność wpisywania pełnych nazw ścieżek jest uciążliwa, gdy musisz przenieść plik Blendera na inny komputer.
Tam plik wtyczki może być w innym folderze, i trzeba parametry tekstur typu Plugin ustawiać od nowa.
Najwygodniej byłoby wpisywać w panelu Plugin tylko nazwę
pliku *.dll — i niech komputer go sam znajdzie! To, na szczęście, jest możliwe.
Wystarczy zebrać wszystkie wtyczki, z których korzystasz, w jedno miejsce (jeden katalog), a
następnie dopisać jego nazwę do zmiennej środowiskowej Path.
Zmienne środowiskowe przestawiasz w Windows następująco:
- Podświetl ikonę Mój Komputer i przejdź do jej Właściwości;
- W oknie dialogowym Właściwości systemu przejdź do zakładki Zaawansowane
i naciśnij umieszczony u dołu przycisk Zmienne środowiskowe
- W oknie dialogowym
Zmienne środowiskowe podświetl na liście Zmienne systemowe zmienną Path i
naciśnij przycisk Edytuj
- W oknie dialogowym Edytowanie zmiennej systemowej dopisz ścieżkę do folderu z wtyczkami Blendera
(np. u mnie to C:\Program Files\Blender\plugins\texture). Zwróć uwagę, że
separatorem poszczególnych ścieżek jest tu średnik! Nie zapomnij sprawdzić, czy
jest przed i za dopisaną przez Ciebie nazwą!
Gdy plik wtyczki znajduje się w jednym z folderów wyliczanych
przez Path, można mu w panelu Plugin usunać całą ścieżkę.
Na innym komputerze możesz wskazać w tej zmiennej środowiskowej inny katalog. Pliki
Blendera, w których wtyczki są wpisane tak, jak na Fig. 1.5, będą się poprawnie
renderować na każdej z tych maszyn.
|
Fig. 1.5 Wtyczka svgtex wskazana w sposób „niezależny od komputera” |
W pole File name wpisz ścieżkę do pliku SVG (w tym
przykładzie to plik decals.svg). Należy wpisywać ścieżki względne — względem
pliku *.blend, w którym aktualnie pracujesz. Zmień jeszcze tło na ciemnoszare, Alpha na 0,
i możesz już włączyć Enable. W panelu Preview pojawi się podgląd tekstury (Fig. 2.1):
|
Fig. 2.1 Przykład tekstury wektorowej - znaki rozpoznawcze i napisy eksploatacyjne samolotu |
Gdybyś pomylił się w nazwie pliku, lub coś poszło nie tak,
jak powinno, w podglądzie tekstury pojawi się jednolity, czerwony kolor. W
takim przypadku zajrzyj do tekstowej konsoli Blendera — powinien się tam
pojawić opis błędu, zgłoszonego przez svgtex (na przykład: „nie można znaleźć
pliku”).
Jak na razie, na podglądzie tekstury obraz wektorowy wygląda
identycznie jak rastrowy (por. Fig. 1.1). W przykładzie, który wykorzystujemy,
jest to tekstura ze znakami rozpoznawczymi i innymi emblematami, nakładana na
model samolotu. Jak w takim razie będzie się prezentować na renderze?
UWAGA: aby uzyskać z svgtex pełen efekt, musisz włączyć opcję OSA (ustawienia na panelu Render).
W przeciwnym razie zawartość pliku SVG zostanie nałożona na model w domyślnej, zazwyczaj bardzo niskiej rozdzielczości.
Fig. 2.2 pokazuje porównanie modeli ze znakami rozpoznawczymi naniesionymi za pomocą
tekstury wektorowej (a) i rastrowej (b). Tekstura rastrowa decals.png ma
rozmiary 2048x2048 pixeli:
|
Fig. 2.2 Porównanie tekstury wektorowej i rastrowej — model w „zwykłej” odległości od kamery |
Mówiąc szczerze, porównanie Fig. 2.2a) i Fig. 2.2b) wygląda
na łamigłówkę typu „znajdź wszystkie różnice”. Z trudem udało mi się
zidentyfikować te dwie, które pokazuję. Sądzę, że obydwie mają tę samą
przyczynę: svgtex stosuje prostsze filtry przybliżania pikseli, niż te, których
używa Blender do plików rastrowych. W każdym razie nie widać tu żadnych przewag
tekstury wektorowej nad rastrową.
Ale zbliżmy się teraz do jakiegoś fragmentu modelu — na
przykład łopaty śmigła (Fig. 2.3). Przypadek (a) pokazuje zbliżenie z teksturą
rastrową, a przypadek (b) — to samo ujęcie z teksturą wektorową. Przypadek (c)
to jeszcze bliższe ujęcie tekstury wektorowej. Można już wyraźnie odczytać
napis na łopacie, a nawet emblemat: Curtiss Electric Propellers!:
|
Fig. 2.3 Porównanie małych napisów w wersji rastrowej (decals.png) i wektorowej (decals.svg) |
Wniosek: tekstury wektorowe są przydatne tam, gdzie wykonujesz większe zbliżenia modelu.
Zasada działania svgtex nie jest jakąś szczególną tajemnicą.
Podczas renderowania Blender żąda od wtyczki podania barwy konkretnego teksela
(piksela tekstury). Svgtex, aby „udzielić odpowiedzi”, tworzy w pamięci
rastrowe fragmenty obrazu. Użyje ich także przy okazji następnych „pytań”
Blendera. Każdy z tych fragmentów ma rozmiar 256x256 pikseli — tak, by zajmował
w RAM nie więcej niż 1 MB. W ten sposób oryginalny obraz jest dzielony jak
szachownica, na kwadratowe, jednolite obszary. Svgtex przygotowuje i
przechowuje tylko takie „pola” tej szachownicy, których zażądał od niego
Blender. Dodatkowo, jeżeli całe takie „pole” jest zupełnie jednolite, zamiast 1
MB danych przechowywany jest pojedynczy, reprezentujący je piksel.
Svgtex tworzy fragmenty wielu różnych wersji obrazu,
różniących się rozdzielczością. Każda kolejna wersja ma czterokrotnie większą
liczbę pikseli od poprzedniej. Pierwsza wersja obrazu jest zawarta w
pojedynczym fragmencie, czyli „wpasowana” w obszar 256x256 pikseli. Następna ma
wymiary 512x512 pikseli, i składa się z 4 fragmentów. Kolejna wersja to obraz
1024x1024 pikseli (złożony z 16 fragmentów o rozmiarach 256x256). W grafice
komputerowej o takim szeregu obrazów mówi się, że są uporządkowane według
„poziomu szczegółowości” (Level of Details — LoD) . Poziom ten określa się jako
liczbę całkowitą. Na potrzeby Svgtex przypisałem LoD = 0 dla obrazu 256x256, LoD
= 1 dla 512x512, LoD = 2 dla 1024x1024, itd. W odpowiedzi na żądane Blendera
svgtex określa wymagany LoD obrazu, i zwraca piksel z jego odpowiedniej wersji.
Jeżeli żądany fragment jeszcze nie istnieje — jest w tym momencie generowany.
Wtyczkę svgtex pisałem przede wszystko z
myślą o własnych potrzebach. Jednak zdawałem sobie sprawę, że kiedyś udostępnię ją
innym użytkownikom. Poświęciłem więc trochę czasu na napisanie obsługi
większości elementów, występujących w formacie SVG. W efekcie komponent potrafi
narysować prawie wszystko, co przewiduje ten standard. Poniżej wyliczam to, co nie
zostało zaimplementowane:
- znaczniki (marker)— bo to sporo pracy, a nie miałem pomysłu, do czego mógłbym je wykorzystywać;
- filtry (filter) — obecnie obsługiwany jest tylko jeden typ: Gaussian blur.
W kodzie przygotowałem miejsce na pozostałe, ale nie były mi potrzebne;
- napisy (text) — brak obsługi wewnętrznych czcionek SVG. Svgtex
wykorzystuje obecnie wyłącznie czcionki True Type, więc w środowisku Windows
wszelkie napisy są wyświetlane poprawnie. W kodzie programu jest przygotowane
miejsce dla innych typów czcionek — np. FreeFont.
Nie implementowałem ich jednak, gdyż tworzę swoje modele w środowisku Windows;
- obrazy rastrowe (image) — wszelkie referencje do obrazów rastrowych
są ignorowane. Svgtex ma służyć do rysowania wektorowego; Oczywiście, wykorzystując bibliotekę AGG,
dodanie obsługi elementu do kodu nie nastręcza większych trudności
Oczywiście, odwieczna mądrość programistów mówi „w każdym programie zawsze jest jeszcze co
najmniej jeden nie wykryty błąd”. Komponent na razie był porównywany z
rezultatami, które zwracał Inkscape, oraz przeszedł test praktyczny na
rysunkach, które przygotowywałem dla moich modeli. Wydaje mi się, że udało mi
się wyeliminować przynajmniej większość jego błędów. W razie czego, udostępniam
kompletny
kod źródłowy.
Rodzaj i położenie kontrolek wtyczki svgtex w panelu Plugin
jest efektem wielu bolesnych kompromisów z ograniczeniami, jakie narzuca
struktura danych Blendera (zdefiniowana w plugin.h). Na przykład — pole na
nazwę pliku *.svg powinno być pierwszą kontrolką tej wtyczki. Niestety, okazuje
się, że można je „wepchnąć” wyłącznie pewnym, nie opisanym w dokumentacji
Blendera sposobem, i w dodatku tylko jako pole ostatnie (Fig. 4.1):
|
Fig. 4.1 Funkcje kontrolek wtyczki svgtex |
Poniżej podaję znaczenie wszystkich kontrolek, w tej kolejności, jak występują w paneli:
- Extend/Repeat/Clip: Przełącznik określający, co ma być przekazane do Blendera,
gdy współrzędne tekstury wykraczają poza granice obrazu.
(Analogiczny, nieco bardziej rozbudowany przełącznik jest także w teksturach opartych o obrazy rastrowe:
zobacz zestaw Shading:Texture buttons, panel Map Image).
Znaczenie poszczególnych alternatyw:
- Extend: na zewnątrz obrazu są powielone piksele z jego krawędzi;
- Repeat: obraz jest powielany w nieskończoność;
- Clip: poza obszarem obrazu nie jest nic rysowane (obraz jest absolutnie przejrzysty);
- Interpol (interpolation): Poziom wygładzania pikseli obrazu. Gdy Interpol = 0,
wykorzystywana jest wartość najbliższego piksela. W takim przypadku granice obrazów mogą być nieco „ziarniste”.
Dla wartości = 1, wykorzystywana jest średnia z 4 najbliższych pikseli, a dla wartości Interpol = 2 — z 16
sąsiednich. Poziom Interpol = 3 oznacza uśrednienie z 64 sąsiednich pikseli. Każde zwiększenie poziomu
interpolacji w sposób widoczny „rozmywa” ostre granice kolorów na teksturze. Wydłuża także czas obliczeń
(każdy kolejny poziom wymaga ich cztery razy więcej, niż poprzedni). Przypuszczam, że zazwyczaj będziesz używał
dla Interpol wartości = 1 lub 0;
-
Fid (fidelity): Poziom doboru rozdzielczości (LoD) obrazu.
Możliwe jest ustawienie od -5.0 do 0.0, przy czym wartość = 0.0 oznacza największą
dokładność. (Przy wartości = 0.0 wykorzystywane są wyłącznie piksele z obrazu o
LoD >= żądanego przez Blender.
Z takim ustawieniem komponent działa najszybciej). Każdy niższy poziom Fidelity
oznacza wyznaczenie piksela poprzez wyciagnięcie średniej z dwóch obrazów o
najbliższych poziomach szczegółowości (LoD). Na przykład, załóżmy że svgtex
określił dla konkretnego żądania Blendera optymalny LoD = 4 (obraz o rozdzielczości 4096x4096 pikseli).
Jeżeli Fid = -0.5, to zwracana Blenderowi wartość teksela jest w 50% wartością z obrazu o LoD = 4,
a w 50% — z obrazu o LoD = 3 (2048x2048). To przypadek klasycznej techniki „mipmapowania”.
Gdyby Fid = -0.2, wówczas zwracany Blenderowi teksel byłby średnią pochodzącą w 80% z pikseli
tekstury 4096x4096, i 20% tekstury 2048x2048. Gdyby Fid = -1.6, uśrednianie rozegrałoby się
pomiędzy pikselami z obrazu o rozdzielczości 2048x2048
(LoD = Max(LoD + Fid) = Max(4 - 1.6) = 3)
i 1024x1024 (LoD = Min(LoD + Fid) = Min(4 - 1.6) = 2).
W każdym razie używaj tego ustawienia z umiarem — dla map nierówności gdzieś pomiędzy 0.0 a -1.0.
Dla zwykłych tekstur barwy pozostaw Fid = 0.0;
-
barwa tła: Standardowy przybornik Blendera do wyboru barwy tła. Ta barwa jest
widoczna tylko wtedy, gdy oryginalny obraz *.svg miał tło przejrzyste.
Uwaga: dla rysunków na przejrzystym tle, takich jak oznaczenia samolotu, barwa tła delikatnie
wpływa na kontury znaków rozpoznawczych i innych emblematów, nawet gdy ustawisz Alpha na 0.0.
Stąd do mapowania decals.svg ustawiłem ją nie na czerń, a 40% szarość (Fig. 2.1).
-
Alpha: Dodatkowy parametr barwy tła. Określa poziom nieprzejrzystości.
Gdy Alpha = 0.0 tło jest zupełnie przejrzyste;
-
Df.LoD (Default Level of Details): po włączeniu Enabled, svgtex
wygeneruje wszystkie fragmenty obrazu o LoD <= DfLoD. Ustawiaj zazwyczaj na
poziomie 1-2, gdyż inaczej możesz za długo czekać na pojawienie się podglądu tekstury w panelu
Preview;
-
Force Df.LoD: Wymusza na svgtex wyłączne korzystanie z wersji obrazu o LoD = DfLoD.
Sugestie dotyczące rozdzielczości, dostarczane przez Blender, są ignorowane;
-
Mem Max: Maksymalna ilość RAM (w MB), jaką mogą zająć fragmenty obrazów,
zarządzanych przez svgtex. Dobieraj tą wartość uważnie, obserwując wartość umieszczonego obok
pola Used. Jeżeli ustawisz Mem Max na poziomie mniejszym od typowych wartości Used,
zmusisz wtyczkę do „porzucania” fragmentów, które jeszcze się jej przydadzą podczas tej samej
sesji renderingu. W takiej sytuacji może tylko, gdy nadejdzie żądanie Blendera, powtórnie
wygenerować obraz. To bardzo wydłuża czas renderingu;
-
Used: Pole wyłącznie informacyjne: aktualna ilość pamięci RAM, zajętej
przez fragmenty obrazów (w MB); Czasami może nieco przekroczyć wartość Mem Max —
o rozmiar pamięci, potrzebnej do przechowania zawartości pliku *.svg. Used
służy do wyrobienia sobie poglądu, jak powinno być ustawione Mem Max aby nie zajmować
za dużo RAM, a jednocześnie nie spowalniać niepotrzebnie procesu renderingu;
-
Enable: Uaktywnia teksturę (sprawia, że w Blenderze pojawia się jej obraz).
Możesz także użyć tego przełącznika do „zresetowania” pamięci, zajętej przez fragmenty
renderowanych obrazów;
-
File name: Ścieżka do pliku *.svg lub (co zostanie omówione później w tej sekcji) — *.xml;
To pole nie jest specjalnie długie — 63 znaki. Najlepiej wpisuj tam ścieżki względne
(względem aktualnego pliku Blendera). W ten sposób, gdy kiedyś przeniesiesz folder z całą
strukturą projektu w nowe miejsce, nie zaszkodzi to działaniu wtyczki
Po tym wyczerpującym opisie pozostaje dorzucić kilka rad
praktycznych:
Zaraz po załadowaniu wtyczki możesz podnieść limit Mem Max i wykonać pierwszy
rendering, by potem odczytać z pola Used, ile svgtex zużył pamięci.
Potem ustaw Mem Max na 110% wartości Used;
Dla tekstur oznaczeń i innych dokładnych rysunków, stosuj Interpol = 0 lub 1 i Fid = 0.0;
Dla tekstur nierówności stosuj Interpol = 1 i Fid = -0.5, by zaokrąglenia i
załamania granic paneli były bardziej płynne;
„Ubocznym produktem” prac nad svgtex jest prosta przeglądarka plików *.svg.
Znajdziesz ją w tym samym folderze, co plik svgtex.dll. To w istocie testowy program
z biblioteki AGG, w którym sprawdzałem działanie parsera obrazu. Możesz używać svgview.exe
do sprawdzenia, jak svgtex wyświetli konkretny obraz. Wystarczy wywołać ten program w linii
poleceń, podając jako argument nazwę pliku *.svg (Fig 5.1):
|
Fig. 5.1 Obsługa programu svgview.exe |
Powiększenie obrazu możesz w svgview.exe zmieniać za pomocą suwaka Scale,
umieszczonego u góry ekranu. Do przesuwania obrazu służy myszka — wystarczy ją przesunąć z
wciśniętym lewym przyciskiem. Przy każdej zmianie skali lub przesunięciu obraz jest rysowany na
nowo. Liczby u góry ekranu (Fig. 5.1) podają, ile wierzchołków napotkano, i ile trwało
przerysowanie obrazu.
Zwróć uwagę na ogromną liczbę wierzchołków pokazaną na ilustracji — niemal 2 miliony (Fig. 5.1).
To mój „stress test”: plik skin.svg,
zawierający wszystkie szczegóły nierówności poszycia modelu samolotu.
Narysowanie zawartości tego pliku
wymaga od interpretera SVG sporego wysiłku, głównie z powodu sposobu odwzorowania nitów.
Każdy rząd nitów to jest w nim jeden tekst, a każdy nit to pojedynczy znak tekstu (kropka).
(Nity są na tyle małe i „blade”, że na Fig. 5.1 ich nie widać. Otwórz jednak sam ten
obraz pod svgview.exe i zwiększ skalę, a je zobaczysz — małe, ciemniejsze kółka).
Prawie wszystkie (95%) wierzchołki spośród naliczonych przez program 1 983 458 należą do nitów
(każde „kółko” ma ich po 32).
Tak duża ilość tekstu — 50 tysięcy znaków — zaczyna być dla przeglądarek SVG wyzwaniem.
Gdy go tworzyłem (w Inkscape), miałem problemy z szybkością tego edytora. Zacząłem więc mierzyć
czas przerysowania całego pliku skin.svg przez interpretery SVG, które miałem pod ręką: Inkscape,
Firefox, i mój svgview. Fig. 5.2 przedstawia rezultaty, uzyskane ma moim laptopie (Dell Latitude 610 -
Intel Centrino 1.6 MHz, 1 GB RAM, Windows XP):
Interpreter SVG
|
Czas narysowania (s)
|
Zajęty RAM (MB)
|
Inkscape 0.49
|
45.0
|
398
|
Sketsa Editor 6.3
|
od 2.0 do 20.0
|
350
|
Firefox 3.5
|
12.0
|
27
|
svgview.exe
|
1.5
|
2
|
Fig. 5.2 Czas i pamięć, użyte do przerysowywania pliku skin.svg |
Jak widać, svgview.exe potrzebuje na zaledwie 1.4 sekundy i 2 MB RAM na to, co w Inkscape zajmuje 45s i 400 MB RAM!
Przy czym zapewniam, że w kodzie mojego parsera SVG można dokonać jeszcze wielu prostych optymalizacji,
a sam program jest był skompilowany w pochodzącym z 1998r MS VC 6.0. Co prawda Inkscape
jest edytorem, więc dane SVG musi przechowywać i przetwarzać w trochę inny sposób.
Ale popatrz na inn edytor: Sketsa. Tam ktoś wraźnie intensywnie optymalizował przerysowywanie.
Przy powiększeniach poniżej 100% przerysowywanie jest rzedu 2s, a przy powiększeniach powyżej 100%
- od 5 do 20s. Sądzę że rozrzutność wykorzystania zasobów komputera przez Inkscape może być przejawem
jakiegoś grubego błędu w architekturze programu.
Inna rzecz, że Sketsa ma uboższą od Inkscape funkcjonalność. Co więcej, pokazuje biały ekran
przy próbie powiększenia skin.svg do 400% i zawiesza się przy próbie selekcji jakiegokolwiek elementu
z tego rysunku. Nie polecam tego programu, tym bardziej że jest płatny.
Nie spodziewałem się takiej wydajności po moim kodzie, choć AGG,
którą wykorzystują svgtex i svgview, jest ładną biblioteką szablonów C++. Być może to właśnie
te szablony umożliwiają kompilatorowi daleko posuniętą optymalizację poprzez zastąpienie wywołań wielu metod
przez "płaski" kod wynikowy? Ale efekt wyszedł całkiem interesujący!
Dodatkową kontrolę nad
svgtex możesz uzyskać, podstawiając w polu
File Name
zamiast pliku
*.svg specjalne, krótkie pliki
*.xml.
Nazwałem je
skrótami XML, gdyż m.in. pozwalają wskazać plik lub pliki SVG, z których
ma powstać tekstura. To zaawansowana funkcjonalność, z której nie musisz korzystać, jeżeli nie
znasz (i nie zamierzasz poznać) podstaw składni XML. Jeżeli jednak masz ochotę spróbować —
przejdź do
opisu skrótów XML.