Como o próprio OpenGL.pas do Delphi é a versão 1.0, e o que é realmente usado agora é pelo menos a versão 1.1, e o método de simulação de software puro do Windows também é a versão 1.1, então você mesmo deve importar algumas funções necessárias. Algumas unidades gratuitas de código aberto também estão disponíveis, como OpenGL12.pas de Mike Lischke. É claro que escrever você mesmo pode tornar o design mais conciso e você não precisa encontrar erros em um código enorme que é muito avançado e completo.
Primeiro introduza as unidades necessárias Windows, Mensagens, OpenGL
Para adicionar algumas extensões necessárias.
const
//GL_EXT_bgra
GL_BGR_EXT = $80E0;
GL_BGRA_EXT = $80E1;
// deslocamento do polígono
GL_POLYGON_OFFSET_UNITS = $2A00;
GL_POLYGON_OFFSET_POINT = $2A01;
GL_POLYGON_OFFSET_LINE = $2A02;
GL_POLYGON_OFFSET_FILL = $ 8.037;
GL_POLYGON_OFFSET_FACTOR = $ 8.038;
Procedimento glBindTexture(destino: GLEnum; textura: GLuint);
procedimento glDeleteTextures(n: GLsizei; texturas: PGLuint);
procedimento glGenTextures(n: GLsizei; texturas: PGLuint);
função glIsTexture (textura: GLuint): GLboolean;
procedimento glPolygonOffset (fator, unidades: GLfloat);
// Esta instrução é usada para corrigir um bug no OpenGL.pas
função gluBuild2DMipmaps (destino: GLEnum; componentes, largura, altura: GLint; formato, atype: GLEnum; Dados: Ponteiro): GLint externo opengl32;
Agora a interface foi basicamente atualizada para a versão 1.1. Se outras extensões forem necessárias, elas poderão ser adicionadas de forma semelhante.
Em seguida, você precisa criar o contexto de desenho OpenGL RC, para o qual você precisa do contexto de dispositivo DC da janela GDI. A propriedade TForm.Handle ou outras propriedades Handle de TWinControl são DC. Você pode usar a seguinte função para criar RC a partir de DC, e o valor de retorno é o identificador de RC. Você pode então desenhar usando OpenGL. Geralmente pode ser usado dentro do evento OnCreate do Form. As opções desta função significam buffer de profundidade, buffer de modelo, buffer de acumulação e gerar valor de canal alfa.
tipo
TRCOptions = conjunto de (roDepth, roStencil, roAccum, roAlpha);
função CreateRC(dc: HDC; opt: TRCOptions): HGLRC;
var
PFDescriptor: TPixelFormatDescriptor;
PixelFormat: Inteiro;
começar
FillChar(PFDescriptor, SizeOf(PFDescriptor), 0);
com PFDescriptor fazer
começar
nSize := SizeOf(PFDescriptor);
nVersão := 1;
dwFlags := PFD_SUPPORT_OPENGL ou PFD_DRAW_TO_WINDOW ou PFD_DOUBLEBUFFER;
iPixelType := PFD_TYPE_RGBA;
cColorBits := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANOS);
se roDepth estiver opt então cDepthBits := 24;
se roStencil estiver opt então cStencilBits := 8;
se roAccum estiver em opt então cAccumBits := 64;
iLayerType := PFD_MAIN_PLANE;
fim;
PixelFormat := EscolhaPixelFormat(DC, @PFDescriptor);
Afirmar(PixelFormat <> 0);
Assert(SetPixelFormat(DC, PixelFormat, @PFDescriptor));
Resultado:=wglCreateContext(DC);
Afirmar(Resultado <> 0);
wglMakeCurrent(dc, Resultado);
fim;
Desenhe no evento OnPaint do formulário. Lembre-se, após a conclusão do desenho, você precisa usar SwapBuffers (dc: HDC) para trocar o buffer de desenho e o buffer de exibição para que a imagem seja exibida. Lembre-se também de chamar glViewport(0, 0, ClientWidth, ClientHeight); no evento OnResize do formulário para que RC e DC possam ser sincronizados.
Destrua RC no evento OnDestroy do formulário.
procedimento DestroyRC(rc: HGLRC);
começar
se rc = 0 então Sair;
wglMakeCurrent(0, 0);
wglDeleteContext(rc);
fim;
Neste ponto, a estrutura de um programa OpenGL já tomou forma. Mas ainda há problemas a serem resolvidos.
Primeiro, evite que o Windows apague o plano de fundo e afete a velocidade. Adicionar funções de membro ao formulário
privado
procedimento WMEraseBkgnd(var Mensagem: TWmEraseBkgnd);
procedimento TGLWindow.WMEraseBkgnd(var Mensagem: TWmEraseBkgnd);
começar
Mensagem.Resultado:= 1;
fim;
Em segundo lugar, para ser mais seguro. Adicione as seguintes funções-membro.
protegido
procedimento CreateParams (var Params: substituição de TCreateParams);
procedimento TGLWindow.CreateParams(var Params: TCreateParams);
começar
herdado;
com Params faça
começar
Estilo := Estilo ou WS_CLIPCHILDREN ou WS_CLIPSIBLINGS;
WindowClass.Style := CS_VREDRAW ou CS_HREDRAW ou CS_OWNDC;
fim;
fim;
Ok, agora você pode esquecer essas coisas problemáticas e escrever sua maravilhosa exibição 3D :)
Devo dizer algumas palavras: não crie vários RCs em um thread, pois isso afetará seriamente o desempenho. Algumas demonstrações pessoais de controle de janela OpenGL colocam vários controles em um Form, o que na verdade não é uma boa ideia. Várias visualizações devem ser exibidas com uma janela OpenGL. Além disso, não acesse funções OpenGL entre threads.
Além disso, quando o Windows instala automaticamente o driver da placa gráfica, ele não instala a aceleração de hardware OpenGL. Você mesmo deve instalar o driver do fabricante da placa gráfica!
Além disso, é fornecida uma função de exibição em tela inteira gratuita :)
função FullScreen (win: TWinControl; largura, altura, profundidade de bits: inteiro): boolean;
var modo de exibição: DEVMODE;
começar
FillChar(modo de exibição, sizeof(modo de exibição), 0);
com displaymode faça
começar
dmSize := sizeof(modo de exibição);
dmPelsWidth:= largura;
dmPelsHeight := altura;
dmBitsPerPel := profundidade de bits;
dmFields := DM_BITSPERPEL ou DM_PELSWIDTH ou DM_PELSHEIGHT;
fim;
se ChangeDisplaySettings(modo de exibição, CDS_FULLSCREEN) = DISP_CHANGE_SUCCESSFUL
então comece
ShowWindow(win.Handle, WS_MAXIMIZE);
resultado := verdadeiro;
fim
senão resultado := falso;
fim;
procedimento RestoreDisplay(win:TWinControl);
começar
ChangeDisplaySettings(PDEVMODE(0)^, 0);
ShowWindow(win.Handle, SW_RESTORE);
fim;