Isso é de um antigo mecanismo de jogo baseado em OpenGL que eu estava tentando escrever há cerca de sete anos, escrito em C ++ tão nu comigo, enquanto tentava explicar como lidei com o mundo 3D e as operações de renderização da GUI 2D dentro dele. Eu usei quatro métodos principais dentro da minha classe de renderizador OpenGL (OGLRender), dos quais são:
- ready3D () para preparar o OpenGL para renderizar a cena mundial em 3D.
- ready2D () para preparar o OpenGL para renderizar a GUI 2D.
- render3D () para o desenho real da cena mundial em 3D.
render2D () para o desenho real da GUI 2D.
void OGLRender::ready3D()
{
glViewport(0, 0, m_Setup.width, m_Setup.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (float) m_Setup.width / m_Setup.height, 0.1, 5000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
}
void OGLRender::ready2D()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0f, m_Setup.width, m_Setup.height, 0.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375, 0.375, 0.0);
glDisable(GL_DEPTH_TEST);
}
void OGLRender::render3D()
{
this->ready3D();
// ... draw 3D world scene here ...
}
void OGLRender::render2D()
{
this->ready2D();
// ... draw GUI here ...
}
E então, no loop principal do thread, eu basicamente chamava os métodos na seguinte ordem:
while(m_drawFrame)
{
gm_Render->render3D(); // draw 3D scene
gm_Render->render2D(); // draw GUI
SDL_GL_SwapBuffers(); // make drawn frame visible
}
Então, o que estou fazendo é desenhar minha cena mundial em 3D primeiro e depois desenhar minha GUI por último, para que a GUI esteja sempre no topo da cena mundial. O método ready3D () prepara a projeção do mundo 3D para o desenho da cena mundial e o método ready2D () prepara a cena orto 2D pronta para o desenho da GUI. m_Setup.width
e m_Setup.height
são apenas as dimensões da tela da porta de visualização.
O que há de especial no método ready2D () é que a gluOrtho2D()
função é chamada com argumentos que informam que, quando desenhamos as primitivas da GUI, as desenhamos nas coordenadas da tela especificadas para corresponder ao Windows, Mac e outros sistemas de coordenadas da tela da área de trabalho. Como no canto superior esquerdo, é (0,0) no formato (X, Y), enquanto no canto inferior direito (ViewportWidth-1, ViewportHeight-1)
. E glTranslatef()
é usado para corrigir o posicionamento preciso por pixel. Assim, quando traçarmos uma linha de (0,0) a (0,9), a linha será realmente desenhada do canto superior esquerdo e direto para baixo, totalizando dez pixels de comprimento e largura de um pixel.
No geral, você provavelmente só está interessado no que o método ready2D () está fazendo. Forneci os exemplos de código-fonte dos outros métodos para dar uma idéia geral de como a maioria dos jogos faz cena do mundo 3D e ordem de desenho da GUI.
([0...1], [0...1], 0, 1)
sem projeção, exibição ou matriz mundial, elas sempre aparecerão no espaço da tela.