home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1997 #3
/
amigamamagazinepolishissue03-1
/
ma_1995
/
08
/
ami021.txt
< prev
next >
Wrap
Text File
|
1997-04-07
|
7KB
|
169 lines
/**** ELA, NAJPRAWDOPODOBNIEJ TRZEBA ZMIENIÊ LEAD, BO JESTEM PEWIEN,
ÛE WYWALË MU CONAJMNIEJ POÎOWË OBRAZKÓW. -Raf ****/
Jak ulepszyê procedurë?
-----------------------
CIENIOWANIE
<lead>Do dzisiejszego odcinka przygotowaîem "nieco" ilustracji. A
zajmiemy sië oôwietlaniem i cieniowaniem ruchomych obiektów.
<a>Miklesz/ Damage
<txt>Na poczâtek parë zaîoûeï przydatnych przy rysowaniu ôcian.
Bëdziemy rysowaê czworokâtnâ ôcianë, wyznaczonâ przez punkty
(0,1,2,3). Musimy jeszcze zaîoûyê jedno. Kolejne punkty ôciany
zawsze "przebiegajâ" w jednym kierunku (np.: w kierunku wskazówek
zegara). Pierwszâ rzeczâ, jakâ musimy zrobiê, bëdzie znalezienie
najwyûszego (majâcego najmniejszâ wspóîrzëdnâ Y) punktu. Zaîóûmy,
ûe bëdzie on miaî numer 0. Kiedy juû to wiemy, îatwo moûna
zauwaûyê, ûe nasza figura bëdzie ograniczona z lewej strony
nastëpujâcymi krawëdziami (posuwajâc sië od góry): 0-3 i 3-2. Z
prawej bëdâ to 0-1 i 1-2. Wiemy, ûe Dy (wysokoôê caîej figury,
liczona po osi Y) jest równa:
<l>Dy=Y2-Y0
<txt>Pozostaje nam wiëc przetablicowaê sobie obie (lewâ i prawâ)
krawëdzie. Kaûdâ liczymy w dwóch etapach (lewâ: 0-3 i 3-2, prawâ:
0-1 i 1-2). Jak szybko wyliczyê wszystkie punkty odcinka?
Przemnaûanie wszystkich wartoôci nie naleûy do najlepszych metod.
Natomiast wyliczenie krótkiego wektora i dodawanie go do
kolejnych punktów spowoduje powstawanie sporych przekîamaï,
wynikajâcych ze staîoprzecinkowoôci procesora gîównego. Nie chcë
byê posâdzony o pisanie tekstów za pomocâ funkcji Copy i Paste,
ale poniewaû wspominaîem o metodzie, pozwalajâcej rozwiâzaê nasz
problem juû kilka miesiëcy temu, to pozwolë sobie przedstawiê jâ
raz jeszcze:
<sr>Wyliczanie krawëdzi
<txt>Caîâ krawëdú moûemy potraktowaê jako funcjë N-elementowâ,
przyporzâdkowujâcâ kaûdemu elementowi (Yi) z osi Y, wartoôê (Xi)
z osi X. Braliômy to juû przy okazji omawiania wektorów
teksturowanych. Podajë wzór:
<l>I - Indeks
N - Liczba punktów
X0 - Wspóîrzëdna X punktu (0,0)
Xn - Wspóîrzëdna X punktu (N,0)
Xi - Wspóîrzëdna X punktu (I,0)
Y0 - Wspóîrzëdna Y punktu (0,0)
Yn - Wspóîrzëdna Y punktu (N,0)
Yi - Wspóîrzëdna Y punktu (I,0)
Xi=(Xn-X0)/N*I+X0
Yi=(Yn-Y0)/N*I+Y0
<txt>Jak jednak dokonywaê wszelkich mnoûeï i dzieleï liczb
zmiennoprzecinkowych? Jeûeli mamy koprocesor matematyczny, to
problem z gîowy, lecz co wtedy, gdy nie jesteômy wîaôcicielami
FPU? Pozostaje nam jedynie symulacja liczb zmiennoprzecinkowych
na liczbach staîoprzecinkowych. Zacznë od przykîadu, którego
bezpoôrednio nie moûna by byîo wykorzystaê w asemblerze, z uwagi
na mnoûenie przez potëgi liczby 10, a nie 2. My jednak
procesorami nie jesteômy, wiëc 10 wyglâda dla nas trochë
przyjaúniej.
Przypuôcmy, ûe chcemy pomnoûyê liczbë 12,34 przez 56,78.
Normalnie procesor gîówny obciâîby wszystko to, co po przecinku,
i otrzymalibyômy 12 x 56 = 672. Jest to oczywiôcie niezgodne z
prawdziwym wynikiem, wynoszâcym 12,34 x 56,78 = 700,6652.
Przypuôêmy, ûe jeszcze bîâd rzëdu +1/-1 byîby dopuszczalny, ale
pomyîka o prawie 1/10 wyniku, to juû powaûna sprawa. A caîoôê
wyglâda jeszcze groúniej, kiedy musimy póúniej zsumowaê kilka
bîëdnie wyliczonych wartoôci! Ale jest sposób na otrzymywanie
dokîadniejszych wyników. Najpierw nasze dwie wartoôci pomnóûmy
przez 100 (czyli przesuïmy przecinek na koniec cyfry). Otrzymamy
1234 i 5678. Teraz spokojnie mnoûymy obie liczby przez siebie,
otrzymujâc w wyniku 7006652. Nastëpnie caîoôê dzielimy przez
100000 (liczba zer jest oczywiôcie sumâ miejsc, o które
przesunëliômy wczeôniej przecinek). Wynik: 700,6652, czyli po
odjëciu zer, równe 700. Bîâd wyniósî 0,6652. Jest to znacznie
mniej niû jeden procent caîoôci, a to chyba dokîadnoôê
wystarczajâca, aby nasza wektorówka wyglâdaîa estetycznie.
Pozostaje pytanie, jak to wszystko mnoûyê w asemblerze? To
proste, wszelkie operacje wykonujemy przy liczbach juû wczeôniej
przemnoûonych przez jakâô potëgë dwójki, czego dokonujemy
oczywiôcie nie przez MULa.b lecz przez przesuniëcia bitowe. Tu
warto zwróciê uwagë, ûe im bardziej wczeôniej przeskalujemy
wartoôci poczâtkowe, tym dokîadniejszych wyników moûemy póúniej
oczekiwaê. Oczywiôcie tak prosto nie da sië uzyskaê samych liczb
z wartoôciami po przecinku. Posiadajâc jedynie CPU, wartoôci
takie uzyskaê moûemy jedynie w wyniku dzielenia przez siebie juû
przeskalowanych liczb. Obecnie na 68EC020++ moûemy juû operowaê
na QuadWordach, tak wiëc zakresów nam raczej nie zabraknie.
Jeûeli zaô chodzi o przesuwanie bitowe, to polecam szybkâ
instrukcjë SWAP.W, która w ekspresowy sposób z kaûdej liczby
$0000abcd, zrobi nam przeskalowanâ $abcd0000. Naleûy pamiëtaê
oczywiôcie, ûe wszelkie operacje na przeskalowanych wartoôciach
muszâ mieê rozmiar dîugiego sîowa (.L), gdyû mniejsze rozmiary
bëdâ dotyczyîy jedynie cyfr "po przecinku".
Kiedy juû wyliczymy sobie to, czego potrzebujemy, jednym SWAPem
sprowadzamy liczbë "na ziemië", czyli obcinamy zera (w zasadzie
to wysyîamy je "do góry", lecz przy dalszych operacjach na samym
sîowie (.W) nie ma to juû znaczenia, choê czasami moûe warto i o
tym pamiëtaê), a czëôê caîkowitâ otrzymujemy w dolnych szesnastu
bitach rejestru. Kiedy wiëc podanâ przeze mnie metodâ wyliczymy
wszystkie cztery krawëdzie i po poîâczeniu tablic otrzymamy dwie:
lewâ i prawâ, wystarczy (jak to robi blitter) wypeîniê przestrzeï
pomiëdzy nimi.
<sr>Cieniowanie ôcian
<txt>Na razie narysowaliômy ôcianë w jednym kolorze. A przecieû
miaîo byê o cieniowaniu! Okazuje sië, ûe wystarczy juû jedem maîy
kroczek. Dla uproszczenia przyjmujemy, ûe odlegîoôê danego punktu
ôciany zaleûy od jego odlegîoôci od obserwatora, liczonej w osi
Z. Dziëki temu, juû po wykonaniu rotacji, znamy jasnoôci
naroûników. Wystarczy wyliczyê natëûenia na caîej ôcianie.
Zaczniemy od wyliczenia jasnoôci kaûdego z punktów krawëdzi.
Znowu skorzystamy z usîug proporcjonalnoôci i kiedy bëdziemy
wiedzieli, ûe naroûnik 0 ma jasnoôê 255, a naroûnik 1 000, to
kolor I tego punktu jest równy:
<l>Ci=(C1-C0)/N*I+C0
<txt>Oznaczenia indeksów pozostajâ takie same, jak we wzorze na X
i Y. Znamy juû natëûenia wszystskich punktów dwóch krawëdzi
lewych i dwóch prawych. Teraz, kiedy wypeîniamy ôcianë, musimy
zadbaê o pîynne przejôcie jasnoôci od lewego do prawego brzegu.
Jeûeli powiem, ûe znów wykorzystamy tu proporcjonalnoôê, to nikt
juû chyba nie bëdzie zaskoczony. Sposób podany przeze mnie nie
jest moûe idealny, ale powstajâce w wyniku jego dziaîania
niedokîadnoôci przy cieniowaniu sâ bardzo maîe. W kaûdym razie
metoda sië sprawdza w 100%, a trzeba zauwaûyê, ûe jest stosunkowo
szybka!
<sr>Ilustracje
<txt>Tradycyjnie prezentujë kilka przykîadów demek wykorzystujâcych
omawiane przeze mnie techniki. Ilustracja pierwsza pochodzâca z dema
"Anahalonium Lewini" grupy Tristar Red Sector Incorporation, to
przykîad zastosowania prostej metody oôwietlania do skomplikowanej
figury, co daîo niezîy efekt koïcowy. Druga ilustracja przedstawia
obraz ôcianki jaki moûna otrzymaê po zastosowaniu algorytmu,
podanego przeze mnie. Jeûeli w wyniku dziaîania Waszej procedurki
"wyszîo" wam coô podobnego, to znaczy, ûe jest wszystko OK!
<sr> Sîowo na niedziele
<txt>Jak widzicie, cieniowanie obiektów, to nie taka straszna
"Magia Davida BlitterFielda". Nadmieniê jednak naleûy, ûe
wykonanie DOBREJ procedury do oôwietlania, jest dosyê
czasochîonne. Ûyczë udanych prób i wspaniaîych efektów. Udanego
Gourauda! Za miesiâc opowiem, jak wykonaê "RealTime Emboss".