grafika 3d
34
lipiec 2004
Wspaniały świat
POV-Raya
Krzysztof Garus
T
en artykuł pokazuje, czym jest
POV-Ray – jeden z bardziej
znanych programów do two-
rzenia grafiki trójwymiaro-
wej metodą śledzenia promieni (ang. ray
tracing). Jest to ciekawa propozycja dla
tych, którzy mają dużo czasu, lubią pracę
twórczą i mają odrobinę wyobraźni.
Praca z POV-Rayem przypomi-
na programowanie: opisujemy w spe-
cjalnym języku świat, który ma
zostać pokazany, a następnie odpa-
lamy program, który czyta zapisany
w pliku opis, wykonuje ray tracing
i “wypluwa” grafikę. Na samo hasło
"specjalny język" wiele osób krzywi się.
Nic dziwnego – wiele rzeczy można
zrobić szybciej i lepiej w takich pro-
gramach, jak Blender, gdzie widać na
bieżąco to, co się tworzy. Bawiąc się
programem POV-Ray (pomijam stosowa-
nie Kpovmodeller, o którym później),
używa się wyobraźni i papieru w kratkę.
Podstawy
Cały świat, który widzimy (zwany sceną),
składa się z takich elementów, jak obiekty,
światła, kamera (określa, jak i skąd na coś
patrzymy) oraz efekty atmosferyczne.
Zajmijmy się obiektami. W wielu
innych programach są one zbudowane po
prostu z wielu trójkącików. POV-Ray jest
bardziej wyrafinowany – może korzystać
z prawdziwych brył geometrycznych.
Obiekt posiada przede wszystkim
kształt. Aby go stworzyć, mamy do dyspo-
zycji podstawowe bryły (ang. primitives),
takie jak kula, torus, płaszczyzna itd.
oraz zestaw operacji CSG, które można
na nich wykonywać. Te operacje to:
łączenie (union), scalenie (merge), część
wspólna (intersection) oraz odejmowanie
(difference).
Przykładowo, nasz ołówek (Listing 1
i Rysunek 1) to cylinder, od którego odjęto
duże sfery (każda sfera na jedno "stru-
gnięcie"). Jeśli chcemy mieć ołówek "kan-
ciaty", odejmujemy od niego kilka płasz-
czyzn. To jest najczęstsze wykorzysta-
nie prymitywów nieograniczonych typu
plane (płaszczyzna) czy poly (powierzch-
nia określona wielomianem n-tego stop-
nia). Co ciekawe, te obiekty mają swoje
"wnętrze", np:
plane {y, 0}
jest płasz-
czyzną skierowaną "do góry" i wszystko
poniżej jest w jej wnętrzu – warto o tym
pamiętać, gdy robimy część wspólną.
Wygląd
Sam kształt obiektu to za mało. Będzie on
zrobiony z jakiegoś materiału (material),
który określa "skórkę" (texture), a jeśli jest
ona chociaż miejscami przeźroczysta, to
warto określić wnętrze (interior).
Tekstur może być kilka np.:
texture{T_metal}
texture{T_lakier}
texture{T_kurz}
Ma to sens, o ile pigmenty tych tek-
stur mają przeźroczystości. W powyż-
szym przykładzie tekstura T_kurz jest
niemal całkowicie przeźroczysta czy
O autorze
Autor pracuje jako administrator
na Uniwersytecie Łódzkim. Linuk-
sem zajmuje się od 5 lat, a pro-
gramem POV-Ray jeszcze dłużej.
Kontakt z autorem:
autorzy@linux.com.pl.
Na płycie CD/DVD
Na płycie CD/DVD znajdują się
pakiety źródłowe i binarne POV-
Raya, jak również przykład oma-
wiany w artykule. Aby wygene-
rować ołówki, należy skopiować
katalog Linux+/Grafika/povray/
olowek na dysk twardy i wykonać
w nim
make.
Bezpośrednio uży-
wając POV-Raya:
povray +io-
lowek.pov +FN +oolowek.png
+D +w320 +h240 +Q8 +a0.2
+am2 +j0.3 +r3
, gdzie
+i
- plik
z opisem sceny,
+o
- plik wyj-
ściowy,
+FN
- format: PNG,
+D
– pokazuje rendering,
+w +h
- rozmiar rysunku,
+a +am +j +r
- opcje polepszające jakość.
CD/DVD
Po uruchomieniu dystrybu-
cji Linux+ Live CD/DVD można
korzystać z POV-Raya.
Rysunek 1.
Przykładowa scenka – ołówki
35
grafika 3d
pov-ray
www.lpmagazine.org
półprzeźroczysta, a gdzieniegdzie jest
widoczna jakaś kropka. Pod spodem
będzie T_lakier – niemal jednolity, ale
miejscami z przeźroczystymi zadra-
paniami. Spod niego wyłania się goły
metal.
Sama tekstura ma kilka elemen-
tów: pigment (kolor+przeźroczystość),
finish (sposób odbijania światła, lśnienie,
połysk, odbijanie) oraz normal (symula-
cja nierówności).
Tekstury nie muszą być jednolite.
Mogą się (tak jak pigment/normal/finish)
zmieniać w przestrzeni z jednej na drugą.
Do tego może posłużyć wzór (pattern).
Prostym wzorem jest szachownica (chec-
ker). Dzieli ona przestrzeń na sześciany,
które mają naprzemiennie raz jedną, raz
drugą teksturę (pigment/normal/finish),
np.:
texture { checker texture{T_Wood_3A},
S
texture{Stone12} }
Dużo ciekawsze są wzory, które każ-
demu punktowi w przestrzeni przypo-
rządkowują liczbę od 0 do 1. W przy-
kładowej scenie z ołówkami użyłem
wzoru cylindrical, który punktom na
osi Y przypisuje wartość 1.0, a dalej,
w miarę oddalania się od tej osi, war-
tość maleje równomiernie aż do 0.0
w odległości 1 od tej osi. Jeszcze dalej,
pozostaje 0. Wykorzystałem to do usta-
lenia koloru rysika:
pigment {
cylindrical
color_map {
[0 Clear]
[.5 Clear]
[.5 Black]
[1 Black]
}
}
Clear to brak barwy – przeźroczystość.
Zauważmy, że od przeźroczystego do
czarnego mamy zerowy przedział, więc
granica między nimi jest ostra. Dzięki
wykorzystaniu tego wzoru ołówek jest
w środku czarny, a dalej przeźroczysty
– prześwituje spod niego poprzednia tek-
stura: drewno.
Domyślnie materiał to czarny pla-
stik z pustym wnętrzem. Na początek nie
musimy wszystkiego określać – wystar-
czy sam pigment. Nie trzeba też pisać
wszystkich szczebli całej struktury:
Listing 1.
Przykładowa scenka z ołówkami
#
include
"colors.inc"
#
include
"textures.inc"
camera
{
location
<-
4, 6.2,
-
9
>
look_at y
*
2
}
light_source
{
y
*
400,
White
}
light_source
{
<-
1, 4,
-
2
>*
100,
White
}
light_source
{
<
3, 2,
-
3
>*
100,
White
}
sky_sphere
{
pigment
{
gradient y
color_map
{
[
0 .4
color Black color Brown
]
[.
4
color Brown
]
[.
45
color Orange
]
[.
58 1
color LightBlue color Blue
]
}
translate
-
y/
2
scale
<
1,2,1
>
turbulence
0.03
}
}
plane
{
y,
0
pigment
{
bumps
color_map
{
[
0
Brown
]
[.
4
Gray
]
[
1
DarkGreen
]
}
}
finish
{
diffuse
0.4
}
}
#declare T_rysik = texture {
pigment
{
cylindrical
color_map
{
[
0
Clear
]
[.
5
Clear
]
[.
5
Black
]
[
1
Black
]
}
}
finish
{
reflection
0.1
phong
0.2
}
}
;
#macro T_lakier(kolor)
pigment
{
kolor
}
finish
{
/*specular 0.2*/
reflection
0.03
}
#end
#macro olowek(kolor, s)
#local wys=6;
difference
{
cylinder
{
0,
// punkt 0,0,0 - "dół" ołówka
y
*
wys
// <0,6,0> - "góra ołówka
1
// średnica
//(przed obskrobaniem)
}
// strugamy czubek
#local c=0;
#while (c<1)
sphere
{
y
*
wys,
wys
rotate x
*
75
translate y
*(
wys
+
0.2
*
rand
(
s
))
rotate y
*(
c
*
360
S
+ (
rand
(
s
)-
0.5
) *
20
)
}
#declare c = c+1/6;
#
end
texture
{
White_Wood scale .
3
translate y
*
rand
(
s
)
}
texture
{
T_rysik
}
}
#end
#macro olowek_kanciaty(kolor, s)
difference
{
olowek
(
kolor, s
)
// obcinamy boczki
#declare c=0;
#while (c<1)
plane
{
z,
-
0.8
texture
S
{
T_lakier
(
kolor
)
}
S
rotate c
*
y
*
360
}
#declare c = c+1/6;
#end
}
#end
object
{
olowek_kanciaty
(
Red,
S
seed
(
1
))
translate x
*-
2
}
object
{
olowek_kanciaty
(
Yellow,
S
seed
(
2
))
translate x
*
0
}
object
{
olowek_kanciaty
(
Green,
S
seed
(
3
))
translate x
*
2
}
object
{
olowek_kanciaty
(
Gray,
S
seed
(
4
))
translate x
*
4
}
36
grafika 3d
lipiec 2004
sphere {
0,1
material {texture {pigment{ color
S
Yellow}}}
}
bo można to uprościć do:
sphere {
0,1
pigment{ Yellow }
}
Inne elementy
Musimy określić kamerę (camera), czyli
podać informację, z którego miejsca
i w które miejsce (lub w jakim kierun-
ku) patrzymy. Podajemy tu też pro-
porcje ekranu. Co ciekawe, rozmiar
wynikowego pliku graficznego, który
przy kwadratowych pikselach defi-
niuje nam te proporcje, wskazujemy
w wywołaniu programu opcjami
+w
i
+h
.
Aby było cokolwiek widać, potrzeb-
ne jest oświetlenie –
light_source
(nie
licząc samoświecenia obiektów, określa-
nego w
finish
).
Dyrektywy
Wszystko, co zaczyna się od
#
w kodzie
źródłowym, jest dyrektywą – odpo-
wiednik
dyrektywy
preprocesora
w języku C. Za pomocą dyrekty-
wy
declare
możemy zadeklarować
sobie zmienną rzeczywistą, wektor,
obiekt czy teksturę, a potem się
nim wygodnie posługiwać, np. dekla-
rujemy pod nazwą Pionek figurę sza-
chową, a potem używamy jej wielo-
krotnie:
object{ Pionek translate jakieś_miejsce }
object{ Pionek translate
S
jakieś_inne_miejsce }
Powyższy sposób jest dobry do obiek-
tów identycznych, ale nie nadaje się, jeśli
zadeklarowany obiekt może różnić się
jakimś szczegółem, np. kolorem emalii
w kredce. Wtedy przydaje się makro
– może ono mieć parametry, które przy
wywołaniu zostaną wstawione w miej-
sce swoich nazw. Trzeba na to uważać,
np. mamy makro do obliczania długości
przeciwprostokątnej:
#macro przeciwp(a,b) sqrt(a*a + b*b) #end
które przy wywołaniu
przeciwp(1,3+4)
rozwinie się do
sqrt(1*1 + 3+4*3+4)
.
Prawidłowo zdefiniowane makro ma
postać:
#macro przeciwp(a,b) sqrt((a)*(a) +
S
(b)*(b)) #end
To makro rozwija się w wyrażenie
– możemy go używać jak funkcji. Inne
makra mogą rozwijać się w obiekty czy
tekstury, tak jak w przykładzie.
Przy okazji, cenna rada dotycząca
deklarowania obiektów: powinien on się
znajdować w środku układu współrzęd-
nych, a dopiero potem w trakcie korzy-
stania z obiektu możemy go sobie prze-
sunąć. Przykładowo, mamy lampę wiszą-
cą u sufitu. Nie deklarujmy jej od razu jako
wiszącej wysoko – niech jej zaczep będzie
w punkcie <0,0,0>. Dopiero potem można
ją sobie wygodnie "powiesić":
object {lampa translate y*wys_pokoju}
Co więcej, jeśli chcemy ją rozbujać
(a obroty są zawsze wokół początku
układu współrzędnych), to wystarczy:
object {lampa rotate z*bujniecie
S
translate y*wys_pokoju}
Dyrektywa
#include
powoduje włączenie
w to miejsce innego pliku źródłowego
– dzięki temu możemy sobie dzielić duży
plik na mniejsze lub tworzyć pliki wyko-
rzystywane wielokrotnie (biblioteki).
Warto się zainteresować standardowy-
mi plikami bibliotecznymi – można tam
znaleźć dużo gotowych rzeczy do wyko-
rzystania. Te pliki są dokładnie opisane
w dokumentacji.
Listing 2.
Skrypt tworzący plik Makefile
dla renderingu równoległego
#!/bin/bash
num=$1
srcfiles='test.pov'
povopts="+itest.pov +oframe.png
S
+w400 +h300 +kfi1 +kff$num"
anim=
"anim: "
echo all: anim
echo "
POV=povray $povopts"
for n in $(seq -w 1
$num);
do
anim="$anim frame$n.png
"
echo -e "frame
$n.png:
S
$srcfiles\n\t\$(POV) +sf$n +ef$n\n"
done
echo
$anim
Rysunek 3.
Plik POV-Raya w edytorze VIM
Rysunek 2.
POV-Ray Modeler
37
grafika 3d
pov-ray
www.lpmagazine.org
Animacje
Program nie tworzy plików Avi/Mpeg,
natomiast generuje sekwencje obra-
zów. Ruch na tych obrazach tworzy się
w bardzo prosty sposób: mamy do dys-
pozycji zmienną
clock
, która dla każdej
klatki ma inną wartość: zaczyna (domyśl-
nie) od zera, a kończy na jedynce. Ma
znaczenie, czy robimy animację zwykłą
czy cykliczną (parametr
+KC
). Dla 5 klatek
animacji zwykłej zmienna clock przyjmie
kolejno wartości: 0 0.25 0.5 0.75 1, a przy
cyklicznej: 0 0.2 0.4 0.6 0.8.
Zmienną clock można wykorzystać w
dowolny sposób – jesteśmy tylko ograni-
czeni pomysłowością i znajomością mate-
matyki. Prosty obrót obiektu robimy tak:
rotate y*clock
a przesunięcie z punktu A do punktu B
tak:
translate A+(B-A)*clock
Zdecydowanie odradzam posługiwanie
się “gołą” zmienną clock – wygodniej
jest tworzyć makra z parametrem "faza",
który zawsze będzie miał zmieniać się od
0 do 1, np.:
// 0 - odchylenie w jedną
// 0.5 - odchylenie w drugą
// 1 - to co 1
#macro hustawka(faza)
...
#end
Jeśli nagle postanowimy, że nasza huś-
tawka będzie wahać się nie raz, a 3 razy,
to wystarczy zmienić
hustawka(clock)
na
hustawka(3*clock)
.
Losowość
Powtarzalność i regularność nie wyglą-
da zbyt naturalnie (jak słoje drewna
w naszych ołówkach), więc warto wpro-
wadzić odrobinę chaosu, np. samą tek-
sturę można przesunąć wzdłuż ołówka
o pewną wartość – wtedy wygląd będzie
odmienny.
Dodatkowo, na Rysunku 1 widać, że
kredki nie są zaostrzone równo, a każde
"machnięcie nożem" jest w jakiś sposób
losowe.
Do losowania służą dwie funkcje, sto-
sowane w taki sposób:
#declare s = seed(1234);
#declare v1 = rand(s);
#declare v2 = rand(s);
#declare v3 = rand(s);
#declare v4 = rand(s);
Funkcji seed() przekazujemy zarodek
losowania. Z tego samego zarodka kolej-
ne wylosowane wartości od v1 do v4
(z przedziału 0.0 - 1.0) będą te same.
Ta cecha jest przydatna w animacjach,
np. dziury w serze niech będą porozpra-
szane, ale ich układ nie może się zmieniać
z klatki na klatkę.
Obliczenia równoległe
Pracę polegającą na wyrenderowaniu
obrazka czy całej animacji łatwo jest
podzielić na kawałki i liczyć równole-
gle. Każdą klatkę można wyrenderować
niezależnie – nawet jedną scenę można
podzielić na kawałki, wyrenderować i na
końcu je posklejać.
Program jest uruchamiany z linii
poleceń (wszelkie ustawienia wpisujemy
w parametry), więc dosyć łatwo można
to “uskryptowić”. Na komputerze wielo-
procesorowym lub na klastrze można by
odpalić wiele programów na raz, każdy
liczący jedną klatkę. Gdy jeden z nich
skończy pracę, to odpalamy następny,
który liczy kolejną klatkę. Można sko-
rzystać z programu make i jego opcji
-j
mówiącej, ile zadań może uruchomić
jednocześnie. Potrzebny mu plik Make-
file można wygenerować przy pomocy
skryptu mkmake.sh (Listing 2), podając
liczbę klatek animacji:
./mkmake.sh 40 >Makefile
Wtedy, mając do dyspozycji 4 proceso-
ry (np. 2 x Xeon), spokojnie odpalamy 6
zadań na raz:
$ make -j6
.
Słowo na koniec
Zamieściłem tutaj krótki przegląd tego,
co oferuje POV-Ray. Polecam jego doku-
mentację, która jest ładnie usystematyzo-
wana i nie trzeba od razu wszystkiego
czytać – można potem w razie potrzeby
łatwo znaleźć interesujący fragment.
Ciekawostki
Dla tych, którzy nie lubią plików teksto-
wych, powstał program POV-Ray Mode-
ler (Rysunek 2). Program pokazuje to, co
się stworzyło – mamy okienko z całym
"drzewem sceny": obiekty zrobione
z podobiektów, z nałożonymi teksturami,
które składają się z prostszych elemen-
tów itd. Osobiście nie korzystam z tego
typu narzędzi, ponieważ efekty osiąga
się na ogół wolniej (tak, tak, przy odro-
binie wprawy sceny w POV-Rayu pisze
się całkiem sprawnie), nie ma skompli-
kowanej elastycznej parametryzacji oraz
animacji.
Istnieje projekt o nazwie Internet
Movie Project – grupa osób postanowi-
ła stworzyć pełnometrażowy film ani-
mowany używając do tego programu
POV-Raya, a animacje renderować
w sposób rozproszony w Internecie (na
podobieństwo projektu Seti@Home).
Jeśli Czytelnik nabierze odrobiny
sprawności w posługiwaniu sie progra-
mem, a do tego ma trochę talentu i pomy-
słowości, może wziąć udział w konkursie
dla amatorów na stronie www.irtc.org. Są
dwie konkurencje: na najlepszą grafikę
oraz animację. Prace wykonane w POV-
Rayu pokazują się tam dosyć często.
W Internecie:
• Oficjalna strona programu POV-Ray:
http://www.povray.org/
• Grupy dyskusyjne na temat POV-
Raya (w tym international, na której
można pisać po polsku):
http://news.povray.org/groups/
• Konkurs grafiki 3D dla amatorów:
http://www.irtc.org/
Rysunek 4.
Strona projektu Internet Movie
Project
Rysunek 5.
Strona główna programu