Úvod

Článkov o počítačovej grafike je na internete pomerne veľké množstvo. Väčšinou však popisujú počítačovú grafiku použitím rôznych grafických API, najčastejšie priemyselnými štandardmi OpenGL alebo DirectX. Menej sa už zaoberajú matematikou na pozadí, počítačovou geometriou, zobrazovacími metódami, všeobecne výpočtovou geometriou. Štandardné grafické API záležitosti okolo matematiky už majú naprogramovanú a slúžia práve na to, aby boli aplikované na vyriešenie nejakého konkrétneho grafického problému a aby programátor nestrácal čas programovaním niečoho, čo už je naprogramované. Navyše programovať v takej forme a kvalite akú definovali tieto grafické štandardy je pri samostatnom úsilí programátora ťažko dosiahnuteľné, resp. bolo by potrebné vynaložiť neadekvátne množstvo času, čo v dnešnej rýchlej dobe už takmer neprichádza do úvahy. Samozrejme, nie vždy si človek vystačí plne s grafickým API, najmä ak je potrebné riešiť nejaké zložitejšie grafické konštrukcie. Vtedy je nutné použiť širšie poznatky z výpočtovej geometrie.

Na nasledujúcich článkoch z kategórie počítačovej grafiky na tomto blogu si popíšeme základné grafické prvky, ktoré zvyknú byť súčasťou každého grafického API. Celé to bude smerovať k realistickému zobrazovaniu priestorových objektov bez použitia grafických knižníc alebo frameworkov. Teda výstupom niektorých článkov bude spustitelný program riešiaci konkrétnu problematiku. Cieľom bude názornejšie vysvetlenie a pochopenie princípov jednotlivých geometrických problémov počítačovej grafiky.

Kostra aplikácie

Vytvoríme si základnú aplikáciu, ktorú budeme postupne rozširovať. Bude sa jednať o non-real time aplikáciu, oproti napr. knižniciam OpenGL alebo DirectX, to znamená, že grafický výstup budeme produkovať len v prípade potreby. Štruktúra samotnej kostry aplikácie, ktorá bude priebežne upravovaná, bude podobná mnohým grafickým API. Dôraz bude kladený na prehľadnosť, jednoduchosť, a preto aplikácia bude popisovaná v jazyku C# (ako konzolová). Pôvodne som napísal kostru aplikácie v jazyku C++, ale tento jazyk podľa mňa nie je celkom vhodný pre prehľadné a názorné písanie programov, zvlásť v tomto prípade. Pri programovaní väčšiny grafických aplikácií je z hľadiska rýchlosti a profesionality jazyk C++ prvou voľbou, avšak jednak sa nebudeme zaoberať príliš zložitými výpočtami a jednak prioritná pre nás bude určitá prehľadnosť, jasná pochopiteľnosť.

Aplikáciu vytvoríme v jazyku C# napr. pomocou Microsoft Visual Studia ako konzolovú. Základná metóda Main() vyzerá nasledovne:

Okrem procesu na konci obsahuje len dve triedy Canvas a Color, ktoré si podrobnejšie popíšeme neskôr. Princíp je jednoduchý, konštruktor triedy Canvas vytvorí „plátno“, dvojrozmerné pole definovanej veľkosti, na ktoré budeme zapisovať jednotlivé farebné pixely. To isté čaká konštruktor triedy Color, kde si nastavíme farbu pomocou kombinácie zložiek červenej, zelenej a modrej farby. Volaním metódy clearColor() inštancie canvas vyplníme obsah dvojrozmerného poľa na nami zvolenú farbu. Metóda render() inštancie canvas takto vytvorené plátno uloží do súboru s názvom frame formátu PPM. Postupne si popíšeme jednotlivé triedy a metódy.

Trieda Color

Definovanie farby je jednou z najdôležitejších častí každého grafického API. Budeme používať najrozšírenejší farebný systém, aditívny trojfarebný systém, kde každý pixel je reprezentovaný troma farbami, červenou, zelenou a modrou.

Trieda je jednoduchá, konštruktor zapíše tri farby typu byte (unsigned char, v rozmedzí od 0 až 255) do premenných jednotlivých zložiek farieb, pričom k týmto zložkám budeme pristupovať cez property mechanizmus. V každom property je možné vynechať telo funkcie get/set, pretože pokiaľ dané funkcie riešia len jednoduchý prístup čítania a zápisu, tak nie je potrebné ich plne implementovať. Ale pre lepšiu názornosť budeme vždy rozpisovať aj triviálne záležitosti, čo neskôr pri zložitejšej problematike oceníme.

Táto trieda ako aj ostatné sa budú časom rozširovať v závislosti od konkrétnej problematiky. Väčšinou si vystačíme s takouto formou, akurát pri realistickom zobrazovaní scén bude vyzerať táto trieda objemnejšie. V každom prípade o farbách bude napísaný samostatný článok.

Trieda Canvas

Ak už máme definované farby, je potrebné ich niekam zapísať. Na to budeme potrebovať určité „plátno“. Nebude to nič iné ako dvojrozmerné pole pixelov, kde každý pixel bude pozostávať z troch zložiek farby.

Trieda obsahuje jednoduché základné prvky pre prácu s grafikou. Predtým, než začneme zapisovať na plátno, konkrétne do poľa canvas, musíme zavolať metódu clearColor(), aby dané pole inicializovala na hodnoty nami zvolenej farby. Možno by bolo vhodné to ošetriť priamo v konštruktore, ale takto je každá metóda transparentná a slúži svojmu účelu. Ďalšie metódy slúžia na čítanie a zápis pixelov plátna.

Metóda render() uskutočňuje prepis pixelov z plátna do grafického súboru. Jedná sa o formát PPM, Portable Pixmap, ktorý je bezstratový a svojou špecifikáciou jeden z najjednoduchších formátov. Podrobný popis tohto formátu si môžte nájsť na webe. Pre naše účely si ho tu nebudeme teoreticky detailne popisovať, pričom zdrojový kód tohto tento formátu je pre množstvo programovacích jazykov dostupný tak pre čítanie ako aj zápis na adrese: http://rosettacode.org/wiki/Bitmap/Write_a_PPM_file a http://rosettacode.org/wiki/Bitmap/Read_a_PPM_file.

Zdrojový kód na uvedenej stránke zápisu PPM súboru pre jazyk C# z doposiaľ nezistených príčin nefunguje, pretože ak som tento kód prepísal pre naše účely, obraz sa nezobrazoval správne (bol vertikálne pruhovaný a rozpadnutý). Zdrojový kód pre jazyk C fungoval bez problémov. Tak som teda skúsil prepísať kód pre jazyk C do jazyka C# a následne sa obraz vykresľoval správne.

Takže pôvodná verzia kódu v jazyku C# zo stránky Rosetta Code pre zápis pixelov do formátu PPM:

Prepísaná verzia podľa vzoru z jazyka C do C#:

Jediná zmena bola v tom, že nezapisujeme farby do inštancie triedy BinaryWriter po jednotlivých zložkách, ale v jednom kroku zapíšeme pole bajtov troch farieb s definovaným začiatočným indexom (v tomto prípade 0, v jazyku C, 1) a počtom zložiek, bajtov. Uvedený program by bolo možné napísať na viac spôsobov, ale kľúčový bol asi ten posledný riadok zápisu metódy Write(buffer, index, count).

Zdrojový kód pre čítanie formátu PPM v jazyku C# zo stránky Rosseta Code je plne funkčný. Ako je možné vidieť v našich zdrojových kódoch sa nevyskytuje. Čítanie má na starosti práve ten proces uvedený na začiatku tohto článku v metóde Main():

Takýmto spôsobom spustíme program Frame (súbor „Frame.exe“) s parametrom nášho obrázku „frame.ppm“. Program Frame.exe som vytvoril ako samostatnú jednoduchú aplikáciu v .NET s jedným formulárovým oknom, kontainerom pre pixely grafických súborov a dvoma tlačidlami, jedným na otvorenie obrázku vo formáte PPM a druhým uloženie obrázku do formátu BMP, GIF, PCX, prostredníctvom vstavaných .NET knižníc pre prácu s grafikou.

Takže, keď skompilujeme našu základnú grafickú aplikáciu, vytvorí sa súbor „frame.ppm“, ktorý bude automaticky otvorený programom Frame a zobrazený v grafickom okne tohto programu.

Vyrenderovaný obrázok PPM otvorený programom Frame

Ako určitý test správnosti vykreslenia môžme upraviť zložky R, G, B, pri zapisovaní PPM súboru z pôvodných kódov od Rosetta Code, kde pre zložku R = y % 256, G = x % 256, B = (x*y) % 256 dostaneme nasledujúci zaujímavý obrázok.

Testovací obrázok

Samozrejme, nemusíme to robiť takýmto spôsobom, ale zdalo sa mi to pohodlnejšie, ako neustále otvárať vygenerovaný grafický súbor „frame.ppm“ v nejakom externom programe, ktorý dokáže čítať súbory typu PPM. Medzi voľne dostupné programy, ktoré vedia čítať a niektoré aj zapisovať formát PPM patria: Ivan View, Irfan View a Gimp.

Bolo by možné použiť priamo .NET knižnice, triedy Canvas, Bitmap, Graphics a nerobiť to takýmto ťažkopádnym spôsobom, lenže práve o tom by mali byť tieto články, použiť čo najmenej externých prostriedkov a porozumieť tak hlbšie princípu počítačovej grafiky.

Čo sa týka literatúry, ktorú budem používať pri písaní týchto článkov, niektoré teoretické princípy najmä formálneho charakteru budem popisovať podľa knihy Moderní počítačová grafika, J.Žára a kol., 2004 a Základy počítačovej grafiky: geometrická problematika, J.Zámožík, 1999.

You may also like...