Pracuji na demu pro Forever 2027 (ano, raději dříve než později). U dem se totiž velmi snadno stane, že člověk v lednu prohlásí, jak má všechno krásně rozmyšlené, v únoru začne psát první efekt a v březnu zjistí, že Forever byl minulý víkend. Tentokrát jsem tedy začal s předstihem a když jsem přemýšlel jak celé demo pojmu, narazil jsem na režím LoRes - ano, demo bude pro ZX Spectrum Next. Na papíře vypadá tento režim skoro podezřele skromně: 128 krát 96 bodů, 16 barev a 6144 bajtů videopaměti. Jenže přesně tahle skromnost z něj dělá velmi užitečný nástroj. Obraz je dost malý na to, aby jej Z80N zvládal přepočítávat v reálném čase, ale pořád dost velký na tunely, plasmy, metabally, deformace, částicové efekty, jednoduché 3D nebo pořádně barevný herní svět.
ZX Spectrum Next / grafické režimy
LoRes: málo pixelů, hodně možností
Praktický pohled na lineární framebuffer, palety, dvě obrazovky, hardwarový scroll a efekty, které se do 6144 bajtů vejdou překvapivě pohodlně.
Proč se nízkého rozlišení nebát
Klasické ZX Spectrum má obrazovou paměť, jejíž adresování dokáže začátečníkovi zpestřit večer, pokazit náladu a v krajním případě ho přimět programovat raději tiskárny. Pixely nejsou uloženy po řádcích jednoduše za sebou a barvy navíc řídí samostatné atributy pro bloky 8 krát 8 bodů. Ale na tom není nic špatného, je potřeba oddělit zrno od plev :). LoRes jde ale opačnou cestou. Nabízí lineární framebuffer, ve kterém jsou řádky uloženy jeden za druhým, každý pixel má vlastní čtyřbitový barevný index a žádné atributové bloky neexistují.
Rozlišení 128 krát 96 se při zobrazení hardwarově roztáhne na aktivní plochu 256 krát 192, takže jeden logický bod vytvoří čtverec 2 krát 2 fyzické pixely. Výsledek má výrazný chunky vzhled, který se k demům, arkádám a stylizované grafice docela hodí. Není to režim pro sazbu daňového přiznání drobným písmem, ale na rotující neonový tunel je překvapivě vhodný.
Samotný název LoRes se někdy používá společně s označením Radastan. Zapnutí se skládá ze dvou
kroků. Bit 7 registru $15 povolí LoRes vrstvu v obrazovém
systému a bit 5 registru $6A zvolí Radastan podobu obrazu
128 krát 96 bodů se čtyřmi bity na pixel. Registr $15
současně určuje pořadí vrstev, takže v hotovém programu není dobré bezmyšlenkovitě opsat jednu
konstantu a doufat, že se sprity, Layer 2 a tilemap nějak domluví mezi sebou. Hardware je
poslušný, ale telepatii zatím další verze core nepřidala.
V jednoduchém samostatném efektu lze do registru $15
zapsat $80 a ostatní vrstvy vypnout. Ve větším demu je
potřeba zachovat správné pořadí spritů, Layer 2, ULA a LoRes vrstvy.
; Minimalni jadro inicializace
nextreg $15,$80 ; povolit LoRes vrstvu
nextreg $6A,$20 ; Radastan 128x96, prvni obrazovka
nextreg $26,0 ; horizontalni posun
nextreg $27,0 ; vertikalni posun
Dva pixely v jednom bajtu
Jeden pixel používá čtyři bity, takže jeden bajt obsahuje dva sousední body. Horní nibble patří
sudému bodu x, dolní nibble následujícímu lichému bodu.
Jeden řádek proto zabere 64 bajtů a celý obraz přesně
64 * 96 = 6144 bajtů. Pokud zapisujeme sudý pixel, musíme
zachovat dolní čtyři bity původního bajtu a novou barvu posunout do horních čtyř bitů. U lichého
pixelu je postup obrácený.
Obecná rutina pro jeden bod je užitečná pro čáry, částice, hvězdy nebo text, ale při kreslení
celé obrazovky bývá lepší pracovat rovnou s dvojicemi pixelů. Renderovací smyčka pak vyrobí oba
barevné indexy, spojí je do jednoho bajtu a jedním zápisem uloží dva body. Při kopírování
připravených řádků lze použít LDIR, při větších přesunech
DMA a u specializovaných efektů rozbalené smyčky. Jakmile se přestane volat univerzální
plot pro každý jednotlivý bod, začne těch 6144 bajtů
působit opravdu příjemně malým dojmem.
Lineární uspořádání je velká výhoda také pro převod grafiky na PC. Obrázek 128 krát 96 stačí převést na šestnáct barevných indexů, vždy dva indexy zabalit do jednoho bajtu a výsledný soubor nahrát přímo do videopaměti. Není potřeba přeskakovat mezi třetinami obrazovky ani sestavovat atributy. Stejně jednoduše lze generovat textury, výškové mapy, masky a předpočítané snímky. Je to starý dobrý obchod: trochu matematiky, trochu podvádění a divákovi samozřejmě řekneme jen o té matematice. :)
Šestnáct barev není jen šestnáct pevných barev
Čtyřbitový pixel vybírá index 0 až 15, skutečný odstín ale pochází z programovatelné ULA palety.
Barvy lze zapisovat v osmibitovém formátu RGB332, tedy tři bity červené, tři bity zelené a dva
bity modré, případně využít rozšířený devítibitový zápis palety. Šestnáct současně použitých
indexů proto nemusí připomínat původní spektráckou paletu. Mohou tvořit plynulou modrou rampu
pro vodu, fialovo-azurový neon, odstíny ohně, kovový lesk nebo několik zcela odlišných materiálů.
Registry $40, $41
a $43 slouží k výběru indexu, zápisu hodnoty a volbě
cílové palety. Po zápisu barvy se index automaticky posouvá, takže celou šestnáctici nahraje
krátká smyčka.
Spodní čtyři bity registru $6A navíc určují posun LoRes
palety. Čtyřbitové hodnoty framebufferu tak mohou vybírat různé šestnáctibarevné bloky z širší
paletové tabulky, aniž by bylo nutné přepisovat pixely. To se hodí pro změnu nálady scény,
barevné varianty objektů, přechody mezi částmi efektu nebo klasické palette cycling. Samotnou
paletu lze měnit také během obrazu, ideálně pomocí Copperu, a jednotlivé části obrazovky pak
mohou používat odlišné odstíny nad stejnými daty framebufferu. Když člověk mění paletu na každém
druhém řádku, je to působivý grafický trik.
Dvě obrazovky a žádné rozkreslené snímky
LoRes umí pracovat se dvěma obrazovými soubory, běžně dostupnými na
$4000 a $6000.
Bit 4 registru $6A určuje, který z nich se zobrazuje.
To přímo vybízí k double bufferu: zatímco první stránka svítí na monitoru, celý nový snímek
vzniká ve druhé. Po dokončení renderu program počká na obrazové přerušení a přepne jediný bit.
Hotový obraz se objeví naráz, bez viditelného mazání, trhání nebo horní poloviny nového tunelu
přilepené ke spodní polovině starého tunelu. V dalším snímku si obě stránky role vymění.
Oba buffery dohromady zaberou 12 kilobajtů, což je na poměry klasického Spectra citelná část
paměti, ale na Nextu jde o rozumnou cenu za čistou animaci. Není přitom povinné double buffering
používat. Statická obrazovka, pomalu doplňovaná mapa nebo efekt, který záměrně kreslí před
paprskem, si vystačí s jedním framebufferem. U celoplošných deformací a animací je dvojice stránek
téměř vždy pohodlnější. Při přepínání je vhodné zachovat všechny ostatní bity registru
$6A, především zapnutí režimu a paletový offset.
Scroll, vrstvy, průhlednost a další hračky
LoRes sdílí s ULA vrstvou registry $26 a
$27 pro horizontální a vertikální posun. Celou obrazovku
lze tedy hardwarově posouvat bez přesouvání jediného bajtu framebufferu. Jemný scroll se hodí
pro kameru, chvění obrazu, refrakci, vlnění nebo levný parallax. Když se posun mění po řádcích
Copperem, lze vytvořit vodní deformaci, zakřivení tunelu nebo horizontální vlny, zatímco Z80 dál
připravuje další snímek. Okraje odhalené posunem je samozřejmě potřeba promyslet. Hardware umí
hodně věcí, ale zatím neumí domalovat grafiku, kterou jsme zapomněli připravit - neptejte se mne jak to vím... :)
Protože je LoRes součástí obrazového systému Nextu, lze jej skládat se sprity, Layer 2, tilemapem
a podle nastavení také s klasickou ULA vrstvou. LoRes může tvořit rychlé procedurální pozadí,
zatímco ostré sprity nesou postavy a částice, tilemap zobrazuje herní prostředí nebo stavový panel
a Layer 2 přidává detailní logo či text. Globální transparentní barva z registru
$14 se vztahuje také na LoRes, takže vybraný výsledný odstín
může odkrýt vrstvu pod ním.
| NextReg | Úloha |
|---|---|
| $15 | Povolení LoRes a nastavení priority obrazových vrstev. |
| $6A | Radastan režim, výběr obrazovky a posun paletového bloku. |
| $40 / $41 | Index a hodnota zapisované barvy palety. |
| $43 | Výběr cílové palety a režimu zápisu. |
| $26 / $27 | Hardwarový posun celé ULA/LoRes vrstvy. |
| $14 | Globální transparentní barva pro skládání vrstev. |
Co se v LoRes dá dělat
Nízké rozlišení s vlastní barvou každého pixelu výborně sedí efektům založeným na tabulkách a jednoduché matematice. Plasma může sčítat několik sinusových průběhů, tunel používá předpočítané polární souřadnice, metabally skládají několik vzdálenostních polí a bump mapping odhaduje normálu z rozdílů sousedních vzorků. Výšková mapa dovolí voxelovou krajinu, zpětná vazba zase oheň, kapalinu nebo rozmazané světelné stopy. Čtyřbitové textury jsou malé, takže se jich do paměti vejde hodně a dobře se kopírují mezi bankami. Pro chunky 3D lze kreslit vyplněné polygony, rotující objekty nebo jednoduchý raycaster. Hrubší pixely přitom část numerických nepřesností schovají, což je vlastnost, kterou budeme samozřejmě vydávat za umělecký styl.
Od dema k malému tutorialu
V demu pro Forever 2027 používám LoRes u několika výrazně složitějších částí. Jsou tam předpočítané mapy, bankování, palety měněné podle fáze efektu, dvojité buffery a renderovací smyčky optimalizované pro konkrétní obraz. Pro vysvětlení samotného režimu je takový kód příliš složitý. Proto jsem z něj oddělil malý samostatný projekt Neon Ribbons - který se ale v demu (myslím tím, tento konkrétní efekt) jako takovém nepoužívá. Obsahuje rutinu pro inicializaci LoRes, nahrání palety, vyčištění obou stránek, výběr zadního bufferu, page flip a zápis jednoho pixelu. Nad touto základní vrstvou běží jednoduchý efekt, který kopíruje barevnou texturu po řádcích, posouvá ji sinusovou tabulkou a přes obecnou pixelovou rutinu doplňuje několik jisker.
Celý příklad se vejde přibližně do 1,25 kilobajtu kódu a tabulek a nepotřebuje žádná externí grafická data. Není to pokus o nejsložitější efekt, ale čitelný základ pro vlastní experimenty. Stačí vyměnit paletu, upravit tabulku vlny, nahradit texturu vlastním obrázkem nebo místo kopírování řádků začít počítat pixely. Jakmile funguje přepínání obrazovek a člověk ví, ve kterém nibblu bydlí který bod, je zbytek už příjemná grafická práce.
Teď už jen něco pěkného nakreslit
Pokud někomu tento tutoriál pomůže, budu jen rád. Pokud ho přejdete a upadne v zapomnění, já si na něj jistě po čase vzpomenu, protože se mi v budoucnosti jistě bude hodit... ;) Níže je odkaz na ukázkový kód a spustitelný NEX soubor pro ZX Spectrum Next. A tímto se Vám omlouvám za pauzu ve vydávání článků - teď už víte proč jsem nic nepsal - mám plné ruce práce.


1 Comment
Hlavně si to pořád zachovává smysluplný poměr stran pixelů jako originál, ne nějaké šišaté poměry jako C64, DVD atd. Pixel má být čtverec, tečka.