11. Úvod do OpenGL
Domovská stránka Programovanie v C++ OOP a Windows Ročníkový projekt Princípy počítačov Princípy databáz Všeličo Kontakt

 

Na prednáške:

Zdroje:


Trocha matematiky

Lineárna transformácia sa dá popísať pomocou matice s rozmermi 4x4. Súradnice transformovaného bodu sa potom vypočítajú:

Nový = Matica * Bod

Zmena veľkosti:

( x 0 0 0 )
0 y 0 0
0 0 z 0
0 0 0 1

Otočenie:

( * * * 0 )
* * * 0
* * * 0
0 0 0 1

Posunutie:

( 1 0 0 x )
0 1 0 y
0 0 1 z
0 0 0 1


Matice v OpenGL

Ako zmeniť maticu transformácie objektu:

var
  M: array[0..3, 0..3] of GLFloat;
begin
  glMatrixMode(GL_MODELVIEW);
  FillChar(M, sizeof(M), 0);
  M[0, 0]:=1;
  M[1, 1]:=1;
  M[2, 2]:=1;
  M[3, 3]:=1;
  glLoadMatrixF(@m);
end;

 OpenGL používa 3 druhy matíc, práca s niektorou z nich sa zapína pomocou funkcie glMatrixMode:

Ak sme pomocou funkcie glMatrixMode( ... ) vybrali maticu, môžeme s ňou ďalej pracovať:
  glLoadMatrixF( ... )
  glLoadIdentity
... nastaví maticu na jednotkovú

Transformácie môžeme skladať pomocou operácie súčin matíc:
  glMulMatrixF(@M) ... vynásobí maticu s maticou M
Pre jednoduché transformácie nemusíme sami zostavovať maticu a volať takéto násobenie. Stačí, ak použijeme funkcie:
  glTranslate(dX, dY, dZ)
  glRotate(Uhol, nX, nY, nZ)
  glScale(X, Y, Z)
Ak chceme bod otočiť o 45° a potom posunúť o vektor (0, 0, 0, -5):
  glLoadIdentity;
  glTranslate(0, 0, -5);
  glRotate(45, 0, 0, 1);
Všimnite si, že obrátené poradie volania funkcií, ktoré vytvoria výslednú maticu transformácie T * R ( T je označenie pre maticu posunutia, ktorú použila funkcia glTranslate a R je označenie matice otočenia, ktorú použila funkcia glRotate). Súradnica nového, transformovaného bodu sa potom vypočíta zo súčinu: ( T * R ) * Bod T * ( R * Bod ) - vidíme, že bod sa naozaj najskôr otočí a až potom posunie.


Inicializovanie

var
  RC: HGLRC=0;
  DC: HDC=0;

procedure TForm1.FormCreate(Sender: TObject);
var
  PFD: TPixelFormatDescriptor;
  PF: Integer;
begin
  //
Nastavenie Device Contextu:
  DC:=GetDC(Handle);
  FillChar(PFD, SizeOf(TPixelFormatDescriptor), 0);
  PFD.nSize:=SizeOf(TPixelFormatDescriptor);
  PFD.nVersion:=1;
  PFD.dwFlags:=PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
  PFD.iPixelType:=PFD_TYPE_RGBA;
  PFD.cColorBits:=32;
  PFD.cDepthBits:=32;
  PFD.iLayerType:=PFD_MAIN_PLANE;
  PF:=ChoosePixelFormat(DC, @PFD);
  if PF=0 then Exit;
  SetPixelFormat(DC, PF, @PFD);
  //
Vytvorenie Rendering Contextu:
  RC:=wglCreateContext(DC);
  wglMakeCurrent(DC, RC);
  glClearColor(0, 0, 0, 0);
  glClearDepth(1);
  glEnable(GL_DEPTH_TEST);
  //
Nastavenie zobrazovania:
  glViewport(0, 0, ClientWidth, ClientHeight);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(60, ClientWidth/ClientHeight, 1, 1000);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  wglMakeCurrent(0, 0);
  wglDeleteContext(RC);
  ReleaseDC(Handle, DC);
end;


Kreslenie jednoduchej scény

procedure TForm1.Button1Click(Sender: TObject);
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glBegin(GL_TRIANGLES);
  glColor(1.0, 0.0, 0.0);
  glVertex(0, +1, -5);
  glColor(0.0, 1.0, 0.0);
  glVertex(-2, -1, -5);
  glColor(0.0, 0.0, 1.0);
  glVertex(1, -1, -5);
  glEnd;
  SwapBuffers(DC);
end;

Animácia pomocou časovača:

var 
  Uhol: Real=0;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glLoadIdentity;
  glTranslate(0, 0, -5);
  glRotate(Uhol, 0, 1, 1);
  glColor(1.0, 0.0, 0.0);
  glBegin(GL_POLYGON);
  glVertex(-1, +1, 0);
  glVertex(+1, +1, 0);
  glVertex(+1, -1, 0);
  glVertex(-1, -1, 0);
  glEnd;
  SwapBuffers(DC);
  Uhol:=Uhol+10;
end;

Komplikovanejší útvar - kocka:

const
 
Vrcholy: array[0..7] of record
    X, Y, Z: Real;
    R, G, B: Real;
  end=(
    (X: -1; Y: +1; Z: +1; R: 1; G: 1; B: 1),
    (X: +1; Y: +1; Z: +1; R: 1; G: 1; B: 0),
    (X: +1; Y: -1; Z: +1; R: 0; G: 1; B: 0),
    (X: -1; Y: -1; Z: +1; R: 0; G: 1; B: 1),
    (X: -1; Y: +1; Z: -1; R: 0; G: 0; B: 1),
    (X: +1; Y: +1; Z: -1; R: 1; G: 0; B: 1),
    (X: +1; Y: -1; Z: -1; R: 1; G: 0; B: 0),
    (X: -1; Y: -1; Z: -1; R: 0; G: 0; B: 0));

  Steny: array[0..5] of record
    I: array[0..3] of Integer;
  end=(
    (I: (0, 1, 2, 3)), (I: (4, 5, 6, 7)),
    (I: (0, 1, 5, 4)), (I: (3, 2, 6, 7)),
    (I: (0, 3, 7, 4)), (I: (1, 2, 6, 5)));

var
  Uhol: Real=0;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  I, S, V: Integer;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glLoadIdentity;
  glTranslate(0, 0, -3);
  glRotate(Uhol, 1, 1, 0);
  for S:=0 to 5 do begin
    glBegin(GL_POLYGON);
    for V:=0 to 3 do begin
      I:=Steny[S].I[V];
      glColor(Vrcholy[I].R, Vrcholy[I].G, Vrcholy[I].B);
      glVertex(Vrcholy[I].X, Vrcholy[I].Y, Vrcholy[I].Z);
    end;
    glEnd;
  end;
  SwapBuffers(DC);
  Uhol:=Uhol+5;
end;

Celý program


Mapovanie textúry

Textúra musí byť s rozmery 2n * 2n:
var
  Tex: array[0..255, 0..255] of record
    R, G, B: Byte;
  end;

  for Y:=0 to 255 do
    for X:=0 to 255 do begin
      Tex[Y, X].R:=X;
      Tex[Y, X].G:=Y;
      Tex[Y, X].B:=0;
    end;
  glEnable(GL_TEXTURE_2D);
  glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameter(GL_TEXTURE_2D, GL_Texture_WRAP_T, GL_REPEAT);
  glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Použitie:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glLoadIdentity;
  glTranslate(0, 0, -2);
  glRotate(Uhol, 0, 1, 1);
  glTexImage2d(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, @Tex);
  glBegin(GL_POLYGON);
  glTexCoord(0, 0);
  glVertex(-1, +1, -1);
  glTexCoord(1, 0);
  glVertex(+1, +1, -1);
  glTexCoord(1, 1);
  glVertex(+1, -1, -1);
  glTexCoord(0, 1);
  glVertex(-1, -1, -1);
  glEnd;
  SwapBuffers(DC);
  Uhol:=Uhol+5;
end;

Celý program 

 

 

©  2003 Ľubomír SALANCI