[Delphi]Renderizando o OpenGL em um TPanel

Ver o tópico anterior Ver o tópico seguinte Ir em baixo

[Delphi]Renderizando o OpenGL em um TPanel

Mensagem por LeandroDaher em Dom 04 Set 2011, 10:41

Renderizando o OpenGL em um TPanel


Bem-vindo(a), vou encinar como renderizar o OpenGL em um TPanel no formulário.

Aqui está o resultado final:



Requerimento para o tutorial:
Delphi 7 ou superior (deve funcionar com o Delphi 5 e 6 tambem).
Saber o básico de Delphi, como usar os eventos dos componentes e etc.

Agora vamos ao tutorial.

Primeiro adicione um TPanel no formulário (O Panel está localizado na aba de componentes Startand), e mude o valor da propiedade Aling para alClient.Deixe o nome como está: Panel1.



Declare nas uses a unit OpenGL que já vem incluso no delphi.

Código:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, OpenGL;

type
  TForm1 = class(TForm)
...

Em private adicione o seguinte codigo:

Código:
rc : HGLRC;    //Contexto de renderização OpenGL
dc  : HDC;    //Contexto de Dispositivo (Device Contex)
ElapsedTime, AppStart, LastTime : DWord;
procedure glDraw;
procedure Idle(Sender: TObject; var Done: Boolean);

Agora depois de:

var
Form1: TForm1;

implementation

{$R *.dfm}

Adicione o codigo:

Código:
procedure TForm1.glDraw;
begin

end;

procedure Tform1.Idle(Sender: TObject; var Done: Boolean);
begin

end;

procedure glInit();
begin

end;

Deiche assim por enquanto...
No evento OnCreate do formulário deixe-o assim:

Código:
procedure TForm1.FormCreate(Sender: TObject);
var pfd : TPIXELFORMATDESCRIPTOR;
    pf  : Integer;
begin
Form1.Caption:='Renderizando o OpenGL em um TPanel';

//OpenGL initialisieren
dc:=GetDC(Panel1.Handle);
//PixelFormat
pfd.nSize:=sizeof(pfd);
pfd.nVersion:=1;
pfd.dwFlags:=PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER or 0;
pfd.iPixelType:=PFD_TYPE_RGBA;      //PFD_TYPE_RGBA e PFD_TYPEINDEX
pfd.cColorBits:=32;
pf :=ChoosePixelFormat(dc, @pfd);  //Returns format that most closely matches above pixel format
SetPixelFormat(dc, pf, @pfd);
rc :=wglCreateContext(dc);    //Rendering Context = window-glCreateContext
wglMakeCurrent(dc,rc);        //Make the DC (Form1) the rendering Context
//Initialist GL environment variables
glInit;
Panel1Resize(sender);    //sets up the perspective
AppStart :=GetTickCount();
//when the app has spare time, render the GL scene
Application.OnIdle := Idle;
end;

No evento OnDestroy do formulário deixe-o assim:

Código:
procedure TForm1.FormDestroy(Sender: TObject);
begin
wglMakeCurrent(0,0);
wglDeleteContext(rc);
end;

Agora no Panel1, use o evento OnResize e deixe-o assim:

Código:
procedure TForm1.Panel1Resize(Sender: TObject);
begin
glViewport(0, 0, Panel1.Width, Panel1.Height);    //Define a viewport para a janela OpenGL
glMatrixMode(GL_PROJECTION);        //Altera o modo Matrix para Projeção
glLoadIdentity();                  //Reseta o visualizador (view)
gluPerspective(45.0, Panel1.Width/Panel1.Height, 1.0, 500.0);  //Faz os cálculos de perspectiva. Último valor = profundidade de corte máxima
glMatrixMode(GL_MODELVIEW);        //Volta para a matriz de modelagem
end;

Até agora o nosso código está assim:

Código:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, OpenGL;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Panel1Resize(Sender: TObject);
  private
    { Private declarations }
    rc : HGLRC;    //Contexto de renderização OpenGL
    dc  : HDC;    //Contexto de Dispositivo (Device Contex)
    ElapsedTime, AppStart, LastTime : DWord;
    procedure glDraw;
    procedure Idle(Sender: TObject; var Done: Boolean);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.glDraw;
begin

end;

procedure Tform1.Idle(Sender: TObject; var Done: Boolean);
begin

end;

procedure glInit();
begin

end;

procedure TForm1.FormCreate(Sender: TObject);
var pfd : TPIXELFORMATDESCRIPTOR;
    pf  : Integer;
begin
Form1.Caption:='Renderizando o OpenGL em um TPanel';

//OpenGL initialisieren
dc:=GetDC(Panel1.Handle);
//PixelFormat
pfd.nSize:=sizeof(pfd);
pfd.nVersion:=1;
pfd.dwFlags:=PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER or 0;
pfd.iPixelType:=PFD_TYPE_RGBA;      //PFD_TYPE_RGBA e PFD_TYPEINDEX
pfd.cColorBits:=32;
pf :=ChoosePixelFormat(dc, @pfd);  //Returns format that most closely matches above pixel format
SetPixelFormat(dc, pf, @pfd);
rc :=wglCreateContext(dc);    //Rendering Context = window-glCreateContext
wglMakeCurrent(dc,rc);        //Make the DC (Form1) the rendering Context
//Initialist GL environment variables
glInit;
Panel1Resize(sender);    //sets up the perspective
AppStart :=GetTickCount();
//when the app has spare time, render the GL scene
Application.OnIdle := Idle;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
wglMakeCurrent(0,0);
wglDeleteContext(rc);
end;

procedure TForm1.Panel1Resize(Sender: TObject);
begin
glViewport(0, 0, Panel1.Width, Panel1.Height);    //Define a viewport para a janela OpenGL
glMatrixMode(GL_PROJECTION);        //Altera o modo Matrix para Projeção
glLoadIdentity();                  //Reseta o visualizador (view)
gluPerspective(45.0, Panel1.Width/Panel1.Height, 1.0, 500.0);  //Faz os cálculos de perspectiva. Último valor = profundidade de corte máxima
glMatrixMode(GL_MODELVIEW);        //Volta para a matriz de modelagem
end;

end.
Volte ao glInit() e subistitua-o por este codigo:

Código:
procedure glInit();
begin
glClearColor(0.0, 0.0, 0.0, 0.0);      //Fundo preto
glShadeModel(GL_SMOOTH);                //Permite sombreamento de cor lisa
glClearDepth(1.0);                      //Setup do Buffer de profundidade
glEnable(GL_DEPTH_TEST);                //Habilitar buffer de profundidade
glDepthFunc(GL_LESS);                //O tipo de teste de profundidade a fazer
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  //Calculos de perspectiva
end;

Volte ao Idle e substitua-o por este código:

Código:
procedure Tform1.Idle(Sender: TObject; var Done: Boolean);
begin
Done := FALSE;
LastTime :=ElapsedTime;
ElapsedTime :=GetTickCount() - AppStart;      //Calcula o tempo decorrido
ElapsedTime :=(LastTime + ElapsedTime) DIV 2; //Média-lo para movimentos mais suaves
glDraw();                        //Desenha a cena
SwapBuffers(DC);                  //Mostra a cena
end;

Volte ao glDraw() e substitua-o por este código:
Código:

procedure TForm1.glDraw;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    //Limpa a tela e o buffer de profundidade
glLoadIdentity();                                      //Reseta o visualizador (view)
              //Position
OpenGL.gluLookAt(-5, 0, 10, 0, 0, 0, 0, 1, 0); //Configura a camêra
                                                                            //X Y Z
glTranslatef(0, 0, 0); //Posiciona as unidades para desenhar o objeto na posição 0 0 0
glColor3f(255, 0, 0); //Define uma cor antes de desenhar o objeto
glRotatef(ElapsedTime/3, 0, 1, 0); //Rotaciona o cubo constantemente
//Desenhar o cubo
glBegin(GL_QUADS);
    //Face frontal
    glNormal3f( 0.0, 0.0, 1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0,  1.0);
    //Face traseira
    glNormal3f( 0.0, 0.0,-1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
    //Face superior (top)
    glNormal3f( 0.0, 1.0, 0.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0,  1.0,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
    //Face inferior (buttom)
    glNormal3f( 0.0,-1.0, 0.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, -1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
    //Face direita
    glNormal3f( 1.0, 0.0, 0.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
    //Face esquerda
    glNormal3f(-1.0, 0.0, 0.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
  glEnd();
end;

Ele é responssável por desenhar toda a cena a cada frame (quadro).

Pronto, agora é só salvar, compilar e testar.
Código fonte completo:

Código:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, OpenGL;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Panel1Resize(Sender: TObject);
  private
    { Private declarations }
    rc : HGLRC;    //Contexto de renderização OpenGL
    dc  : HDC;    //Contexto de Dispositivo (Device Contex)
    ElapsedTime, AppStart, LastTime : DWord;
    procedure glDraw;
    procedure Idle(Sender: TObject; var Done: Boolean);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.glDraw;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    //Limpa a tela e o buffer de profundidade
glLoadIdentity();                                      //Reseta o visualizador (view)
              //Position
OpenGL.gluLookAt(-5, 0, 10, 0, 0, 0, 0, 1, 0); //Configura a camêra
                                                                            //X Y Z
glTranslatef(0, 0, 0); //Posiciona as unidades para desenhar o objeto na posição 0 0 0
glColor3f(255, 0, 0); //Define uma cor antes de desenhar o objeto
glRotatef(ElapsedTime/3, 0, 1, 0); //Rotaciona o cubo constantemente
//Desenhar o cubo
glBegin(GL_QUADS);
    //Face frontal
    glNormal3f( 0.0, 0.0, 1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0,  1.0);
    //Face traseira
    glNormal3f( 0.0, 0.0,-1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
    //Face superior (top)
    glNormal3f( 0.0, 1.0, 0.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0,  1.0,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
    //Face inferior (buttom)
    glNormal3f( 0.0,-1.0, 0.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, -1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
    //Face direita
    glNormal3f( 1.0, 0.0, 0.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
    //Face esquerda
    glNormal3f(-1.0, 0.0, 0.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
  glEnd();
end;

procedure Tform1.Idle(Sender: TObject; var Done: Boolean);
begin
Done := FALSE;
LastTime :=ElapsedTime;
ElapsedTime :=GetTickCount() - AppStart;      //Calcula o tempo decorrido
ElapsedTime :=(LastTime + ElapsedTime) DIV 2; //Média-lo para movimentos mais suaves
glDraw();                        //Desenha a cena
SwapBuffers(DC);                  //Mostra a cena
end;

procedure glInit();
begin
glClearColor(0.0, 0.0, 0.0, 0.0);      //Fundo preto
glShadeModel(GL_SMOOTH);                //Permite sombreamento de cor lisa
glClearDepth(1.0);                      //Setup do Buffer de profundidade
glEnable(GL_DEPTH_TEST);                //Habilitar buffer de profundidade
glDepthFunc(GL_LESS);                //O tipo de teste de profundidade a fazer
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  //Calculos de perspectiva
end;

procedure TForm1.FormCreate(Sender: TObject);
var pfd : TPIXELFORMATDESCRIPTOR;
    pf  : Integer;
begin
Form1.Caption:='Renderizando o OpenGL em um TPanel';

//OpenGL initialisieren
dc:=GetDC(Panel1.Handle);
//PixelFormat
pfd.nSize:=sizeof(pfd);
pfd.nVersion:=1;
pfd.dwFlags:=PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER or 0;
pfd.iPixelType:=PFD_TYPE_RGBA;      //PFD_TYPE_RGBA e PFD_TYPEINDEX
pfd.cColorBits:=32;
pf :=ChoosePixelFormat(dc, @pfd);  //Returns format that most closely matches above pixel format
SetPixelFormat(dc, pf, @pfd);
rc :=wglCreateContext(dc);    //Rendering Context = window-glCreateContext
wglMakeCurrent(dc,rc);        //Make the DC (Form1) the rendering Context
//Initialist GL environment variables
glInit;
Panel1Resize(sender);    //sets up the perspective
AppStart :=GetTickCount();
//when the app has spare time, render the GL scene
Application.OnIdle := Idle;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
wglMakeCurrent(0,0);
wglDeleteContext(rc);
end;

procedure TForm1.Panel1Resize(Sender: TObject);
begin
glViewport(0, 0, Panel1.Width, Panel1.Height);    //Define a viewport para a janela OpenGL
glMatrixMode(GL_PROJECTION);        //Altera o modo Matrix para Projeção
glLoadIdentity();                  //Reseta o visualizador (view)
gluPerspective(45.0, Panel1.Width/Panel1.Height, 1.0, 500.0);  //Faz os cálculos de perspectiva. Último valor = profundidade de corte máxima
glMatrixMode(GL_MODELVIEW);        //Volta para a matriz de modelagem
end;

end.

Tutorial criado por leandrohackerx.

A maioria dos códigos que eu usei aprendi na internet.
Créditos abaixo:

www.sulaco.co.za pelos tutoriais e exemplos de OpenGL.

LeandroDaher

Número de Mensagens : 357
Idade : 20
Data de inscrição : 13/05/2010
Reputação : 3
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: [Delphi]Renderizando o OpenGL em um TPanel

Mensagem por Klior em Dom 04 Set 2011, 13:11

Vlw, obrigado por compartilhar, apesar de que poucos usarão isso em delphi, visto que o fórum é mais voltado para game maker, mais conhecimento nunca é demais né, sabendo que o game maker também é feito em delphi, é bom saber como as coisas funcionam internamente.

Klior

Número de Mensagens : 426
Idade : 25
Data de inscrição : 07/03/2010
Reputação : 13
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: [Delphi]Renderizando o OpenGL em um TPanel

Mensagem por Biel22GM em Qui 15 Set 2011, 12:05

Gostei de Parabéns Happy

Biel22GM

Número de Mensagens : 75
Idade : 21
Data de inscrição : 09/09/2011
Reputação : 0
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0

http://www.gabrielfelipegames.blogspot.com

Voltar ao Topo Ir em baixo

Re: [Delphi]Renderizando o OpenGL em um TPanel

Mensagem por Conteúdo patrocinado Hoje à(s) 07:24


Conteúdo patrocinado


Voltar ao Topo Ir em baixo

Ver o tópico anterior Ver o tópico seguinte Voltar ao Topo

- Tópicos similares

 
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum