Realizzare un HUD / GUI con OpenGL (LWJGL)


15

Sono nella fase di sviluppo del mio gioco in cui devo creare un HUD o una GUI. Non sono mai arrivato a questa parte, quindi non so come sia stato fatto. Ho provato a renderizzare un quad semplice in una posizione fissa sullo schermo, ma c'è un problema. Per far funzionare la mia fotocamera con ortogonale, utilizzo questo:

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

Non vedo come sarei in grado di riparare qualcosa sullo schermo usando questo metodo? Qualche modo per aggirare questo? Grazie :)


Non risponderò perché questo proviene da una prospettiva Direct3D, ma se usi le coordinate ([0...1], [0...1], 0, 1)senza proiezione, vista o matrice mondiale, finiranno sempre nello spazio dello schermo.
Jonathan Dickinson,

Risposte:


13

Questo proviene da un vecchio motore di gioco basato su OpenGL che stavo cercando di scrivere circa sette anni fa, scritto in C ++, così nudo con me mentre provo a spiegare come ho gestito il mondo 3D e le operazioni di rendering della GUI 2D al suo interno. Ho usato quattro metodi principali all'interno della mia classe di rendering OpenGL (OGLRender) di cui sono:

  • ready3D () per preparare OpenGL per il rendering della scena mondiale 3D.
  • ready2D () per preparare OpenGL per il rendering della GUI 2D.
  • render3D () per il disegno reale della scena del mondo 3D.
  • render2D () per l'effettivo disegno della 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 poi nel loop del thread principale, chiamerei semplicemente i metodi nel seguente ordine:

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

    SDL_GL_SwapBuffers(); // make drawn frame visible
}

Quindi, quello che sto facendo è disegnare prima la mia scena mondiale 3D e poi disegnare la mia GUI in quel modo la GUI è sempre in cima alla scena mondiale. Il metodo ready3D () prepara la proiezione del mondo 3D per il disegno della scena mondiale e il metodo ready2D () prepara la scena orto 2D per il disegno della GUI. m_Setup.widthe m_Setup.heightsono solo le dimensioni dello schermo della porta di visualizzazione.

La particolarità del metodo ready2D () è che la gluOrtho2D()funzione viene chiamata con argomenti che lo dicono quando disegniamo le primitive della GUI le disegniamo nelle coordinate dello schermo specificate per abbinare Windows, Mac e altri sistemi di coordinate dello schermo del desktop. Come in alto a sinistra è (0,0) in formato (X, Y) mentre in basso a destra è (ViewportWidth-1, ViewportHeight-1). E glTranslatef()viene utilizzato per correggere il posizionamento accurato per pixel. In modo che quando tracciamo una linea da (0,0) a (0,9), allora la linea verrà effettivamente tracciata dalla parte superiore sinistra e verso il basso di dieci pixel in totale lunghezza e una larghezza di pixel.

Nel complesso, molto probabilmente sei solo interessato a ciò che sta facendo il metodo ready2D () . Ho fornito esempi di codice sorgente degli altri metodi per darti un'idea di come generalmente la maggior parte dei giochi fa la scena del mondo 3D e l'ordine di disegno della GUI.


Grazie, non sapevo se il passaggio tra orto e prospettiva sarebbe negativo per le prestazioni, perché a me sembra una grande operazione (ovviamente so a malapena come funziona OpenGL ... ancora imparando!) Ma ovunque ho visto e cosa hai detto, suggerisci di farlo. Quindi suppongo che lo farò :)
smoth190

Mi piace questa risposta è un po 'quello che stavo pensando di fare. Mi stavo solo chiedendo se potesse essere fatto meglio spingendo la tua matrice di proiezione su ogni rendering 2D e poi saltando fuori. Ciò significherebbe che potresti semplicemente configurare il 3D una volta sicuramente? Quindi dovrai solo richiamare nuovamente la tua configurazione 3D per modificare le dimensioni della finestra se lo gestisci.
Lampadina 1
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.