2010-05-24 10 views
30

Mi piacerebbe avere un contesto OpenGL senza finestre (su GNU/linux con Xorg e Windows). Non renderò nulla ma solo chiamate funzioni come glGetString, glCompileShader e simili.OpenGL senza finestre

Ho fatto qualche goggling ma non ho trovato nulla di utile, tranne la creazione di una finestra nascosta; che mi sembra un trucco.

Così qualcuno ha un'idea migliore (per qualsiasi piattaforma)?

EDIT: Con Xorg sono stato in grado di creare e collegare un contesto OpenGL alla radice dei finestrini:

#include<stdio.h> 
#include<stdlib.h> 
#include<X11/X.h> 
#include<X11/Xlib.h> 
#include<GL/gl.h> 
#include<GL/glx.h> 

int main(int argc, const char* argv[]){ 
    Display *dpy; 
    Window root; 
    GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; 
    XVisualInfo *vi; 
    GLXContext glc; 

    dpy = XOpenDisplay(NULL); 

    if (!dpy) { 
    printf("\n\tcannot connect to X server\n\n"); 
    exit(0); 
    } 

    root = DefaultRootWindow(dpy); 
    vi = glXChooseVisual(dpy, 0, att); 

    if (!vi) { 
    printf("\n\tno appropriate visual found\n\n"); 
    exit(0); 
    } 

    glc = glXCreateContext(dpy, vi, NULL, GL_TRUE); 
    glXMakeCurrent(dpy, root, glc); 

    printf("vendor: %s\n", (const char*)glGetString(GL_VENDOR)); 

    return 0; 
} 

EDIT2: Ho scritto un breve articolo su windowless opengl (con il codice di esempio) in base alla risposta accettata

+1

Usa GetDesktopWindow per la piattaforma Windows. – Luca

risposta

21

In realtà, è necessario avere un handle di finestra per creare un contesto di rendering "tradizionale" (la finestra radice su X11 o la finestra del desktop su Windows sono buone per questo). Viene utilizzato per recuperare le informazioni OpenGL e la disponibilità di estensioni.

Una volta ottenute queste informazioni, è possibile distruggere il contesto di rendering e rilasciare la finestra "fittizio"!

Si dovrebbe verificare le estensioni ARB_extensions_string e ARB_create_context_profile, (descritti in queste pagine: ARB_create_context). Quindi, è possibile creare un contesto di rendering chiamando CreateContextAttribs, in modo indipendente dalla piattaforma, senza avere una finestra di sistema associata e richiedendo solo il contesto dispositivo di sistema:

 int[] mContextAttrib = new int[] { 
      Wgl.CONTEXT_MAJOR_VERSION, REQUIRED_OGL_VERSION_MAJOR, 
      Wgl.CONTEXT_MINOR_VERSION, REQUIRED_OGL_VERSION_MINOR, 
      Wgl.CONTEXT_PROFILE_MASK, (int)(Wgl.CONTEXT_CORE_PROFILE_BIT), 
      Wgl.CONTEXT_FLAGS, (int)(Wgl.CONTEXT_FORWARD_COMPATIBLE_BIT), 
      0 
     }; 


     if ((mRenderContext = Wgl.CreateContextAttribs(mDeviceContext, pSharedContext, mContextAttrib)) == IntPtr.Zero) 
      throw new Exception("unable to create context"); 

Poi, si potrebbe associare un telaio oggetto buffer o una finestra di sistema al contesto di rendering creato, se si desidera eseguire il rendering (ma come ho capito, si desidera compilare solo shader).

Utilizzando CreateContextAttribs ha molti vantaggi:

  • È piattaforma indipendente
  • E 'possibile richiedere OpenGL specifica implementazione
  • E' possibile richiesta implementazione a> 3.2 OpenGL
  • È possibile al forza l'opzione di compatibilità in avanti (Shader solo rendering, questo è il futuro modo)
  • E 'possibile selezionare (in un contesto compatibile solo in avanti) uno specifico profilo di esecuzione OpenGL (in realtà c'è solo il profilo NUCLEO , ma potrebbe esserci di più in futuro.
  • E 'possibile abilitare un'opzione di debug, anche se non è definito come tale opzione potrebbe essere utilizzato con l'attuazione effettiva conducente

Tuttavia, hardware più vecchio/driver non poteva utensileria questa estensione, infatti, suggerisco di scrivere un codice di fallback per creare un contesto compatibile con le versioni precedenti.

+0

Questo mi sembra quello che sto cercando, lo proverò. – ext

+0

come si fa la stessa cosa su Windows? –

+0

@PetarIvanov Esattamente con lo stesso eseguibile, utilizzando C#. Tuttavia, tutte le API OpenGL sono portatili. – Luca

2

Hai bisogno di una finestra per ospitare il contesto e hai bisogno di un contesto per poter fare qualsiasi cosa.

Source

Se non si desidera visualizzare qualche cosa per renderli la finestra invisibile.

Se ci fosse un altro modo per farlo, sarebbe stato documentato da qualche parte e facilmente reperibile in quanto non è un problema raro.

7

Fino a quando non si crea una finestra, OpenGL non ha idea di quale implementazione si utilizza. Ad esempio, c'è un driver molto diverso (e una diversa accelerazione hardware) per OpenGL in una sessione X-Windows remota vs OpenGL in una sessione X-Windows DRI. Il supporto del linguaggio shader potrebbe essere diverso tra questi casi e l'output del compilatore shader sarà sicuramente dipendente dall'implementazione, così come gli eventuali errori generati in base all'esaurimento delle risorse.

Così, mentre in realtà la creazione di una finestra potrebbe non essere necessaria al 100%, devi associare il tuo contesto all'hardware grafico (o alla sua mancanza) in qualche modo, e dato che questo può essere fatto con una finestra nessuno si è preoccupato di implementare un metodo alternativo .

+0

E riguardo la creazione di un contesto e l'associazione con la finestra radice? – ext

+0

@ext: sembra un approccio ragionevole. Si noti che non è stato necessario scrivere codice aggiuntivo per OpenGL per gestire tale caso, è comunque "associare un nuovo contesto con una finestra", invece di "associare un nuovo contesto con questa scheda grafica e no non ho una finestra" . Basta fare attenzione a non eseguire il rendering nella finestra radice. –

1

Una delle cose che ho fatto - che è certamente un po 'un trucco - per evitare il sovraccarico di creare la mia finestra GL - è sfruttare le finestre di processo aperte.

La chiave per comprendere OpenGL è questa: tutto ciò che serve per creare un contesto GL con la chiamata a wglCreateContext è un DC valido.

Non c'è NULLA nella documentazione che dice che deve essere quella che possiedi.

Per testare questo, sono spuntato Worlds Of Warcraft, e sfruttando SPY ++ per ottenere un handle di finestra, ho quindi inserito manualmente tale handle in una chiamata a GetDC, che restituisce un Device Context valido, e da lì, ho eseguito il resto del mio codice GL come normale.

Nessuna creazione di una finestra GL.

Ecco cosa è successo quando ho fatto questo con entrambe le Worlds of Warcraft e Star Trek Online https://universalbri.wordpress.com/2015/06/05/experiment-results

Quindi, per rispondere alla tua domanda, sì avete bisogno di una finestra, ma non c'è niente nella documentazione in cui si afferma che la finestra deve essere di proprietà di te

Ora si consiglia: non è possibile ottenere questo metodo per fornire un output visivo valido utilizzando la finestra del desktop, ma sono riuscito a creare un controller di dominio utilizzando l'API getDeskTopWindow per HWND e quindi una chiamata a GetDC. Quindi, se c'è un'elaborazione non visiva, vuoi usare OpenGL per - fammi sapere cosa stai facendo, sono curioso, e se ti capita di ottenere il metodo GetDesktopWindow lavorando con le immagini - PER FAVORE ripubblicare su questo thread cosa hai fatto.

Buona fortuna.

E non permettere a nessuno di dirti che non si può fare.

Quando c'è una volontà c'è un modo.

Problemi correlati