Podstawy programowania grafiki

Patkoss

Podstawy niskopoziomowego programowania grafiki przy użyciu języków wysokiego poziomu.

W artykule tym zajmiemy się podstawami programowania grafiki w językach wysokiego poziomu (z wykorzystaniem języka Pascal), używając przy tym niskopoziomowych możliwości graficznych komputera osobistego, popularnie zwanego pecetem w języku polskim.

Artykuł przedstawia ogólne możliwości programowania grafiki, przytoczony tutaj kod będzie działał zarówno w systemie Linux jak i Windows. Jedynym ograniczeniem jest możliwość wywoływania funkcji niskopoziomowych przez wywołania Assembler'a. Tak więc Linux nie stwarza nam tutaj żadnych ograniczeń, niestety Windows (a jakże) w wersji XP nie zezwoli nam na tego typu ExPerymenty. Niemniej Windows 95/98 nie ma tego typu ograniczeń. Czego poza systemem operacyjnym potrzebować będziemy? Kompilatora języka Pascal. Dla Windows może to być znakomity Turbo Pascal Borland'a, dostępny już za darmo. Dla Linuxa mamy darmowy oczywiście Free Pascal Compiler, włączony w dystrybucję Debian GNU/Linux 3.0 "Woody", którego mam przyjemność używać.

Pierwszą rzeczą jaką zrobimy, aby uzyskać jakikolwiek efekt jest oczywiście edycja kodu. Odpalamy edytor i rozpoczynamy:

program gfx;
var x, y: word; {wspolrzedne x, y oraz c jako kolor}
    c   : byte;
{inicjacja trybu graficznego 320x200x256)
procedure initvga; assembler;
asm
  mov ah, 00h; {do gornej polowki rejestru AX liczba 0}
  mov al, 13h; {do dolnej polowki rejestru AX liczba 13h, dziesietnie 19}
  int 10h; {wywolujemy przerwanie karty graficznej}
end;
{powrot do trybu textowego}
procedure inittxt; assembler;
asm
  mov ah, 00h;
  mov al, 03h;
  int 10h;
end;
begin
end.

Jak nietrudno zauważyć tryb textowy ma numer 03h, a graficzny (320x200x256) 13h. Sprawa jest prosta. Ale nasz program na razie nic nie robi. Podstawowym narzędziem w grafice jest umiejętność zapalania pixeli na ekranie i matematyka.

Jeżeli ktoś zajmował się wcześniej BGI (Borland Graphics Interface) to z pewnością wie, że bardzo użyteczną procedura byla putpixel(). Napiszemy teraz naszą własną procedurę putpixel. To wystarczy. aby na ekranie otrzymywać rozmaite figury, w różnych kolorach, lub nawet soczyste fraktale - praktycznie stosując wiedzę matematyczną (o tym niestety nie ma w szkołach).

{procedura zapalajaca punkt na ekranie}
procedure putpixel (x, y: word; c: byte); assembler;
asm
  mov ah, 0Ch;
  mov al, c; {kolor pixela}
  mov cx, x; {koordynata pozioma pixela}
  mov dx, y; {koordynata pionowa pixela}
  int 10h;
end;

Potrafimy już ustawiać tryb graficzny, zapalać na ekranie pojedynczy pixel i to wszystko co nam potrzeba. Zajmijmy się więc wykorzystaniem powyższego kodu. Dodajmy do klauzuli stałych (w języku Pascal występuje ona po deklaracji zmiennych trzy stałe:

const mx=319; {wartość maxymalna x - od 0 do 319 = 320 punktow}
      my=199; {wartość maxymalna y - od 0 do 199 = 200 punktow}
      mc=255; {wartość maxymalna c - od 0 do 255 = 256 kolorow}

I możemy rozpoczynać w ciele głównym programu:

begin
  initvga;
  for x:=0 to mx do
    for y:=0 to my do putpixel(x, y, 10);
  inittxt;
end.

Ten kod zamaluje cały ekran na zielono. Co jeśli chcielibyśmy uzyskać z powrotem kolor czarny? Wystarczy zmienić parametr c (kolor) w procedurze putpixel() z 10 (kod koloru zielonego) na 0 (czarny).

A teraz wykorzystajmy to co ludzkość wie o podstawach matematyki. Załóżmy, że chcielibyśmy uzyskać wykres f-cji sin(x) na ekranie - sinusoida przypomina falę. Pierwsze co musimy zrobić to napisać funkcję, która będzie potrafiła konwertować stopnie na radiany. Łatwo możemy posługiwać się stopniami, natomiast komputer wymaga podawania radianów jako parametrów f-cji trygonometrycznyc:

function degtorad (deg: real): real;
begin
  degtorad:=deg*(((2*pi))/360);
end;
begin
(...)
for x:=0 to mx do putpixel(x, round(40*sin(degtorad(x))+100), 15);
(...)

Ten kod wyrysuje nam fragment sinusoidy na ekranie. Trygonometrię można także wykorzystać do wyrysowania okręgu na ekranie, znane jest bowiem trygonometryczne równanie okręgu:

x=r*cos(deg); y=r*sin(deg);

gdzie x, y to punkty leżące na okręgu, a r jest jego promieniem.

Czyścimy wiec ekran znanym już sposobem i wykorzystujemy to równanie w pętli. Zmienną i wykorzystujemy jako stopnie, aby okrąg się zamknął potrzeba kąta pełnego czyli 360 stopni. Do x i y wyliczonych w pętli, podczas wyświetlania w putpixel() należy dodać pewne wartość (u nas 100 i 100). Są to współrzędne środka okręgo. Aby okrąg nie składał się z punktów należy zwiększyć dokładność wyliczania stopni. A wiec np. wyliczać stopnie nie co 10, a np. co 1. A oto kod:

for x:=0 to mx do
  for y:=0 to my do putpixel(x, y, 0);
i:=0;
repeat
  x:=round(20*cos(degtorad(i)));
  y:=round(20*sin(degtorad(i)));
  putpixel (x+100, y+100, 15);
  i:=i+10;
until i>360;

Do kompilacji możemy użyć kompilatora Free Pascal'a lub powszechnego Turbo Pascala Borlanda.

Grafika komputerowa to bardzo obszerny temat. Programowanie niskopoziomowe może nie jest oszałamiające (na tym poziomie), lecz ma ogromną zaletę - jest szybkie. Oczywiście można wiele rzeczy usprawnić, np. operować bezpośrednio na pamięci graficznej, zamiast wywoływać funkcję Bios'u. Rekurencja jest techniką niezwykle użyteczną w programowaniu grafiki. Poza tym matematykę na razie wykorzystaliśmy w poziomie bardzo podstawowym. Ale to już temat na następny artykuł...

Patkoss

12 komentarzy

popatrzcie na tryb Vesy

jak chcecie sie uczyc programowania grafiki w pascalu na trybie 13h to zapraszam do kupna ksiazki "Tworzenie gier 2d i 3d w jezyku Turbo Pascal". Dobra ksiazka, zakupilem rok temu i nie zaluje, polecam wszystkim nawet malo zaawansowani zrozumieja intencje autora( Piotra Besty) i z kolejnymi dzialami poglebiaja wiedze.

Ciekawy artykul. Jeśli chcialbyś dowiedzieć się czegoś jeszcze nt. programowania grafiki z niskopoziomowego assemblera, bez jego znajomości zapraszam:

http://www.kskoczylas.ixwe.net

znajdziesz tam dzial download, a tam modul mojego autorstwa, który obsluguje 2 standardy. VGA 320x200x256 kol, i 320x200x16 bit ktory osiaga 500FPS. Zawiera podstawowe operacje takie jak odczyt bitmap i ich wyswietlanie, dzialanie podobne do DirectX. Na stronie znajdziesz tez wiele programow 3d demonstrujacych programowanie grafiki, oraz moja prace dyplomowa - Programowanie grafiki w Turbo Pascalu.
Kamil

do OcelotX: pascala da sie bardzo latwo przetlumaczyc na c, a delphi na c++

pascala da sie bardzo latwo przetlumaczyc na c, a delphi na c++

a sie bardzo latwo przetlumaczyc na c, a delphi na c++

O kurcze... używać przerwania do narysowania pixela to istne samobujstwo <lol> nie lepiej odwołać się bezpośrednio do pamięci karty graficznej?? Ekran zamalował by w ułamku sekundy <lol> można wtedy uzyskac nawet 1000FPS....

mam w chacie moduł tak szybki że wam gały wyjdą z orbit

tryb 13h jest taki raczej do zabawy. jak ktos lubi sie bawić z przerwaniami 103 , 118 :) mozna tak odpalic roz. 1582 x coś tam, ale funkcjonalnośc jest zerowa :). A co do grafy bgi....mozna też ją troche ponaginać z 16 na gdzieś ok 21 kolorów. Wiec jak ktoś lubi eksperymenty to powodzenia

czy ja wiem czy to takie szybkie??? ten ekran zamalowuje sie z 3-4 sec.....

Właśnie czegoś takiego szukałem (szukałem pod C, ale Pascala też trochę znam) :)

Ee ja tam wole bgi :P może i jest wolny ale łatwy:)