czwartek, grudnia 25, 2008

Nie taka Java wolna jak ją opisują...

W poście o cieniowaniu metodą Gourada napisałem, że mój applet nie jest zbyt prędki.

W mojej ocenie [a pewnie i tych, którzy czytali tamten post ;-)] winę za to ponosiła niewydolność Java'y w obliczeniach... i tu okazuje się, że się myliłem :-)

Okazuje się, że prawie 10 razy więcej czasu zabiera stworzenie obrazka z pikseli przekazanych do metody setRGB(int, int, int, int, int[], int, int) niż wyliczenie wartości tych pikseli...... OK, trochę zamotane ;-)

Na wejściu mamy 550 punktów w przestrzeni 3D, te punku wchodzą w składa 1039 trójkątów [zwanych w kodzie facetami ;-) od face ;-)]. Program dokonuje obliczeń na 550 punktach obracając je w przestrzeni 3D, w tym celu używa 9 mnożeń [standardowo powinno być 12, ale gdy wykorzysta się macierz obrotów to okazuje się, że niektóre czynniki się powtarzają i można zredukować ilość mnożeń z 12 do 9 [niestety nie wpadłem na to sam]], mając nowe położenia punktów program rzutuje je na powierzchnię ekranu. Teraz mając już zestaw punktów na płaszczyźnie przechodzi do rysowania. W tym celu używa 1039 trójkątów, które zawierają w sobie numery wchodzących w ich skład punktów. Dzięki temu można dla każdego z trójkątów poznać współrzędne na płaszczyźnie ekranu [potrzebne do narysowania trójkąta w odpowiednim miejscu] i współrzędne w 3D [potrzebne do wyliczenia wektora normalnego, a przez to koloru punktu]. Rysowanie trójkątów to nie jest takie hop-siup, bo trzeba po pierwsze wyliczyć kolory ich wierzchołków [używając wektora normalnego], po drugie wyliczyć ich z-index, posortować je wg. z-index'u [tak żeby najpierw rysować dalsze trójkąty, a później bliższe] a później spróbować narysować te trójkąty tak by przejścia kolorów między wierzchołkami na całej powierzchni trójkąta były znośne. Z tym, że rysowanie odbywa się w buforze, w którym każdy punkt składa się z 3 liczb [po jednej na kolory czerwony, zielony i niebieski].
I okazuje się, że na maszynie na której to teraz piszę cały ten proces zajmuje od 1.46 do 3 ms. Czyli w najgorszym wypadku mogę takich "rysunków" narysować od ponad 300 do blisko 700 na sekundę. Z ilością klatek średni czas maleje [w chwili obecnej przy ponad 4500 klatek czas na jedną klatkę wynosi około 1.37 ms, a po 5000 klatek jest to już 1.33 ms].
Za to przerobienie tego bufora z rysunkiem, za które to przerobienie odpowiada już sama Java zajmuje około 21-22 ms... Czyli trwa od 10 do 17 razy dłużej niż narysowanie rysunku...
Żeby było zabawniej, zmiana typu rysunku z TYPE_3BYTES_RGB na TYPE_INT_RGB spowodowała przyśpieszenie z 21-22 ms do około 14-15 ms :-)


Podobne postybeta
Gouraud = Pseudo Phong :-)
WebGL - dalsze zabawy
Chrome, Firefox, IE9 preview i cieniowanie Gouraud'em w JavaScript
Cieniowanie Gourauda w JavaScript part 2 - przyśpieszamy :-)
Na śpiocha....