Créer un HUD / GUI avec OpenGL (LWJGL)

15

Je suis à l'étape du développement de mon jeu où j'ai besoin de créer un HUD ou une GUI. Je ne suis jamais arrivé à cette partie, donc je ne sais pas comment c'est fait. J'ai essayé de rendre un simple quad à une position fixe sur l'écran, mais il y a un problème. Pour faire fonctionner ma caméra avec orthographique, j'utilise ceci:

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);
}

Je ne vois pas comment je pourrais faire quelque chose de fixe sur l'écran en utilisant cette méthode? Quelque chose autour de ça? Merci :)

smoth190
la source
Je ne répondrai pas parce que c'est du point de vue Direct3D, mais si vous utilisez les coordonnées ([0...1], [0...1], 0, 1)avec AUCUNE projection, vue ou matrice mondiale, elles atterriront toujours dans l'espace de l'écran.
Jonathan Dickinson,
stackoverflow.com/questions/5467218/opengl-2d-hud-over-3d
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Réponses:

13

Cela provient d'un ancien moteur de jeu basé sur OpenGL que j'essayais d'écrire il y a environ sept ans écrit en C ++ si nu avec moi alors que j'essaie d'expliquer comment je gérais le monde 3D et les opérations de rendu GUI 2D en son sein. J'ai utilisé quatre méthodes principales dans ma classe de rendu OpenGL (OGLRender), dont:

  • ready3D () pour préparer OpenGL au rendu de la scène mondiale 3D.
  • ready2D () pour préparer OpenGL au rendu de l'interface graphique 2D.
  • render3D () pour le dessin de la scène mondiale 3D réelle.
  • render2D () pour le dessin GUI 2D réel.

    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 ...
    }

Et puis dans la boucle de thread principale, j'appellerais simplement les méthodes dans l'ordre suivant:

while(m_drawFrame)
{
    gm_Render->render3D(); // draw 3D scene
    gm_Render->render2D(); // draw GUI

    SDL_GL_SwapBuffers(); // make drawn frame visible
}

Donc, ce que je fais, c'est que je dessine d'abord ma scène mondiale 3D, puis je dessine mon interface graphique en dernier de cette façon, l'interface graphique est toujours au sommet de la scène mondiale. La méthode ready3D () prépare la projection du monde 3D pour le dessin de la scène mondiale et la méthode ready2D () prépare la scène ortho 2D pour le dessin de l'interface graphique. m_Setup.widthet ne m_Setup.heightsont que les dimensions de l'écran du port de vue.

La particularité de la méthode ready2D () est que la gluOrtho2D()fonction est appelée avec des arguments qui lui indiquent que lorsque nous dessinons les primitives GUI, nous les dessinons dans les coordonnées d'écran spécifiées pour correspondre à Windows, Mac et autres systèmes de coordonnées d'écran de bureau. Tels que le coin supérieur gauche est (0,0) au format (X, Y) tandis que le coin inférieur droit l'est (ViewportWidth-1, ViewportHeight-1). Et glTranslatef()est utilisé pour corriger le positionnement précis par pixel. De sorte que lorsque nous dessinons une ligne de (0,0) à (0,9), la ligne sera en fait dessinée en haut à gauche et en bas de dix pixels de longueur et d'une largeur de pixel.

Dans l'ensemble, vous êtes probablement intéressé par ce que fait la méthode ready2D () . J'ai fourni les exemples de code source des autres méthodes pour vous donner une idée de la façon dont la plupart des jeux font la scène mondiale 3D et l'ordre de dessin de l'interface graphique.

NAM TRON
la source
Merci, je ne savais tout simplement pas si le passage de l'ortho à la perspective serait mauvais pour les performances, car cela me semble être une grosse opération (bien sûr, je sais à peine comment fonctionne OpenGL ... j'apprends toujours!) Mais partout où j'ai vu, et ce que vous avez dit, suggérez de le faire. Donc je suppose que je le ferai :)
smoth190
J'aime cette réponse, c'est un peu ce que je pensais faire. Je me demandais simplement si cela pouvait être mieux fait en vous poussant la matrice de projection sur chaque rendu 2D puis en la sautant après. Cela signifierait que vous pourriez simplement configurer la 3D une fois? Ensuite, il vous suffira d'appeler à nouveau votre configuration 3D pour les changements de taille de fenêtre si vous gérez cela.
Ampoule1