Esto es de un viejo motor de juegos basado en OpenGL que estaba tratando de escribir hace siete años, escrito en C ++, tan claro conmigo mientras trato de explicar cómo manejé las operaciones de renderizado 3D GUI y mundo 2D dentro de él. Usé cuatro métodos principales dentro de mi clase de renderizador OpenGL (OGLRender) de los cuales son:
- ready3D () para preparar OpenGL para representar la escena mundial en 3D.
- ready2D () para preparar OpenGL para representar la GUI 2D.
- render3D () para el dibujo real de la escena mundial en 3D.
render2D () para el actual dibujo 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 ...
}
Y luego, en el bucle de hilo principal, básicamente llamaría a los métodos en el siguiente orden:
while(m_drawFrame)
{
gm_Render->render3D(); // draw 3D scene
gm_Render->render2D(); // draw GUI
SDL_GL_SwapBuffers(); // make drawn frame visible
}
Entonces, lo que estoy haciendo es dibujar primero mi escena mundial en 3D y luego dibujar mi GUI al final de esa manera, la GUI siempre está en la cima de la escena mundial. El método ready3D () prepara la proyección del mundo 3D para el dibujo de la escena mundial y el método ready2D () prepara la escena orto 2D para el dibujo de la GUI. m_Setup.width
y m_Setup.height
son solo las dimensiones de la pantalla del puerto de vista.
Lo que es especial sobre el método ready2D () es que gluOrtho2D()
se llama a la función con argumentos que le indican que cuando dibujamos las primitivas de GUI las dibujamos en las coordenadas de pantalla especificadas para que coincidan con Windows, Mac y otros sistemas de coordenadas de pantalla de escritorio. Tal como la parte superior izquierda es (0,0) en formato (X, Y) mientras que la parte inferior derecha es (ViewportWidth-1, ViewportHeight-1)
. Y glTranslatef()
se utiliza para corregir el posicionamiento preciso por píxel. De modo que cuando dibujamos una línea desde (0,0) hasta (0,9), la línea realmente dibujará desde la parte superior izquierda y hacia abajo diez píxeles en total de longitud y un ancho de píxel.
En general, lo más probable es que solo te interese lo que está haciendo el método ready2D () . Proporcioné los ejemplos de código fuente de los otros métodos para darle una idea de cómo generalmente la mayoría de los juegos hacen la escena mundial 3D y el orden de dibujo de la GUI.
([0...1], [0...1], 0, 1)
sin proyección, vista o matriz mundial, siempre aterrizarán en el espacio de la pantalla.