OpenGL (16.) - Fading

Ve starých dobách DOSu bylo ztmavení obrazovky relativně snadné - stačilo jen při každém snímku dekrementovat paletu. Nyní v době 16ti nebo 32ti bitů vzniká problém s tím, že paletu nemáme. Pokud chcete tak můžete ztmavit pixel po pixelu odečtením jedničky od každé RGB hodnoty, já jsem na to šel trochu jinak...

Základní myšlenka je vhodně umístit černý obdelník tak, aby zakrýval celou plochu obrazovky. Jemu budeme měnit průhlednost podle toho, jestli chceme zesvětlení nebo ztmavení scény. Proměnné FadeOut a FadeIn nám budou při vykreslování říkat, jestli máme průhlednost pro snímek zvýšit nebo snížit. Alpha je pak samotná průhlednost.

type KFadeC = class
       private
       public
         FadeOut: boolean;            //setmeni
         FadeIn: boolean;             //zesvetleni
         alpha: single;
         DisplayWidth, DisplayHeight: integer;
         procedure SetFadeOut;
         procedure SetFadeIn;
         function Draw(ElapsedTime: single): boolean;
         constructor Create;
     end;

V proměnných DisplayWidth a DisplayHeight si uchováváme rozlišení obrazovky. Pro ztmavení bude sloužit procedura SetFadeOut, pro zesvětlení SetFadeIn.

//Setmeni
procedure KFadeC.SetFadeOut;
begin
  FadeIn := false;
  FadeOut := true;
  Alpha := 0;
end;

//Zesvetleni
procedure KFadeC.SetFadeIn;
begin
  FadeOut := false;
  FadeIn := true;
  Alpha := 1;
end;

A hlavní část dnešního kódu je zde. Po každém vyrenderování scény zavoláme funkci Draw s parametrem kolik času trvala poslední smyčka renderování. Tato hodnota je velmi důležitá pro plynulost jak setmívání ale i jiných událostí ve hře (hlavně pohyb).

function KFadeC.Draw(ElapsedTime: single): boolean;
begin
  if FadeOut or FadeIn then begin

    glMatrixMode (GL_PROJECTION);
    glPushMatrix;
    glLoadIdentity;
    glOrtho (0,DisplayWidth,DisplayHeight,0,-1000,1000);
    glMatrixMode (GL_MODELVIEW);
    glPushMatrix;
    glLoadIdentity;
    glPushAttrib (GL_DEPTH_BUFFER_BIT or GL_ENABLE_BIT or GL_COLOR_BUFFER_BIT);
    glDisable (GL_DEPTH_TEST);

    if Alpha < 0 then begin
      FadeIn := false;
    end else
    if (Alpha >= 0) AND (Alpha <= 1 ) then begin
      glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
      EnableBlending;
      if FadeOut then
        Alpha := Alpha + ElapsedTime / 5 //5 udává počet sekund
      else
        Alpha := Alpha - ElapsedTime / 5;
      glColor4f(0, 0, 0, Alpha);
      glRectd(0, 0 , DisplayWidth, DisplayHeight);
      DisableBlending;
    end else
    if Alpha >= 1 then begin
      glColor3f(0, 0, 0);
      glRectd(0, 0 , DisplayWidth, DisplayHeight);
    end;

    glEnable(GL_DEPTH_TEST);
    glPopAttrib;
    glPopMatrix;
    glMatrixMode (GL_PROJECTION);
    glPopMatrix;
    glMatrixMode (GL_MODELVIEW);
    result := true;
  end else result := false;
end;

Teď bych měl zdroják trošku vysvětlit. Pokud je aktivní buď zesvětlování nebo setmění scény, pak voláním glOrtho změníme pohled. Nový rozsah v okně OpenGL je v ose X 0 až 640, v ose Y 0 až 480 a v ose Z -100 až 100. To uděláme proto, aby se nám lépe umisťoval text na obrazovku. Je li alpha menší než jedna, pak ukončíme zesvětlování. Je-li větší jak jedna, pak zobrazíme přes celou obrazovku černý čtverec a ukončíme ztmavování. Je-li Alpha v rozsahu od 0 do 1, pak povolíme a nastavíme průhlednost a také vykreslíme poloprůhledný obdelník přes celou obrazovku. Pak načteme zpět uložené matice.

V samotném programu pak stačí volat:

var 
  Fade: KFadeC;
begin
  Fade := KFadeC.Create;
  Fade.DisplayWidth := Width;
  Fade.DisplayHeight := Height;
  Fade.SetFadeIn;

Pak v renderovací smyčce voláme(ElapsedTime je v sekundách):

  Fade.Draw(ElapsedTime);

Tímto jsme docílili vlastnosti, že po zavolání SetFadeIn se obrazovka začne pomalu zesvětlovat (asi 5 sekund) až do normálu, pak už se nic neděje. Zavoláme-li SetFadeOut, obrazovka se začne stmívat až do černé, kde zůstane - GAME OVER.

Tento efekt (ale asi jiným algoritmem) je využit snad ve všech hrách a teď si ho můžete jednoduše vytvořit i vy. Co se týče rychlost, pak klesne zhruba o 10 fps - Při startu nebo ukončení hry nám to moc nevadí a navíc to vypadá pěkně...

Pro zajímavost jsem tento kus zdrojáku vyšťoural ze hry quake2. Je vidět, že na stmavení obrazovky šli podobně - přes obdelník vykreslený přes celou obrazovku. Nejedná se o plynulý fading, ale stmavení v menu ap.

void Draw_FadeScreen (void)
{
	qglEnable (GL_BLEND);
	qglDisable (GL_TEXTURE_2D);
	qglColor4f (0, 0, 0, 0.8);
	qglBegin (GL_QUADS);

	qglVertex2f (0,0);
	qglVertex2f (vid.width, 0);
	qglVertex2f (vid.width, vid.height);
	qglVertex2f (0, vid.height);

	qglEnd();
	qglColor4f (1,1,1,1);
	qglEnable (GL_TEXTURE_2D);
	qglDisable (GL_BLEND);
}

Vyšlo 30.10.2002, v blogu: 0 1 2 3 4 5 6 7 8

Děkuji, že jste se rozhodl(a) přečíst tento článek. Budu rád i za komentář. Pokud Vás tento článek zaujal a rádi byste jej doporučili ostatním, podpořte mně prosím tím, že věnujete minutku svého času a uděláte mi reklamu na linkuj.cz, vybrali.sme.sk či jagg.cz. Přeji příjemné čtení

Poslední články

Diskuse k blogu

Zatím nikdo nevložil komentář. Chcete být první? Přidání příspěvku
©PC-guru.cz 2000-2008 | Optimalizováno pro 1024*768