In OpenGL, è una cattiva idea "combinare" la modalità immediata e la modalità mantenuta per il bene delle GUI?


8

Supponiamo che io stia disegnando una scena 3D glDrawArrays(...)e voglio renderizzare qualcosa di semplice, come una sovrapposizione 2D. Sarebbe una cattiva idea usare la modalità immediata per una cosa del genere, invece di impostare un renderer 2D con modalità mantenuta?

Esempio:

void Draw()
{
    // Draw the 3D scene:
    // *does stuff*
    glDrawArrays(...);
    // *some other stuff*

    // Setup a quad with immediate mode (for something like a vignette overlay)
    glBegin(GL_QUADS);
    glTexCoord2f(...); glVertex2f(...);
    glEnd();
}

Minecraft fa questo. Funziona bene, tranne per limitare la tua versione OpenGL (a <3.1 o un profilo di compatibilità) e per rendere la tua GUI meno veloce.
user253751

Nota Minecraft ha anche un proprio set di funzioni che simulano la modalità immediata usando array di vertici: non è difficile scrivere. Non sono ancora sicuro se li stanno usando per la GUI.
user253751

Risposte:


7

È una cattiva idea in quanto non ha senso. Non c'è nulla da "impostare" che non hai già fatto, ad eccezione di una matrice di proiezione orto (che dovrai comunque fare).

La portabilità probabilmente non è un problema, sebbene dovrebbe esserlo. Gli IHV sembrano essere molto riluttanti a rinunciare al supporto della modalità immediata per il futuro prevedibile (sembra "funzionare bene" anche nei profili di base), quindi anche se la modalità immediata avrebbe dovuto estinguersi molto tempo fa, probabilmente rimarrà per sempre. Le prestazioni sono un'altra storia. Vuoi davvero qualcosa che rappresenti lo 0,1% della complessità della scena per consumare il 15-20% del tempo della CPU - le chiamate GL sono relativamente leggere, rispetto ad esempio a DX, ma non sono gratuite - e il 15-20% di tempo reale dei fotogrammi dovuto allo stallo della tubazione? Puoi permettertelo con il tuo budget? La maggior parte dei giochi non può.

E poi, naturalmente, le stranezze. Oh le stranezze. L'apparente bellezza della modalità immediata è che è (apparentemente) facile e diretto fare qualcosa come disegnare un paio di quad veloci. In realtà, la modalità immediata può essere un tale dolore nella parte posteriore, è così piena di insidie ​​non ovvie.
D'altra parte, è altrettanto facile (e più semplice se me lo chiedi!) Scrivere semplicemente una piccola funzione a 5 LOC DrawQuadche quando viene chiamata aggiunge coordinate e indici di vertice a un buffer di memoria e incrementa un contatore. Che, sorpresa, puoi quindi disegnare glDrawArrays/Elementse con cui puoi riutilizzare (la copia della GPU, non solo la copia della terra dell'utente!) Il fotogramma successivo così com'è fintanto che nulla è cambiato.
La modalità immediata deve, non c'è altro modo, allocare un buffer ed eseguire ogni volta un trasferimento PCIe. Oppure, qualcosa di equivalente in latenza (GPU che legge la memoria principale sul bus, qualunque cosa). Il driver non può sapere (o presumere) che i dati siano rimasti esattamente gli stessi del frame precedente.

Il trasferimento dei dati nella GPU è un'operazione ad alta velocità, ma anche ad alta latenza . Non solo il trasferimento del bus è di per sé un protocollo complicato e ad alta latenza (diversi livelli di protocollo, pacchetti, riconoscimenti, ecc.), Ma non tutte le GPU sono anche in grado di trasferire e disegnare contemporaneamente, o se possono farlo , potrebbero non essere sempre in grado di alternare o avviare nuove operazioni liberamente mentre fanno qualcosa di diverso. Leggi come: Non trasferire invano .


"Non c'è nulla da" impostare "che non hai già fatto" Rendering in batch?
HolyBlackCat

2
Sebbene gli IHV siano riluttanti a abbandonare la modalità immediata, ci sono anche driver video in Linux che non supportano una versione OpenGL superiore a meno che non si richieda il profilo principale. Questo in particolare significa grafica Intel HD ( inteldriver), ma anche chip NVidia e AMD quando si utilizzano driver open source ( nouveaue amdgpurispettivamente). Allo stesso modo, su MacOS non hai anche il profilo di compatibilità con OpenGL> 2.1.
Ruslan,

@HolyBlackCat: non sono sicuro di cosa intendi? Gli stati OP hanno una pipeline 3D funzionante basata su glDrawArrays. Quindi c'è tutto impostato che è necessario per fare ancora un'altra chiamata glDrawElements(o Array, a seconda di) per disegnare tutti i quad per la GUI (dopo aver scritto i vertici in un buffer). Le funzioni sono caricate, hai un framework per l'allocazione dei buffer, ecc. Niente di speciale da fare per il batch della GUI, davvero. Basta bind (o no, se avete abbastanza TU a sinistra per lasciarlo legato) la texture grafica, impostare la matrice orto, e fare una chiamata pareggio supplementare. Come si desidera eseguire il batch in modo migliore?
Damon,

(Ovviamente sono d'accordo sul fatto che la modalità immediata sia negativa.) Scusatemi se non ero chiaro. Intendo il processo di riempimento di detto buffer di vertici. È facile, ma è leggermente più lavoro che usare la modalità immediata.
HolyBlackCat

12

Personalmente lo vedo solo come male per due motivi:

  1. È molto obsoleto e deprecato. E,
  2. È molto più lento dei modi moderni di disegnare con OpenGL.

Ma, se funziona, e le prestazioni non saranno un problema, e se non è un problema per te utilizzare funzioni OpenGL deprecate nel tuo programma, allora credo che potresti farlo. Sarà più lento avere tonnellate e tonnellate di GUI, ma se non è così tanti, ancora una volta, provaci.

Comprendilo, però. Che alla fine della giornata, OpenGL sta facendo la stessa cosa; disegno sullo schermo. La modalità immediata è solo molto più lenta se si devono elaborare molte cose. Quindi, dovresti scegliere qual è il più utile per l'attività che hai in mente. Spero che questo ti aiuti!


1

Un altro aspetto negativo è che rende il tuo codice meno portatile. Alcune varianti di OpenGL non supportano affatto la modalità immediata, ad esempio OpenGL ES. (e poiché i dispositivi basati su Android di calibro più grande come i tablet ottengono maggiore trazione, potrebbe diventare importante)


0

L'uso della modalità immediata non è assolutamente necessario per il lavoro relativo alla gui.

Per creare un semplice oggetto gui, diciamo, un pulsante:

  1. Hai bisogno di una maglia quadrata / triangolare,
  2. Una trama per la maglia
  3. Una trasformazione di proiezione ortografica

In questo modo, puoi semplicemente scrivere un semplice shader pass-through che ignora le considerazioni sull'illuminazione e ridimensionare semplicemente l'elemento gui su una scala di pixel o una percentuale della finestra, quindi eseguire un algoritmo di pittori per il rendering.

In questo modo, puoi realizzare un sistema di interfaccia utente completo con tutti i vantaggi in termini di prestazioni della modalità mantenuta.

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.