OpenGL (2.) - Čtverec s texturou

Minule jsme si vysvětlili, jak napsat základní aplikaci využívající OpenGL. Dnes tyto znalosti trochu rozšíříme přidáním textury na náš čtverec. Vždyť bez textur bychom se vlastně nikam nedostali.

K vysvětlení dnešního tématu jsem využil zdroják z minulého dílu. Všechny změny průběžně vysvětlím, nebude jich však mnoho. Výsledku se dá dosáhnout za okamžik, leč psaní článku zabere celé odpoledne... Při spuštění programu se zavolá procedura TForm1.create, ve které provedeme inicializaci OpenGL.

procedure TForm1.FormCreate(Sender: TObject);
beginj
  UhelX := 0;
  UhelY := 0;
  UhelZ := 0;
  X := 0.0; Y := 0; Z := -4.0;
  SetcursorPos(left+round(width/2),top+70);
  bool:=true;
  Model := 1;

  //inicializace OpenGL
  SetDCPixelFormat(Canvas.Handle);
  hRC := wglCreateContext(Canvas.Handle);
  wglMakeCurrent(Canvas.Handle,hRC);
  glClearColor(0.0,0.0,0.0,0.0);
  glShadeModel(GL_FLAT);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_Texture_2D);
  glPixelStorei(GL_Unpack_Alignment,2);
  glTexParameterf(GL_Texture_2D,GL_Texture_Wrap_S,GL_Repeat);
  glTexParameterf(GL_Texture_2D,GL_Texture_Wrap_T,GL_Repeat);
  glTexParameterf(GL_Texture_2D,GL_Texture_Mag_Filter,GL_Linear);
  glTexParameterf(GL_Texture_2D,GL_Texture_Min_Filter,GL_Linear);
  glTexEnvf(GL_Texture_Env, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  Ctverec;
  NastaveniProstoru;
  wglMakeCurrent(0,0)
end;

Funkcí glClearColor vymažeme buffery základních barev (RGBA). Funkce glShadeModel slouží k přepínání typu stínování. GL_FLAT - je obyčejné stínování. Stín je znázorňován pomocí hrubě odstupňovaných širokých pruhů. Další vlastnost je (GL_SMOOTH). Je to dokonalejší typ stínování. Zde je stín již reprezentován plynulým, hladkým přechodem, využívajícím širokou část dostupné barevné palety. Dále otestujeme velikost bufferu a zapneme zobrazení 2D textury příkazem glEnable. funkcemi glTexParameterf nastavíme vlastnosti 2D textury. Nakonec zavoláme další procedury ctverec a nastavení prostoru.

procedure TForm1.Ctverec;
var Cesta : string;
begin
  Cesta := ExtractFilePath(Application.ExeName);

  glNewList(Model,GL_COMPILE_AND_EXECUTE);
  LoadBitmap(Cesta + 'Image1.bmp');
  glTexImage2d(GL_Texture_2D,0,3,Velikost,Velikost,
  	0,GL_RGB,GL_Unsigned_byte,@buffer);
  glBegin(GL_POLYGON);
    glTexCoord2f(0,0);
    glVertex3f( 0.5,-0.5,0.0);
    glTexCoord2f(1,0);
    glVertex3f(-0.5,-0.5,0.0);
    glTexCoord2f(1,1);
    glVertex3f(-0.5, 0.5,0.0);
    glTexCoord2f(0,1);
    glVertex3f( 0.5, 0.5,0.0);
  glEnd;
  glEndList
end;

V proceduře ctverec je funkce glNewList. Ta spolu s funkcí glEndList vytváří nebo nahrazují seznam příkazů. Tyto seznamy jsou skupiny OpenGL příkazů, které jsou připravené pro následné spuštění. Všechny následující příkazy jsou uloženy do seznamu. Model je číslo integer, které specifikuje jméno daného seznamu. Slouží jako jednoznačná identifikace daného seznamu. GL_COMPILE specifikuje mód kompilace. V tomto případě jsou příkazy jen zkompilovány. Další možná hodnota je (GL_COMPILE_AND_EXECUTE).

Funkcí LoadBitmap natáhneme bitmapu do seznamu a funkcí glTexImage specifikujeme vlastnosti dvourozměrné bitmapy: Barevná textura s max. detailem velikosti 256*256. Mezi funkcemi glBegin a glEnd definujeme trar a vlastnosti objektu. Parametry funkce glBegin mohou být (GL_POLYGON, GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS, GL_QUAD_STRIP).

Dále zavoláme proceduru Nastaveni prostoru, kterou jsme minule měli obsaženou přímo v proceduře Create.

procedure TForm1.NastaveniProstoru;
begin
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(30.0,ClientWidth / ClientHeight,0.01,50.0);
  glViewport(0,0,ClientWidth,ClientHeight);
end;

Matici zobrazení prostoru nastavíme příkazem glMatrixMode na GL_PROJECTION a tuto nastavenou matici načteme příkazem glLoadIdentity. Nyní nastavíme prostor tak, jak se bude jevit z pozice kamery funkcí gluPerspective a velikost zobrazované plochy nastavíme funkcí glViewport.

procedure TForm1.FormPaint(Sender: TObject);
begin
  wglMakeCurrent(Canvas.Handle,hRC);
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  VlastnostiObjektu;
  glCallList(Model);
  glFlush;
  SwapBuffers(Canvas.Handle);
  wglMakeCurrent(0,0)
end;

Tato procedura slouží ke zobrazení scény. funkcí wglMakeCurrent Nastavíme daný RC jako aktuální. Funkcí glClear vymažeme buffery. GL_COLOR_BUFFER_BIT - maže buffer, který je právě vybrán pro barevné kreslení. GL_DEPTH_BUFFER_BIT - maže hloubku bufferu. GL_ACCUM_BUFFER_BIT - maže akumulační buffer, GL_STENCIL_BUFFER_BIT - maže buffer barvy na malování šablonou. Nyní zavoláme funkci vlastnosti objektu a příkazem glCallList načteme námi definovaný seznam příkazů pro náš objekt. Následuje funkce SwapBuffers, kterou vyměníme buffery a funkcí wglMakeCurrent vynulujeme handlery.

procedure TForm1.VlastnostiObjektu;
begin
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
  glTranslatef(X,Y,Z);	//pozice kamery
  glTranslatef(0,0,0);	//střed rotace objektu
  glRotatef(UhelX, 1, 0, 0);	//rotace objektu v ose X
  glRotatef(UhelY, 0, 1, 0);	//rotace objektu v ose Y
  glRotatef(UhelZ, 0, 0, 1);	//rotace objektu v ose Z
end;

Příkazem glMatrixMode nastavíme matici zobrazení objektu a příkazem glLoadIdentity tuto matici načteme. Nastavíme pozici kamery - glTranslatef(x,y,z) a střed rotace objektu - glTranslatef(0,0,0). Funkcí glRotatef nastavíme rotaci objektu v osách x, y a z.

procedure TForm1.LoadBitmap(Path : string);
var
 X : TImage;
 bih : TBitmapInfoHeader;
 bi : TBitmapInfo;
 b : byte;
 i,j : word;
begin
  X := TImage.Create(Self);
  X.Picture.LoadFromFile(Path);
  with bih do
    begin
      biSize := SizeOf(bih);
      biWidth := Velikost;
      biHeight := Velikost;
      biPlanes := 1;
      biBitCount := 24;
      biCompression := BI_RGB;
      biSizeImage := Velikost;
      biXPelsPerMeter := 0;
      biYPelsPerMeter := 0;
      biClrImportant := 0;
      biClrUsed := 0;
    end;
  bi.bmiHeader := bih;
  GetDIBits(X.Picture.Bitmap.Canvas.Handle,X.Picture.Bitmap.Handle,
            0,Velikost,@buffer,bi,dib_rgb_colors);
  for i := 1 to Velikost do
    for j := 1 to Velikost do
      begin
        b := buffer[i,j].red;
        buffer[i,j].red := buffer[i,j].blue;
        buffer[i,j].blue := b;
      end;
  X.Free
end;

Tato funkce načte bitmapu o velikosti 256*256 pixelů ze souboru a prohodí červenou a modrou složku. Bitmapu jiné velikosti je nutno upravit tak, aby její šířka a výška byly mocninou dvou.

Procedury pro pohyb a rotaci našeho čtverce s texturou jsem použil ty samé jako v minulém dílu našeho seriálu, stejně jako procedury pro ukončení a změnu velikosti okna aplikace.

Odtud (230 kB) si můžete stáhnout zdroják toho, co jsme dnes vytvořili i s texturou.

Vyšlo 20.09.2001, 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