Converta o framework VC OPENGL do NeHe traduzido pelo CKER para a versão Delphi.
Espero que seja útil para irmãos que usam Delphi para aprender OPENGL.
Não sei por que, mas ele não pode ser executado diretamente no meu ambiente Delphi, mas parece funcionar bem em outras máquinas.
Minha máquina só pode compilar e executar arquivos EXE.
Obrigado ao NeHe por fornecer uma estrutura tão boa e ao CKER por traduzir as informações do VC.
PROGRAMA PROJETO1;
Usos
opengl,
Windows,
Mensagens;
Const.
WND_TITLE = 'Estrutura básica OPenGl';
Var
//============================================== ===========================
// Cada OpenGL está conectado a um contexto de sombreamento. A tabela de contexto de sombreamento conecta todas as chamadas OpenGL a
// Recebe o Contexto do Dispositivo (tabela de descrição do dispositivo) e define a tabela de descrição de sombreamento OpenGL como hRC, para que o programa possa
// Se for suficiente desenhar a janela, você também precisa criar uma tabela de descrição de dispositivos A tabela de descrição de dispositivos do Windows é definida como hDC,
// DC conecta a janela ao GDI (Graphics Device Interface). E RC conecta OpenGL
// para DC.
//============================================== ===========================
h_RC: HGLRC; // Contexto de renderização (tabela de descrição de sombreamento).
h_DC: HDC; // Contexto do dispositivo (tabela de descrição do dispositivo)
h_Wnd: HWND; // identificador da janela
h_Instance: HINST; // Instância do programa (instância).
teclas: Array[0..255] Of Boolean; // Array para rotinas de teclado
{$R *.res}
//============================================== ==============================
//Redefine o tamanho da cena OpenGL independentemente de o tamanho da janela ter sido alterado (assumindo que o modo de tela cheia não é usado).
//Mesmo quando a janela não pode ser redimensionada (por exemplo, no modo de tela cheia), ela ainda será executada pelo menos uma vez————————
//Defina a perspectiva no início do programa. O tamanho da cena OpenGL será definido de acordo com o tamanho da janela na qual ela é exibida.
//============================================== ==============================
Procedimento glResizeWnd(Width, Height: Integer); //Redefinir e inicializar o tamanho da janela GL
Começar
If (Height = 0) Then // Evita que a altura seja 0 e cause uma exceção de divisão por 0.
Altura:= 1;
glViewport(0, 0, Width, Height); //Redefinir a viewport atual (Viewport)
//As linhas a seguir configuram a tela de perspectiva. Isso significa que as coisas que estão mais distantes parecem menores. Fazer isso cria uma realidade
//Cena de aparição. A perspectiva aqui é calculada como um ângulo de visão de 45 graus com base na largura e altura da janela. 0,1f, 100,0f são
//O ponto inicial e final da profundidade que podemos desenhar na cena.
//glMatrixMode(GL_PROJECTION) especifica que as próximas duas linhas de código afetarão a matriz de projeção.
//A matriz de projeção é responsável por adicionar perspectiva à nossa cena.
//glLoadIdentity() é semelhante a redefinir. Restaura o estado da matriz selecionada ao seu estado original.
//Após chamar glLoadIdentity() definimos a perspectiva da cena.
glMatrixMode(GL_PROJECTION); //Selecione a matriz de projeção
glLoadIdentity(); // Redefine a matriz de projeção
gluPerspective(45.0, Width / Height, 0.1, 100.0); // Calcula a proporção da aparência da janela
//glMatrixMode(GL_MODELVIEW) especifica que qualquer nova transformação afetará a matriz modelview (matriz de observação do modelo).
//Nossas informações do objeto são armazenadas na matriz de observação do modelo.
glMatrixMode(GL_MODELVIEW); //Seleciona a matriz de observação do modelo
glLoadIdentity(); //Redefinir matriz de observação do modelo
//Se você ainda não entende o que esses termos significam, não se preocupe.
//Só saiba que você precisa fazer isso se quiser obter uma cena com ótima perspectiva.
Fim;
//============================================== ==============================
// Faça todas as configurações para OpenGL. Defina a cor para limpar a tela, ative o cache de profundidade,
// Habilita o sombreamento suave (suavização de sombras), etc. Esta rotina não é chamada até que a janela OpenGL seja criada.
// Este processo terá um valor de retorno. Mas a inicialização aqui não é tão complicada e não há necessidade de se preocupar com o valor de retorno ainda.
//============================================== ==============================
Procedimento glInit();
Começar
//Define a cor usada ao limpar a tela. Se você não tem certeza de como as cores funcionam, aqui está uma explicação rápida.
//Os valores das cores variam de 0,0f a 1,0f. 0,0f representa a situação mais sombria e 1,0f é a situação mais clara.
//O primeiro parâmetro após glClearColor é Red Intensity (componente vermelho), o segundo é verde e o terceiro é azul.
//O valor máximo também é 1.0f, que representa o caso mais brilhante de um componente de cor específico. O último parâmetro é o valor Alpha.
//Quando for usado para limpar a tela, não se preocupe com o quarto número. Agora seja 0,0f.
//Ao misturar três cores primárias (vermelho, verde, azul), você pode obter cores diferentes
//Então, use glClearColor(0.0f,0.0f,1.0f,0.0f), seu azul para limpar a tela.
//Se você usar glClearColor(0.5f,0.0f,0.0f,0.0f), o vermelho médio será usado para limpar a tela.
//Nem o mais claro (1.0f), nem o mais escuro (0.0f). Para obter um fundo branco, todas as cores devem ser definidas como mais brilhantes (1.0f).
//Se você quiser um fundo preto, defina todas as cores para o mais escuro (0.0f).
glClearColor(0.0, 0.0, 0.0, 0.0); // fundo preto
//A suavização de sombra combina cores com precisão por meio de polígonos e suaviza a luz externa.
glShadeModel(GL_SMOOTH); // Habilita suavização de sombra
//A próxima coisa que deve ser feita é sobre o buffer de profundidade. Pense no buffer de profundidade como uma camada atrás da tela.
//O buffer de profundidade monitora continuamente a profundidade com que o objeto entra na tela. Na verdade, este programa não usa o cache de profundidade.
//Mas quase todos os programas OpenGL que exibem cenas 3D na tela usam buffers de profundidade. Sua ordem determina qual objeto é desenhado primeiro.
//Dessa forma você não desenha um quadrado atrás de um círculo no círculo. O buffer de profundidade é uma parte muito importante do OpenGL.
glClearDepth(1.0); //Definir o buffer de profundidade
glEnable(GL_DEPTH_TEST); // Habilita teste de profundidade
glDepthFunc(GL_LESS); // Tipo de teste de profundidade realizado
//Então diga ao OpenGL que queremos a melhor correção de perspectiva possível.
//Isso afetará levemente o desempenho. Mas faz com que a perspectiva pareça um pouco melhor.
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Correção de perspectiva muito boa
Fim;
//============================================== ==============================
//Todo o código do desenho. Tudo o que você deseja exibir na tela aparecerá neste código.
//Cada programa futuro adicionará novo código aqui.
//============================================== ==============================
Procedimento glDraw();
Começar
glClear(GL_COLOR_BUFFER_BIT Ou GL_DEPTH_BUFFER_BIT); // Limpa tela e buffer de profundidade;
glLoadIdentity(); //Redefinir a matriz de observação do modelo atual
Fim;
Function WndProc(hWnd: HWND; // identificador da janela
Mensagem: UINT; // Mensagem da janela
wParam: WPARAM; // Conteúdo adicional da mensagem
lParam: LPARAM // Conteúdo adicional da mensagem
): LRESULT;
Começar
Resultado:= 0;
Case (Msg) Of // Verifica as mensagens do Windows
WM_ACTIVATE: // Mensagem de ativação da janela do monitor
Começar
Fim;
WM_CREATE: //Criar
Começar
Fim;
WM_CLOSE: //fecha
Começar
PostQuitMessage(0); //Envia mensagem de saída
Resultado:= 0
Fim;
WM_KEYDOWN: // tecla pressionada
Começar
keys[wParam] := True; // Se sim, defina como TRUE;
Resultado:= 0;
Fim;
WM_KEYUP: // Solte a tecla
Começar
keys[wParam] := False; // Se sim, defina como FALSE;
Resultado:= 0;
Fim;
WM_SIZE: //Ajusta o tamanho da janela OpenGL
Começar
glResizeWnd(LOWord(lParam), HIWORD(lParam)); //LoWord=Largura,HiWord=Altura
Resultado:= 0;
Fim;
WM_TIMER: //temporizadores
Começar
Fim;
Else //Deixe o Windows cuidar do resto.
Resultado := DefWindowProc(hWnd, Msg, wParam, lParam); // Passa todas as mensagens não processadas para DefWindowProc.
Fim;
Fim;
//============================================== ==============================
// Chamado apenas antes do encerramento do programa. A função é liberar a tabela de contexto de coloração, a tabela de contexto do dispositivo e o identificador da janela em sequência.
// Adicionadas muitas verificações de erros. Se o programa não conseguir destruir nenhuma parte da janela, uma mensagem de erro apropriada aparecerá.
// janela de mensagem,
//============================================== ==============================
Procedimento glKillWnd(Tela Cheia: Boolean);
Começar
//A primeira coisa feita em KillGLWindow() é verificar se está em modo tela cheia.
//Se sim, volte para a área de trabalho. A janela deveria ter sido destruída antes de desativar o modo de tela inteira,
//Mas fazer isso em algumas placas gráficas pode travar a área de trabalho. Portanto, é melhor desativar primeiro o modo de tela cheia.
//Isso evitará travamentos da área de trabalho e funciona muito bem em placas gráficas Nvidia e 3dfx!
Se tela cheia então // Em modo tela cheia?
Começar
// Use ChangeDisplaySettings(NULL,0) para retornar à área de trabalho original.
//Tome NULL como primeiro parâmetro,
// Passar 0 como segundo parâmetro força o Windows a usar o valor atualmente armazenado no registro
// (resolução padrão, profundidade de cor, taxa de atualização, etc.) para restaurar efetivamente minha área de trabalho original.
// Depois de voltar para a área de trabalho, o ponteiro do mouse deve ficar visível novamente.
ChangeDisplaySettings(devmode(Nil^), 0); // Se sim, volte para a área de trabalho
ShowCursor(True); //Mostra mouse
Fim;
//Se possui tabela de descrição de cores (hRC).
Se h_RC > 0 Então
//Veja se conseguimos liberá-lo (separar hRC de hDC).
Se (Não wglMakeCurrent(h_DC, 0)) Então
MessageBox(0, 'DC e RC não podem ser liberados!', 'Erro', MB_OK Ou
MB_ICONERROR);
// A tabela de descrição de sombreamento pode ser excluída?
Se (Não wglDeleteContext(h_RC)) Então
Começar
MessageBox(0, 'Falha ao excluir tabela de contexto de sombreamento!', 'Erro', MB_OK Ou
MB_ICONERROR);
h_RC := 0;
Fim;
//Se a tabela de contexto do dispositivo existe e, em caso afirmativo, tente liberá-la.
Se ((h_DC > 0) E (ReleaseDC(h_Wnd, h_DC) = 0)) Então
Começar
MessageBox(0, 'Falha ao liberar contexto do dispositivo!', 'Erro', MB_OK Ou
MB_ICONERROR);
h_DC := 0;
Fim;
//Se houver um identificador de janela, chame DestroyWindow(hWnd) para tentar destruir a janela
Se ((h_Wnd <> 0) E (Não DestroyWindow(h_Wnd))) Então
Começar
MessageBox(0, 'Não é possível destruir o formulário!', 'Erro', MB_OK Ou
MB_ICONERROR);
h_Wnd := 0;
Fim;
//Sai da classe da janela
//Isso nos permite destruir a janela normalmente e depois abrir outras janelas,
//Você não receberá mensagens de erro como "Classe Windows já registrada" (classe de janela já registrada).
If (Not UnRegisterClass('OpenGL', hInstance)) Então
Começar
MessageBox(0, 'Não é possível sair da classe da janela!', 'Erro', MB_OK Ou
MB_ICONERROR);
hInstância := 0;
Fim;
Fim;