Modne ostatnio karty grafiki 21- i 24- bitowej umoûliwiajâ - przez bezpoôrednie okreôlenie wartoôci skîadowych R,G,B koloru - uzyskaê miliony barw.
Niestety, karty te sâ bardzo drogie, zaô sama Amiga okreôla kolor punktu nieco inaczej. Robi to za pomocâ najwyûej 6-bitowej liczby, wskazujâcej adres w tablicy, w której sâ zapamiëtane kolory. Umoûliwia to uzyskanie maksimum 64 (2 x 32 w trybie Extra Halfbright [Halfbrite]) odcieni barw jednoczeônie. A zatem -- nie moûna w standardowych rozdzielczoôciach (takûe w trybie HAM) korzystaê z wiëkszej liczby odcieni na raz.
Za pomocâ opisanej poniûej sztuczki zmusimy standardowy tryb graficzny niskiej rozdzielczoôci (LoRes) do tego, aby pozwoliîa na uûycie w niej jednoczeônie i niezaleûnie od siebie 4096 odcieni. Pomoûe nam w tym koprocesor zwany Copperem. Moûe on pobieraê dowolnâ pozycjë rastra, a nastëpnie zmieniaê dowolny rejestr hardware'owy (miëdzy innymi takûe kolor podkîadu). W momencie gdy Copper oczekuje na rozkaz -- przesuwa on promieï rastra. Otwiera to przed nami pewne moûliwoôci:
Zasada: Pozostawiamy Copper w stanie oczekiwania na linië obrazu, przez taki czas, w którym 40-krotnie nada on kolorowi podkîadu innâ wartoôê. Po 40 rozkazach -- promieï rastra ustawi sië na koïcu obrazka (40 x 8 = 320 punktów) wszystko to musi Copper powtórzyê takûe dla innych linii obrazka.
W kaûdym wierszu musimy teraz zdefiniowaê na nowo odstëpy dla kaûdych oômiu punktów koloru podkîadu, i to nieco inaczej, a mianowicie jako wartoôê 12-bitowâ (ma to byê zawartoôê skîadowej R,G i B jednego z 4096 odcieni). Moûna takûe pokazaê na ekranie wszystkie 4096 odcieni na raz. Rozdzielczoôê zmniejszy sië do 40 x 256 punktów, co oznacza, ûe jeden punkt bëdzie miaî dîugoôê 8 "normalnych" pixeli. Nie jest to jednak tak tragiczne, jak mogîoby sië wydawaê, poniewaû na tak wspaniale barwnym podkîadzie wspaniaîej liczby barw moûemy umieôciê obrazek w normalnej rozdzielczoôci (320 x 256 punktów). Obrazek taki nie moûe mieê jednak wiëcej niû 16 kolorów. Îadowanie obrazka odbywa sië za pomocâ rozkazu umieszczonego w ostatnim wierszu listingu nr 1.
Tâ technikâ moûemy tworzyê piëkne podkîady do obrazów, w których niûsza rozdzielczoôê nie bëdzie stanowiê przeszkody przy korzystaniu z 4096 barw, na przykîad: sîoïce wynurzajâce sië z morza, zaô na takim podkîadzie rysujemy przykîadowo sylwetkë zakochanej pary (przypominam, najwyûej w 16 kolorach).
Listing 1 pokazuje, jak programowaê w "nowym" trybie (nazwijmy
go "LoLoRes"). W miejsce adresu "obraz" w ostatniej linii
programu, moûesz zaîadowaê 16-kolorowy obrazek w formacie
RAW, potraktowany dowolnym konwerterem bit-planów. Przede
wszystkim, jeôli w obrazie zostanie uûyty drugi kolor z
palety, wówczas zobaczysz 4096-kolorowy podkîad. Za pomocâ
procedury "SetPoint" -- kaûdemu punktowi po kolei zostanie
przypisany kolor bitplanu. W rejestrze D0 zostanie zapisana
pozycja X (z zakresu 0-39), w rejestrze D2 -- pozycja Y (z
zakresu 0-255) punktu, zaô w rejestrze D2 -- kolor punktu. Na
liôcie Coppera pod adresem "Data" znajduje sië rozkaz dla
Coppera, podajâcy kolory podkîadu. Procedura "initdata" wytwarza
wspomnianâ listë Coppera. Poniewaû wczeôniej na liôcie
rozkazów zostaî zapisany rozkaz "Wait", zatem Copper bëdzie
czekaî na poczâtek pierwszego wiersza obrazu. Rozkaz:
$303f, $fffe
$30 -- poczâtkowa pozycja Y obrazka
$3f -- poczâtkowa pozycja X obrazka
$fffe -- rozpoznanie rozkazu "Wait"
$0180,$0000
Rozkaz ten ustawia drugiemu kolorowi (rejestr barw $182) wartoôê tego koloru (tu $0000). A zatem najpierw wszystkie punkty stanâ sië czarne. Dopiero procedura "setpoint" zapisze odpowiednie wartoôci kolorów na listë Coppera. Jednoczeônie pozycja Y rozkazu "Wait" o jeden wiersz sië zwiëkszy, a caîy przebieg zostanie powtórzony dla wszystkich 255 linii obrazu.
initdata:
lea data,a0 ;lista rozkazów na liôcie Coppera
move #256-1,d7 ;liczba wierszy obrazu
move.l #$303ffffe,d0 ;format pierwszego rozkazu Wait
idl:
move.l d0,(a0)+ ;zapis rozkazu Wait na listë Coppera
move #40-1,d6 ;liczba kolumn obrazu
idl2:
move.l #$01820000,(a0)+ ;40 krotna zmiana koloru punktu
dbf d6,idl2
add.l #$01000000,d0 ;rozkaz Wait przeniesiony do nastëpnej linii
dbf d7,idl ;pozostaîe wiersze
DATA: blk.l 40+2*256 ;lista rozkazów na liôcie Coppera
Procedura "SetPoint" oblicza pozycjë X w D0 i pozycjë Y w
D1 adresu uûytego koloru na liôcie rozkazów i z powrotem
umieszcza odpowiedniâ wartoôê parametru barwy w rejestrze D2.
Wartoôê Y jest mnoûona przez 164, gdyû na jeden wiersz
potrzebne bëdzie 41 rozkazów Coppera, kaûdy o dîugoôci 4
bajtów (41 x 4 = 164), zaô wartoôê X przez 4, gdyû jak juû
wiesz jeden rozkaz ma 4 bajty dîugoôci.
SetPoint:
lea data+6,a0 ;wartoôê dla koloru pierwszego punktu
lsl #2,d0 ;X mnoûone przez 4
mulu #40+1*4,d1 ;Y mnoûone przez 64
add.l d1,a0
move d2,(a0,d0,w) ;zapis wartoôci dla koloru
Na poczâtku programu zostaîy dla celów testowych ustawione
trzy punkty (wiersze 8 do 19). W to miejsce moûecie
sobie wejôê, aby poeksperymentowaê. Przykîadowo moûna zmieniê
Listing 1. Nastëpnie zapëdziê do pracy drugi koprocesor o nazwie
Blitter. Pozwoli nam to na uzyskanie feerii barw, poprzez
pomieszanie w tabeli wartoôci dla kolorów i zapisanie tego na
liôcie rozkazów. Moûemy kaûdy skîadnik koloru (czerwony,
zielony, niebieski) oddzieliê, a na ekranie utworzyê poruszajâcâ
sië sinusoidë, jednak tak, aby trzy krzywe nie zostaîy
zakîócone. Bëdzie to wyglâdaê tak, jakbyômy farbë z garnka
wylali do wanny z wodâ i mocno rozbeîtali -- przedstawiony
listing nie jest aû tak rozrzutny. Najpierw uîóûmy tabelë, w
której stworzymy "belki" o szerokoôci 8 punktów. Oto przykîad
dla koloru czerwonego:
Tabela:
blk.w 100,$000 ;"poczâtkowy" czarny kolor
dc.w $100 ;rozjaônia sië
dc.w $100 ;rozjaônia sië dalej
dc.w $100 ;i bardziej
dc.w $200 ;coraz bardziej
dc.w $300
dc.w $400
dc.w $500
i tak powtarzamy rozkaz dc.w z wartoôciâ zmienianâ o 100, aû osiâgniemy:
dc.w $f00 ;maksymalna jasnoôê.
A teraz "pojedziemy" z tabelâ w drugâ stronë:
dc.w $e00
dc.w $d00
dc.w $c00
i tak dalej, aû z powrotem dojdziemy do:
dc.w $200
dc.w $100
blk.w 100,$000 ;tu znowu jest czarny kolor.
Wiecie juû teraz, jak tworzyê tabelë. Zapisujemy jâ z Blitterem na liôcie rozkazów tak, aby pierwsze pionowe 8 punktów obrazowaîo sinusoidë. Kolejne "belki" na prawo od juû wprowadzonej zapisujemy w sposób opisany powyûej -- pod lub ponad wpisanâ tabelâ, aû osiâgniemy minimum (lub maksimum) naszej sinusoidy. Tak samo postâpimy z kolorem niebieskim i zielonym. Teraz musimy tylko przesunâê tabelë o 4 lub 8 punktów na prawo lub na lewo. Oczywiôcie dla tych dwóch skîadników koloru (B,G) powinniômy zmieniê przebieg naszej sinusoidy, tak by w efekcie otrzymaê trzy róûne krzywe. Kaûda z nich bëdzie tworzyê inny rozkîad barw.
Skopiujmy jednym przebiegiem Blittera wszystkie trzy
tabele barw jednoczeônie do jednej kolumny. Kaûde úródîo
wskazuje na wîaôciwe wejôcie do tabeli, a zatem trzeba
przesunâê na prawo úródîo A o 8 punktów (z $X00 na $00X,
niebieski), zaô úródîo B o 4 punkty (na $0X0, zielony). Úródîo
C pozostanie nie zmienione ($X00, czerwony). Szerokoôê okna
Blittera wynosi 2 bajty (1 "sîowo barwne"), a wysokoôê 256
(jest równa wysokoôci ekranu w danej rozdzielczoôci). Modulo
dla wszystkich trzech úródeî wynosi 0. Chcemy teraz zapisaê
nastëpnâ wartoôê z tabeli barw na liôcie Coppera. Wszystkie
trzy úródîa îâczymy rozkazem OR (logiczne "lub"), zatem
wszystkie trzy skîadniki koloru zostanâ do siebie dodane
(MINITERM = %11111110). Modulo dla rejesru docelowego obliczymy
ze wzoru:
szerokoôê wiersza listy Coppera - 2
poniewaû po skopiowaniu wartoôci barwy wskaúnika na D, wiersz na liôcie Coppera bëdzie poîoûony niûej.
Teraz musimy powtórzyê operacjë z Blitterem (jej opis zaczyna sië od gwiazdki) dla kaûdej kolumny ekranu, czyli w naszym przypadku 40 razy. Trzy úródîa zostanâ umieszczone w formie trzech niezaleûnych sinusoid o róûnym ksztaîcie na róûnych pozycjach tabeli barw. Cel pokazuje ciâgle jednâ z 40 wartoôci barw w pierwszym wierszu Coppera. Wartoôê barwna dla pozostaîych 256 wierszy zostanie uzyskana za pomocâ funkcji Modulo dla D. Wartoôci funkcji sinus umieôcimy w tabeli, gdyû zawsze krócej trwa pobranie wartoôci z tabeli niû wyliczenie jej.
Moûna w tym celu wykorzystaê pomocniczy BASIC-owy (tak,tak) program -- przedstawiony jako listing 3. Za pomocâ obliczonych 512 wartoôci moûemy zbudowaê caîkiem przyzwoitâ sinusoidë, której maksimum bëdzie wynosiê $800, zaô minimum -$800. Sposób "poîâczenia" uzyskanej tabelki z programem w assemblerze opisany jest na poczâtku listingu nr 3.
Wróêmy jednak do naszego programu. Niezaleûnie od trzech sinusoid "krëcâcych sië" w pionie, rusza sië teû caîy ekran (tyle ûe w poziomie, ale za to tam i z powrotem). Tak powstaje wzorzec. Za pomocâ Coppera moûna teraz pozycjë X sprawdziê bezpoôrednio jedynie dla 4 punktów. Poniewaû zmiana pozycji X pomimo to pasuje do punktu, moûliwe jest zastosowanie sztuczki: Na ekranie umieszczamy "czyste" belki o szerokoôci 8 punktów, i w ten sposób zostanâ pokazane zmienione kolory dla wszystkich 8 punktów z rejestrów $ 184 i $186. Za pomocâ Coppera zmieniamy teraz tylko na przemian oba te kolory, jednak wciâû tylko te, które sâ bezpoôrednio niewidoczne. Oprócz tego, musimy pracowaê z dwiema listami Coppera. W tym samym czasie, gdy jedna z nich bëdzie opracowywana, na drugiej liôcie Blitter bëdzie zapisywaî wartoôci kolorów. Po kaûdym przejôciu rastra obie listy "zamieniâ sië miejscami".
Na poczâtku listingu nr 2 znajdujâ sië zmienne okreôlajâce szybkoôê, siîë i rozkîad barw. Moûna je modyfikowaê w zakresach podanych w poniûszej tabelce. Gdy juû "nacieszysz oczy" efektem dziaîania programu opisanego listingiem 2, wówczas radzimy Ci spróbowaê eksperymentów z wartoôciami tych zmiennych.