OpenGL (5.) - Urychlení pomocí glDrawElements
Dnes se dostávám k psaní dalšího článku, ve kterém vám ukáži pár způsobů, jak zlepšit dosavadní práci. Mezi novinky patří vytvoření odděleného procesu, tzv. thread, který se používá místo časovače a volání funkce glDrawElements, která se rovněž významný podílí na zvýšení fps.
Aplikace používá místo časovače oddělený proces Thread,
function Tread(P : pointer) : integer;
var
i: integer;
begin
i := 1;
repeat
Form1.Repaint;
until
i = 2;
end;
který se vytvoří touto funkcí volanou v TForm1.create:
Handles := BeginThread(nil, 0, Tread, nil, 0, ThreadID);
![]() |
| Popis obrázku |
Největší změna oproti předešlým dílům je volání funkce glDrawElements. V proceduře InicializaceOpenGL je zavolána další procedura InitElements, která vypadá následově:
procedure TForm1.InitElements;
var
Path : string;
begin
Path := ExtractFilePath(Application.ExeName);
//nacteni textur
LoadBitmap(Path + 'floor.bmp');
glGenTextures(1, @textura[1]);
glBindTexture(GL_TEXTURE_2D, textura[1]);
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);
glTexImage2d(GL_Texture_2D,0,3,Velikost,Velikost,0,GL_RGB,
GL_Unsigned_byte,@buffer);
LoadBitmap(Path + 'wall.bmp');
glGenTextures(1, @textura[2]);
glBindTexture(GL_TEXTURE_2D, textura[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);
glTexImage2d(GL_Texture_2D,0,3,Velikost,Velikost,0,GL_RGB,
GL_Unsigned_byte,@buffer);
//**************************************************************************
//1. ctverec
VertexPointer1[0].X := 0; //Pozice bodu 1 v ose x
VertexPointer1[0].Y := 0; //Pozice bodu 1 v ose y
VertexPointer1[0].Z := 0; //Pozice bodu 1 v ose z
CoordPointer1[0].S := 0; //Texturova koordinace bodu 1
CoordPointer1[0].K := 0; //Texturova koordinace bodu 1
Indices1[0] := 0; //Identifikace bodu 1
VertexPointer1[1].X := 10;
VertexPointer1[1].Y := 0;
VertexPointer1[1].Z := 0;
CoordPointer1[1].S := 1;
CoordPointer1[1].K := 0;
Indices1[1] := 1;
VertexPointer1[2].X := 10;
VertexPointer1[2].Y := 0;
VertexPointer1[2].Z := 10;
CoordPointer1[2].S := 1;
CoordPointer1[2].K := 1;
Indices1[2] := 2;
VertexPointer1[3].X := 0;
VertexPointer1[3].Y := 0;
VertexPointer1[3].Z := 10;
CoordPointer1[3].S := 0;
CoordPointer1[3].K := 1;
Indices1[3] := 3;
//2. ctverec
VertexPointer2[0].X := 10;
VertexPointer2[0].Y := 0;
VertexPointer2[0].Z := 0;
CoordPointer2[0].S := 0;
CoordPointer2[0].K := 0;
Indices2[0] := 0;
VertexPointer2[1].X := 20;
VertexPointer2[1].Y := 2;
VertexPointer2[1].Z := 0;
CoordPointer2[1].S := 1;
CoordPointer2[1].K := 0;
Indices2[1] := 1;
VertexPointer2[2].X := 20;
VertexPointer2[2].Y := 2;
VertexPointer2[2].Z := 10;
CoordPointer2[2].S := 1;
CoordPointer2[2].K := 1;
Indices2[2] := 2;
VertexPointer2[3].X := 10;
VertexPointer2[3].Y := 0;
VertexPointer2[3].Z := 10;
CoordPointer2[3].S := 0;
CoordPointer2[3].K := 1;
Indices2[3] := 3;
//leva stena
VertexPointer3[0].X := 0;
VertexPointer3[0].Y := 0;
VertexPointer3[0].Z := 0;
CoordPointer3[0].S := 0;
CoordPointer3[0].K := 2;
Indices3[0] := 0;
VertexPointer3[1].X := 0;
VertexPointer3[1].Y := 2;
VertexPointer3[1].Z := 0;
CoordPointer3[1].S := 0;
CoordPointer3[1].K := 0;
Indices3[1] := 1;
VertexPointer3[2].X := 20;
VertexPointer3[2].Y := 2;
VertexPointer3[2].Z := 0;
CoordPointer3[2].S := 10;
CoordPointer3[2].K := 0;
Indices3[2] := 2;
VertexPointer3[3].X := 10;
VertexPointer3[3].Y := 0;
VertexPointer3[3].Z := 0;
CoordPointer3[3].S := 5;
CoordPointer3[3].K := 2;
Indices3[3] := 3;
//zadni stena
VertexPointer4[0].X := 0;
VertexPointer4[0].Y := 0;
VertexPointer4[0].Z := 0;
CoordPointer4[0].S := 4;
CoordPointer4[0].K := 2;
Indices4[0] := 0;
VertexPointer4[1].X := 0;
VertexPointer4[1].Y := 0;
VertexPointer4[1].Z := 10;
CoordPointer4[1].S := 0;
CoordPointer4[1].K := 2;
Indices4[1] := 1;
VertexPointer4[2].X := 0;
VertexPointer4[2].Y := 2;
VertexPointer4[2].Z := 10;
CoordPointer4[2].S := 0;
CoordPointer4[2].K := 0;
Indices4[2] := 2;
VertexPointer4[3].X := 0;
VertexPointer4[3].Y := 2;
VertexPointer4[3].Z := 0;
CoordPointer4[3].S := 4;
CoordPointer4[3].K := 0;
Indices4[3] := 3;
//prava stena
VertexPointer5[0].X := 0;
VertexPointer5[0].Y := 0;
VertexPointer5[0].Z := 10;
CoordPointer5[0].S := 10;
CoordPointer5[0].K := 2;
Indices5[0] := 0;
VertexPointer5[1].X := 0;
VertexPointer5[1].Y := 2;
VertexPointer5[1].Z := 10;
CoordPointer5[1].S := 10;
CoordPointer5[1].K := 0;
Indices5[1] := 1;
VertexPointer5[2].X := 20;
VertexPointer5[2].Y := 2;
VertexPointer5[2].Z := 10;
CoordPointer5[2].S := 0;
CoordPointer5[2].K := 0;
Indices5[2] := 2;
VertexPointer5[3].X := 10;
VertexPointer5[3].Y := 0;
VertexPointer5[3].Z := 10;
CoordPointer5[3].S := 5;
CoordPointer5[3].K := 2;
Indices5[3] := 3;
glEnableClientState(GL_COLOR_ARRAY); //aktivuje pole barev
glEnableClientState(GL_VERTEX_ARRAY); //aktivuje pole bodu
glEnableClientState(GL_TEXTURE_COORD_ARRAY); //akt. pole tex. koordinaci
glColorPointer( 4, GL_UNSIGNED_BYTE, 0, @Buffer ); //nacte pole barev
end;
Samozřejmostí je, že máme všechny proměnné nadefinovány:
//body
type TVertexPointer = array [0..100] of record
X: TGLFloat;
Y: TGLFloat;
Z: TGLFloat;
end;
//texturova koordinace
type TCoordPointer = array [0..100] of record
S: TGLFloat;
K: TGLFloat;
end;
//indikator poli
type TIndices = array [0..100] of TGluInt;
var VertexPointer1, VertexPointer2, VertexPointer3,
VertexPointer4, VertexPointer5 : TVertexPointer;
CoordPointer1, CoordPointer2, CoordPointer3,
CoordPointer4, CoordPointer5 : TCoordPointer;
Indices1, Indices2, Indices3, Indices4, Indices5: TIndices;
Funkce "GLDrawElements" načítá tyto pole barev, texturových koordinací, pozic bodů a z těchto hodnot renderuje objekty. Pole hodnot se načtou jen jednou a potom se v nekonečné smyčce volá funkce "glDrawElements", čímž se docílí rychlejšího překreslování scény, než u klasické metody renderování přes funkce "glBegin() .... glEnd".
procedure TForm1.DrawElements; begin //1. ctverec glBindTexture(GL_TEXTURE_2D, textura[1]); //nacte texturu glTexCoordPointer(2, GL_FLOAT, 0, @CoordPointer1); //nacte pole tex. koordinaci glVertexPointer(3, GL_FLOAT, 0, @VertexPointer1); //nacte pole bodu glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, @Indices1);//zobrazi vysledny objekt //2. ctverec glBindTexture(GL_TEXTURE_2D, textura[1]); glTexCoordPointer(2, GL_FLOAT, 0, @CoordPointer2); glVertexPointer(3, GL_FLOAT, 0, @VertexPointer2); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, @Indices2); //leva stena glBindTexture(GL_TEXTURE_2D, textura[1]); glTexCoordPointer(2, GL_FLOAT, 0, @CoordPointer3); glVertexPointer(3, GL_FLOAT, 0, @VertexPointer3); glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_INT, @Indices3); //zadni stena glBindTexture(GL_TEXTURE_2D, textura[2]); glTexCoordPointer(2, GL_FLOAT, 0, @CoordPointer4); glVertexPointer(3, GL_FLOAT, 0, @VertexPointer4); glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_INT, @Indices4); //prava stena glBindTexture(GL_TEXTURE_2D, textura[2]); glTexCoordPointer(2, GL_FLOAT, 0, @CoordPointer5); glVertexPointer(3, GL_FLOAT, 0, @VertexPointer5); glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_INT, @Indices5); end;
Proceduru DrawElements voláme v proceduře ZobrazitScenu, kde se zároveň nastaví posuny a rotace při procházení námi vytvořenou scénou:
procedure TForm1.ZobrazitScenu; begin pohyb; wglMakeCurrent(Canvas.Handle,hRC); glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); VlastnostiObjektu; DrawElements; glFlush; SwapBuffers(Canvas.Handle); wglMakeCurrent(0,0) end;
Také jsem vylepšil proceduru, která zajišťuje pohyb ve scéně. Pohyb už není tak sekaný, jak byl doposud. Nebudu se o ní však rozepisovat, protože si ji můžete stáhnout se zdrojákem.Zbytek zdrojáku zůstává stejný jako v předchozích příkladech, takže popis dalších použitých funkcí najdete v nich.
Pozn.: Na počítači AMD Duron 750Mhz s integrovanou grafikou při rozlišení 1024*768 běhá tento prográmek rychlostí přibližně 70fps, při změně rozlišení na 320*240 několikanásobně rychleji.
![]() |
| Popis obrázku |
Tady (340 kB) si můžete dnešní stáhnout zdroják i s texturami.
Vyšlo 20.12.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
- OpenGL (10.) - Nová knihovna geometry.pas
- OpenGL (9.) - Generování textur a vylepšení FarClip Distance
- Zoner Callisto (1.) - Export do GIFu
- 3D Studio MAX (9.) - Vytváření odlesků vodní hladiny
- OpenGL (8.) - Slovníček pojmů v OpenGL
- OpenGL (7.) - Detekce kolizí, načtení mapy a textury v jpg souboru
- OpenGL (6.) - Co je to MiniGL
- OpenGL (5.) - Urychlení pomocí glDrawElements
- Delphi (7.) - Syst. repro a autodestrukce souboru
- OpenGL (4.) - FullScreen
- 3D Studio MAX (8.) - Tvorba hořící zápalky
- 'DOOM' 3D Engine techniques
- OpenGL (3.) - Procházení scénou
- 3D Studio MAX (7.) - 3D text
- 3D Studio MAX (6.) - Vznášející se dým

