• Welcome to Forum graficzne Burning-Brushes.pl. Please log in or sign up.
 

Bardziej zaawansowane podstawy POV-Raya

Zaczęty przez Abik, Grudzień 21, 2011, 00:18:02

Poprzedni wątek - Następny wątek
Siema, to już przedostatni tutorial z tego co mam zaplanowane dla was na temat POV-Raya (albo ostatni jak coś pójdzie nie tak :P), więc ku waszemu szczęściu już niedługo przestanę was tym ustrojstwem męczyć.
Czym zajmiemy się w tym tutorialu? Niczym szczególnym tak naprawdę. Będzie to kontynuacja tego czego można było się nauczyć z tutoriala o podstawach POV-Raya. Całość będzie mieć formę pewnych tricków, ciekawych gadżetów i innych bajerów jakie możemy w povku wykorzystać, które są przydatne i ważne, a o których jeszcze nie pisałem.
Tyle słowem wstępu, zacznijmy.

1.Powtórka
Zaczynamy od małej powtórki. Tu zebrane są wszystkie konstrukcje jakie trzeba by znać przed przystąpieniem do tego tutka (chociaż aż tak bardzo konieczne to to nie nie jest). Jeśli coś z tej powtórki jest dla was niejasne, to dokładne objaśnienia znajdziecie we wcześniejszych tutorialach.

Ustawienie kamery:
camera{location<x,y,z> look_at<x,y,z>}

Ustawienie światła:
light_source{<x,y,z> color KOLOR}
gdzie jako KOLOR możemy podać nazwę (po załączeniu colors.inc) lub wygenerowany kolor przez funkcję rgb:
rgb<r,g,b>
r,g,b przyjmują wartości od 0 do 1.

Ustawienie koloru tła:
background{color KOLOR}

Nadawnie koloru obiektom:
pigment{color KOLOR}

Utworzenie kuli:
sphere{<x,y,z>, r}

Walec:
cylinder{<x1,y1,z1>,<x2,y2,z2>,r}
Przy okazji walca, fajny bajer! Walec (i stożek też przy okazji) możemy zrobić ,,otwarty" czyli hmmm bez ,,wieczka". O co chodzi? O to:

W kodzie jest to śmiesznie proste i jedyne co tu istotne to magiczne słówko open w deklaracji walca:
#include "colors.inc"
camera{ location <0,0,-10> look_at<0,0,0>}
light_source{ <10,20,-10> color White }                                                           
plane{y, -1 pigment{color White}}     
cylinder{<0,0,0>,<1,1,-2>,1.3 open pigment{color Green}}

Zapamiętajcie sobie to bo nigdy nie wiecie kiedy wam się może przydać.

Stożek:
cone{<x1,y1,z1>,r1,<x2,y2,z2>,r2}

Prostopadłościan:
box{<x1,y1,z1>,<x2,y2,z2>}

Torus:
torus{r1, r2}

Płaszczyzna:
plane{nazwa_osi, przesunięcie}

Wpisywanie tekstu:
text{ttf ,,nazwa_czcionki.ttf", ,,Co_ma_byc_napisane", głębokość, przesunięcie}

Ustawianie wbudowanych tekstur:
texture{nazwa_tekstury}

Ustawienie własnych tekstur:
pigment{image_map{typ ,,plik.typ"}}

Ustawienie błyszczenia i odbijania światła:
finish{reflection A phong B}

Skalowanie, rotacja, przesunięcie:
scale<x,y,z>
rotate<x,y,z>
translate<x,y,z>


Suma obiektów, różnica i część wspólna:
union{ obiektA obietkB}
difference{obietkA obiektB}
intersection{obiektA obiektB}


To chyba wszystko. Pamiętajcie o tym koniecznie!

2.Figury geometryczne
Po pierwsze, do testowania figur geometrycznych jako szablon będę korzystać z takiego kodu:
#include "colors.inc"
camera{ location <0,0,-10> look_at<0,0,0>}
light_source{ <10,20,-10> color White }         
background{color White}

Ale najpierw pytanie, po co nam płaskie obiekty w trójwymiarowym świecie? Ja nie wiem, mnie nie pytajcie, ale jestem pewien, że znajdzie się dla nich zastosowanie, można z nich ułożyć puzzle czy coś.
Pierwsza figura jaką poznamy to trójkąt. Jego kod jest bardzo prosty:
triangle{<x1,y1,z1>,<x2,y2,z2>,<x3,y3,z3>}
Czujecie o co chodzi? Opisujemy po prostu pozycję każdego z trzech wierzchołków trójkąta, sprawa zdaje się być dość prosta, wprowadźmy więc jakieś wartości i zobaczymy czy to działa:
triangle{<0,0,0>,<0,5,0>,<3,0,0> pigment{color Green}}
Pierwszy punkt mamy gdzieś w środku, drugi pięć jednostek wyżej, a trzeci 3 w prawo od środka. Wygląda to tak:

Ekstra mamy trójkąt. Zróbmy sobie hmmm.... nazwijmy to dysk. Tak to się nazywa w POV-Rayu, bo nie będzie to tak do końca koło, będzie mieć jedną fajną opcję. W każdym razie wzór na dysk jest taki:
disc{<x,y,z>,<x2,y2,z,2>,r,r2}
To wymaga trochę wyjaśnienia. X,y,z to współrzędne środka naszego dysku. X2,y2,z2 to współrzędne punktu, że tak powiem.. do którego nasz dysk jest prostopadły. Chodzi o to, że nasz dysk po prostu ,,patrzy się" na ten właśnie punkt, obraca się powierzchnią w jego stronę. R to promień dysku, a r2 to promień pustego środka, który może zostać wycięty – i to właśnie różni nasz dysk od koła. Przykładowy dysk:
[code]disc{<0,0,0>,<0,0,-1>,3,1 pigment{color Red}} 


Jeszcze jedna figura jaką poznamy to nasz język polski chyba wielokąt. To jest taka figura, która może mieć bardzo wiele boków, zgięć i innych bajerów, zależy to tylko od nas. Składnia polecenia do tworzenia wielokątów:
polygon{a, <x,y,z> powtórzone a-razy}
Co oznacza ten zapis? No najpierw podajemy liczbę punktów, które będą szkieletem naszego wielokąta, a następnie podajemy ich współrzędne, POV-Ray za nas łączy kropeczki i koloruje nie wychodząc za linie. Spójrzcie na przykład:
[code]polygon{5, <0,0,0>, <0,2,0>, <1,3,0>, <3,1,0>, <1,-1,0> pigment{color Blue}}


Nie wiem czy zauważyliście, ale podając kolejne punkty edytujemy tylko ich składowe x i y. Dlaczego? A no bo wielokąt to figura płaska, dwuwymiarowa, dlatego trzeba ją tworzyć tak aby zmieściła się w jakiejś jednej płaszczyźnie, pamiętajcie o tym, albo nie... lepiej zapomnijcie o wielokątach i wszystkich innych figurach geometrycznych, w końcu bawimy się grafiką 3D.

3.Turbulencje zamiast tekstur
Może ktoś pamięta, w tutorialu o bałwanie i bombkach było trochę na temat powierzchni obiektów. Najbardziej niezbędne rzeczy już w tym temacie wiemy, ale teraz zajmiemy się czymś niezwykle ciekawym, niekoniecznie praktycznym, ale na pewno ciekawym. Poznana tam funkcja finish pozwalała na zwiększenie odbijania światła na przykład, ale możemy użyć jej trochę w inny sposób w połączeniu z funkcją irid. Irid ma następującą składnię:
irid{A thickness B turbulence C}
Parametr A ustala jak bardzo będą widoczne na powierzchni obiektu wszelkie efekty generowane przez irid. Thickness (B) i turbulence (C) pozwalają nam na opisanie jak chcemy aby te efekty wyglądały. No ale ja tu sobie gadam, a wy nie bardzo wiecie o co chodzi, więc może przykład:

#include "colors.inc"
camera{ location <0,0,-10> look_at<0,0,0>}
light_source{ <10,20,-10> color White }                                                             
plane{y, -1 pigment{color White}}     

sphere{<0,0,0>, 1 pigment{color Red} finish{irid{1 thickness 0.5 turbulence 0.5}}}

Teraz wiecie o co chodzi? Nie wiem jak to nazwać, ale są to pewnego rodzaju abstrakcyjne zaburzenia :D
Thickness zmniejsza lub zwiększa grubość poszczególnych ,,zaburzeń", spójrzcie:

Turbulence niby oznacza jak bardzo zmienne mają być te nasze zaburzenia, w praktyce działa podobnie jak thickness, najlepiej jak sami się pobawicie różnymi opcjami parametrów bo kombinacji jest sporo.

4.Superelipsoida, bryły obrotowe i bloby!
To chyba najfajniejsza część tutka. Rozszerzy nasze umiejętności modelarskie. Zaczniemy od fajnej zabawki – superelipsoidy. Składnia
superellipsoid{<a,b>}
Prawda, że prosta? Bryła ta jest trochę specyficzna... delikatnie mówiąc. Pod pewnym względem przypomina torusa bo nie możemy podać jej współrzędnych, więc jeśli chcemy ją przemieścić to koniecznie poleceniem translate! Ale na tym podobieństwa się kończą. Oba parametry superelipsoidy opisują to jak bardzo będzie ona przypominać kulę albo sześcian. Zero jest bliższe sześcianowi, jedynka bliższa kuli. Przy czym zmiana każdego z nich powoduje zmianę w nieco inny sposób, trudny do opisania jeśli nie jest się pro, a ja nie jestem. W każdym razie zobaczcie sami najpierw jeden malutki przykładzik:
#include "colors.inc"
camera{ location <0,5,-10> look_at<0,0,0>}
light_source{ <10,20,-10> color White }                                                     
plane{y, -1 pigment{color White}}     
superellipsoid{<0.3,0.1> pigment{color Red}}


Teraz czaicie mniej więcej o co mi chodziło? Jesteśmy blisko zera i mamy coś co mocno przypomina sześcian, ale jest trochę pozaokrąglane.
Popatrzcie na różne kombinacje wartości:

Szalona bryłka, ciekawe formy przybiera, lubię się nią bawić.
Inną formą bryły w POV-Rayu, o której wam nie mówiłem są jeszcze bryły obrotowe. To jest też ciekawe ustrojstwo. Działa trochę podobnie do figur geometrycznych. Opisujemy kolejne wierzchołki pewnej prostej łamanej, povek łączy te wierzchołki, obraca prostą tak jakby dookoła wokół pewnej osi i tworzy z tego bryłę, dobre nie? : >
Składania brył obrotowych jest różna zależnie od tego jakie wybierzemy polecenie, zajmijmy się najpierw poleceniem lathe.
lathe{sposób_łączenia a, <x,y> a-razy}
Widzicie? Podobna sytuacja jak przy wielokącie – musimy podać ile będzie ,,zgięć". Sposób łączenia to metoda jaka zostanie użyta do wygenerowania linii łączących kolejne wierzchołki, do wyboru mamy linear_spline, cubic_spline, quadratic_spline, czyli tak najprościej jak się da ostry, łagodny i trochę mniej łagodny.
Żeby nie owijać szczególnie długo w bawełnę to pokażę wam kod tej samej bryły dla tych 3 różnych połączeń i zczaicie szybko o co chodzi, o to kod (zmieniają się tylko typy łączeń dlatego pokazuję go raz, ale pamiętajcie o nich):
#include "colors.inc"
camera{ location <0,5,-10> look_at<0,0,0>}
light_source{ <10,20,-10> color White }                                                           
plane{y, -1 pigment{color White}}     

lathe{linear_spline 4, <0,0>,<1,1>,<1,2>,<2,3> pigment{color Green}}


Jak widać, zmieniając jedynie (albo aż) sposób łączenia naszych punktów powstają mocno różniące się bryły, warto o tym pamiętać gdybyśmy chcieli używać brył obrotowych, a jeśli mamy zamiar coś porzeźbić to raczej ich nie unikniemy bo są ekstremalnie przydatne.
No ale jest jeszcze druga instrukcja tworząca bryły obrotowe:
sor{a, <x,y> a-razy}
Jak widać prostsza w konstrukcji od lathe. Zróbmy sobie identyczną bryłkę jak w przypadku lathe, o tak:
sor{4, <0,0>,<1,1>,<1,2>,<2,3> pigment{color Green}}

Widać wyraźnie, że mocno przypomina w efekcie cubic_spline. Sor ma pewne istotne zastrzeżenie – każdy kolejny parametr y musi być większy od poprzedniego. Szczerze powiedziawszy nigdy nie zagłębiałem się w to czym sor i lathe dokładnie się różnią i nie korzystałem z sor, więc więcej w tej kwestii wam nie powiem niestety (albo i stety bo jeszcze parę ciekawych rzeczy przed nami : >).
Teraz zajmiemy się czymś totalnie magicznym.
Będziemy robić bloby! Blob z angielskiego oznacza kropelkę, albo plamę, ale nam znacznie bardziej pasuje słowo kropelka. Nie powiem wam do czego służy blob, zobaczcie sami:

Cudowne :D
Teraz chyba widać, po co jest blob, łączy nam dwie kule (tak, kule) w jedną bryłę, w płynny bardzo sposób. Kod powyższego obrazka:
blob{
threshold 0.5
sphere{<-1.2,0,0> 2,1 pigment{color Red}}
sphere{<1.2,0,0> 2,1 pigment{color Red}}
}

Polecenie blob ma po pierwsze jeden parametr – threshold, który mówi nam jak silny ma być blob. Przy czym siła bloba jest niepojęta! Przy ustawieniu tej wartości na 1 kulki mogą nawet zniknąć, ale dla przykładu spójrzcie na różne wartości threshold:

To jest trochę pic, że blob ma jeden parametr, jak ktoś jest bystry to zauważy, że nasze kule w blobie są trochę dziwne i mają po promieniu wpisaną jeszcze jedną wartość. Ta wartość to płynność  naszego bloba, od niej też sporo zależy i może jakbyśmy ją zmniejszyli to dla threshold równego 1 kule by nie zniknęły :D Wizualnie zmniejszanie płynności daje podobne efekty jak zwiększanie siły, zachęcam do kombinowania bo bloby są naprawdę niezłe, niekoniecznie aż tak przydatne jak bryły obrotowe, ale na pewno nie mniej czarodziejskie.

5.Elementy programistyczne
To będzie dość mocno teoretyczne bo nie jest zbyt ciekawe dla zwykłych śmiertelników, a i ja w POV-Rayu z wykorzystaniem konstrukcji programistycznych nie ma zbytnio doświadczenia, ale jest parę rzeczy, które z tej części warto poznać i zapamiętać.
Po pierwsze zmienne. One pozwalają nam zapisać coś na stałe i przypisać temu czemuś nazwę. W povku to wygląda następująco:
#declare zmienna = 1;
Do nazwy ,,zmienna" przypisaliśmy jedynkę. Po co? Trochę bez sensownie, ale dla przykładu, możemy tej zmiennej użyć teraz w naszym kodzie np. tak:
sphere{<zmienna, zmienna, zmienna>, zmienna pigment{color <zmienna,zmienna,zmienna>}}
Wygląda to co najmniej dziwnie, ale można przetłumaczyć na coś dokładnie takiego:
sphere{<1,1,1>,1 pigment{color rgb<1,1,1>}}
A to jest już dla nas jasne i oczywiste – stworzenie kuli o promieniu 1, o środku w punkcie 1,1,1 i kolorze białym.
Do takiego banalnego zastosowania zmienne nie są jakoś szczególnie przydatne. Bardziej przydają się w połączeniu z innymi konstrukcjami programistycznymi. Na przykład instrukcjami warunkowymi. Można sobie napisać coś takiego:
#declare zmienna = 1;
#if(zmienna =1 )
sphere{<zmienna, zmienna, zmienna>, zmienna pigment{color rgb<zmienna, 0 , 0>}}
#else
sphere{<0,0,0>,2 pigment{color rgb<0,0,1>}}
#end

Ale o co chodzi!? Otóż, po zapisie if, w nawiasie sprawdzamy czy zmienna ma wartość 1, prosta sprawa... porównujemy wartość naszej zmiennej z jedynką. Jeśli są równe, no to wykonuje się pierwsza instrukcja sphere... w przeciwnym wypadku (po angielsku else) wykona się ta druga. Po prostu napisaliśmy coś co będzie wyglądało różnie, zależnie od tego jaką wartość przyjmie zmienna. Spróbujcie sami zmienić jej wartość na cokolwiek innego niż 1 i zobaczycie, że w efekcie dostaniecie inną kulę. Możemy też sprawdzać czy zmienna jest różna ( zmienna != 1 ),  mniejsza ( zmienna < 1), większa (zmienna > 1), mniejsza lub równa ( zmienna<= 1)  i większa lub równa ( zmienna >= 1). Oczywiście możemy porównywać zmienne do czegokolwiek, nie tylko do jedynki, ba, możemy nawet porównywać różne zmienne, nie koniecznie stałe liczby.
W każdym razie do niczego nam się to w sumie nie przydaje skoro i tak wiemy jakie wartości mają zmienne... no bo skoro wiemy jakie mają wartości to wiemy też, jakie wartości są większe albo mniejsze, to po co te konstrukcja warunkowe? Otóż, możemy ich używać w połączeniu z jeszcze innymi programistycznymi konstrukcjami, np. pętlami.
Pętle są ekstra, wszyscy programiści kochają pętle, do czasu aż się nie wieszają (na nich). Co robi pętla? Nie wiem czy jest sens to tłumaczyć bo jak znam życie to i tak nikt nie zrozumie, ale spróbujmy :D
Pętla sprawdza, czy jakiś warunek jest prawdziwy, dokładnie tak samo jak if, ale wykonuje jakiś kod tyle razy ile sprawdzenie warunku daje prawdę.
Ktoś pomyśli, że to przecież do bani. W naszym przypadku, gdy sprawdzaliśmy czy zmienna ma wartość 1 (a miała), pętla powinna działać w nieskończoność bo zmienna nigdy się nie zmieniła w naszym kodzie. No i ten ktoś ma rację. ALE ... możemy zmienną zmienić jak sama nazwa wskazuje i np. w każdym wykonaniu się pętli zwiększyć wartość zmiennej. Po co zwiększać zmienną? No np. możemy w pętli dać warunek, że ma się wykonywać tak długo, aż zmienna ma wartość MNIEJSZĄ niż 10... wtedy w każdym to się nazywa ,,obrocie" pętli (czyli za każdym razem gdy warunek jest prawdziwy) możemy zwiększyć zmienną o 1, dzięki temu pętla wykona się tylko 9 razy. Nie wiem czy czaicie, więc to rozpiszmy sobie.
Na początku zmienna ma wartość 1.
Pętla sprawdza warunek (czy zmienna jest mniejsza od 10). Jest! Czyli wykonuje wskazany kod, na końcu którego zwiększamy zmienną o 1. Czyli teraz zmienna ma wartość 2.
Po skończeniu tego kodu, sprawdzamy jeszcze raz warunek. Czy 2 jest mniejsze od 10? No jest, czyli kod wykonujemy znowu, no i znowu na końcu zwiększamy zmienną o 1. Teraz ma wartość 3.
Raz jeszcze pętla sprawdza warunek, czy zmienna (o wartości 3) jest mniejsza od 10? Jest! Wykonujemy kod, zwiększamy zmienną o 1 (teraz już mamy 4). Sprawdzamy warunek – 4 jest mniejsze od 10, więc wykonujemy kod, na końcu którego zwiększamy wartość pętli o 1 (ma wartość 5 teraz). Sprawdzamy warunek, 5 jest mniejsze od 10, więc jedziemy znów.... wykonujemy kod, zmienną zwiększamy o 1 (6)... sprawdzamy warunek, jest ok.... wykonujemy kod, zwiększamy zmienną o 1 (7) ... warunek znów ok.... wykonujemy kod, zwiększamy zmienną o 1 (wartość 8).... sprawdzamy warunek, jest ok... wykonujemy kod, zwiększamy wartość zmiennej o 1 (9)... sprawdzamy warunek, jest ok... wykonujemy kod, zwiększamy zmienną o 1 (ma wartość 10)... sprawdzamy warunek, STOP, 10 nie jest mniejsze od 10, więc kod już się więcej razy nie wykona.
Strasznie to głupie i niewygodne jak się rozpisuje samemu, ale po to właśnie są komputery, no i uwierzcie, że wszystkie programy, których używacie w pętlach tego typu spędzaj jakieś 99% swojego czasu. W POV-Rayu pętle przydają się do automatyzacji pewnych czynności. Ale jak w sumie wiemy już (albo nie wiecie jak nie zrozumieliście :P ) jak działają pętle, ale mają jakieś sensowne zastosowanie? Ja ich nigdy sensownie nie zastosowałem, ale można ich używać do ogromnej ilości celów. Spójrzcie np. na to:
#declare zmienna = 1;
#while(zmienna<10)
        sphere{<zmienna,0,0>,1 pigment{color<1,0,0>}}
        #declare zmienna = zmienna+1;
#end

To jest formalny POV-Ray'owy zapis tego co przed chwilą sobie powiedzieliśmy. Jako nasz kod mamy tutaj stworzenie nowej kuli o pozycji x zależnej od zmiennej, co znaczy, że nasza pozycja będzie się zmieniać. W efekcie:

Przykład banalny czy wręcz głupkowaty, ale dobrze ukazuje jak pętle mogą nam uprościć życie. W połączeniu z instrukcjami warunkowymi dają ogromne możliwości generowania elementów w scenach.
No, ale jako, że nie każdy musi lubić i rozumieć programowanie, niekoniecznie musi uważać takie gadżety za fajowe. Ale jest jeden, który spodoba się każdemu. W zasadzie już go znamy – declare. Ale użyty wraz z obiektami, o tak:
#declare obiekt = sphere{<0,0,0>,1};
Po co to? Teraz możemy używać nazwy obiekt do tworzenia obiektów! Co więcej! Możemy ją edytować! O np. tak:
object{ obiekt pigment{color <1,0,0>} }
Czyż nie jest to mega ułatwiające całą sprawę? Oczywiście, że jest, dlatego warto o tym pamiętać i używać!

To by było na tyle na dziś, chciałem napisać jeszcze o dwóch rzeczach, ale o nich już praktycznie nic nie wiem, więc wolę was nie wprowadzać w ewentualne błędy, chociaż jest duża szansa, że już to zrobiłem, tak czy siak, myślę, że ten tutek pokazuje sporo ciekawych trików i wykonywanie go daje niemało radochy :D
Pozdrawiam i jeszcze raz wesołych świąt!

TUTORIAL WYKONANY TYLKO I WYŁĄCZNIE DLA BURNING-BRUSHES.PL