To jest ze starego silnika gry opartego na OpenGL, który próbowałem napisać około siedem lat temu, napisanego w C ++, więc nie mam go przy sobie, gdy próbuję wyjaśnić, w jaki sposób radziłem sobie z operacjami w świecie 3D i renderowaniem 2D GUI. Użyłem czterech podstawowych metod w mojej klasie renderera OpenGL (OGLRender), z których są to:
- ready3D () do przygotowania OpenGL do renderowania sceny 3D świata.
- ready2D () do przygotowania OpenGL do renderowania graficznego interfejsu użytkownika 2D.
- render3D () dla rzeczywistego rysunku sceny świata 3D.
render2D () dla aktualnego rysunku 2D GUI.
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 ...
}
A potem w głównej pętli wątku po prostu wywołałbym metody w następującej kolejności:
while(m_drawFrame)
{
gm_Render->render3D(); // draw 3D scene
gm_Render->render2D(); // draw GUI
SDL_GL_SwapBuffers(); // make drawn frame visible
}
Tak więc to, co robię, to najpierw rysuję scenę świata 3D, a następnie rysuję GUI w ten sposób, że GUI jest zawsze na szczycie światowej sceny. Metoda ready3D () przygotowuje projekcję świata 3D do rysowania sceny światowej, a metoda ready2D () przygotowuje scenę 2D orto do rysowania GUI. m_Setup.width
i m_Setup.height
to tylko wymiary ekranu portu widokowego.
Szczególną cechą metody ready2D () jest to, że gluOrtho2D()
funkcja jest wywoływana z argumentami, które informują ją, gdy rysujemy prymitywy GUI, rysujemy je we współrzędnych ekranu określonych dla Windows, Mac i innych układów współrzędnych ekranu. Tak jak górny lewy to (0,0) w formacie (X, Y), podczas gdy dolny prawy to (ViewportWidth-1, ViewportHeight-1)
. I glTranslatef()
służy do skorygowania per-pixel dokładnego pozycjonowania. Tak więc, gdy narysujemy linię od (0,0) do (0,9), wówczas linia będzie rysować od lewego górnego rogu i prosto w dół o łącznej długości dziesięciu pikseli i szerokości jednego piksela.
Ogólnie rzecz biorąc, najprawdopodobniej interesuje Cię tylko to, co robi metoda ready2D () . Podałem przykłady kodu źródłowego innych metod, aby dać ci wyobrażenie o tym, jak większość gier robi scenę świata 3D i kolejność rysowania w GUI.
([0...1], [0...1], 0, 1)
bez projekcji, matrycy widoku lub świata, zawsze wylądują one w przestrzeni ekranu.