Tworzenie HUD / GUI z OpenGL (LWJGL)


15

Jestem na etapie tworzenia gry, w którym muszę stworzyć interfejs lub GUI. Nigdy nie dotarłem do tej części, więc nie wiem, jak to się robi. Próbowałem renderować prosty quad w stałej pozycji na ekranie, ale jest problem. Aby mój aparat działał z ortografią, używam tego:

public void lookThrough()
{
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GL11.glOrtho(position.x, position.x + Display.getDisplayMode().getWidth()/zoom, position.y + Display.getDisplayMode().getHeight()/zoom, position.y, -1, 1);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
}

Nie rozumiem, jak mógłbym zrobić coś naprawionego na ekranie za pomocą tej metody? Jakiś sposób na to? Dzięki :)


Nie odpowiem, ponieważ jest to z perspektywy Direct3D, ale jeśli użyjesz współrzędnych ([0...1], [0...1], 0, 1)bez projekcji, matrycy widoku lub świata, zawsze wylądują one w przestrzeni ekranu.
Jonathan Dickinson

Odpowiedzi:


13

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.widthi m_Setup.heightto 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.


Dzięki, po prostu nie wiedziałem, czy przełączanie między orto a perspektywą byłoby niekorzystne dla wydajności, ponieważ wydaje mi się, że to duża operacja (oczywiście ledwo wiem, jak działa OpenGL ... wciąż się uczę!), Ale wszędzie mam widzieliście i co powiedzieliście, sugerujcie to. Więc chyba tak zrobię :)
smoth190

Podoba mi się ta odpowiedź, o której myślałem. Zastanawiałem się jednak, czy można to zrobić lepiej, przesuwając matrycę projekcyjną na każdym renderowaniu 2D, a następnie wstawiając ją później. Oznaczałoby to, że możesz raz skonfigurować 3D na pewno? Następnie wystarczy ponownie wywołać konfigurację 3D w celu zmiany rozmiaru okna, jeśli sobie z tym poradzisz.
Żarówka 1
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.