2014-02-18 8 views
5

Ich habe Ubuntu Maschine und eine Befehlszeile in OS X geschrieben, die etwas außerhalb des Bildschirms mit FBOs macht. Dies ist Teil des Codes.Linux Rendern Offscreen mit OpenGL 3.2 + w/FBOs

 this->systemProvider->setupContext(); //be careful with this one. to add thingies to identify if a context is set up or not 
    this->systemProvider->useContext(); 
    glewExperimental = GL_TRUE; 
    glewInit(); 


    GLuint framebuffer, renderbuffer, depthRenderBuffer; 

    GLuint imageWidth = _viewPortWidth, 
      imageHeight = _viewPortHeight; 

    //Set up a FBO with one renderbuffer attachment 
    glGenFramebuffers(1, &framebuffer); 
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 

    glGenRenderbuffers(1, &renderbuffer); 
    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, imageWidth, imageHeight); 
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); 


    //Now bind a depth buffer to the FBO 
    glGenRenderbuffers(1, &depthRenderBuffer); 
    glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer); 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, _viewPortWidth, _viewPortHeight); 
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer); 

Die „Systemanbieter“ ist ein C++ Wrapper um OS X NSOpenGLContext, die gerade verwendet wird, eine Wiedergabe-Kontext zu erstellen und aktuellen machen, ohne es mit einem Fenster zugeordnet wird. Das gesamte Rendering erfolgt in den FBOs.

Ich versuche den gleichen Ansatz für Linux (Ubuntu) mit GLX zu verwenden, aber ich habe es schwer, da ich sehe, dass GLX einen Pixelpuffer benötigt.

Ich versuche, dieses Tutorial zu folgen:

http://renderingpipeline.com/2012/05/windowless-opengl/

Am Ende es wird ein Pixelpuffer den Kontext Strom zu machen, was ich höre, ist veraltet, und wir sollten es für Frame Buffer aufgeben Objekte, ist das richtig (ich kann mich deswegen irren).

Hat jemand einen besseren Ansatz oder eine bessere Idee?

+0

Nun, ja, renderbuffer sind heutzutage nicht von großem Nutzen. –

+0

Können Sie es ausarbeiten? Was meinst du mit Renderpuffern? Haben Sie eine bessere plattformübergreifende Alternative? – csotiriou

+0

Was könnte ich möglicherweise mit "renderbuffer" meinen? Dein Code benutzt sie. –

Antwort

4

Ich weiß nicht, ob es die beste Lösung ist, aber es funktioniert sicherlich für mich.

Bindung die Funktionen auf lokale Variablen, die wir

typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); 
typedef Bool (*glXMakeContextCurrentARBProc)(Display*, GLXDrawable, GLXDrawable, GLXContext); 
static glXCreateContextAttribsARBProc glXCreateContextAttribsARB = NULL; 
static glXMakeContextCurrentARBProc glXMakeContextCurrentARB = NULL; 

Unsere Objekte als Klasseneigenschaften verwenden können:

Display *display; 
GLXPbuffer pbuffer; 
GLXContext openGLContext; 

Einrichten der Kontext:

glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB"); 
    glXMakeContextCurrentARB = (glXMakeContextCurrentARBProc) glXGetProcAddressARB((const GLubyte *) "glXMakeContextCurrent"); 

    display = XOpenDisplay(NULL); 
    if (display == NULL){ 
     std::cout << "error getting the X display"; 
    } 

    static int visualAttribs[] = {None}; 
    int numberOfFrameBufferConfigurations; 
    GLXFBConfig *fbConfigs = glXChooseFBConfig(display, DefaultScreen(display), visualAttribs, &numberOfFrameBufferConfigurations); 

    int context_attribs[] = { 
     GLX_CONTEXT_MAJOR_VERSION_ARB ,3, 
     GLX_CONTEXT_MINOR_VERSION_ARB, 2, 
     GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, 
     GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 
     None 
    }; 

    std::cout << "initialising context..."; 
    this->openGLContext = glXCreateContextAttribsARB(display, fbConfigs[0], 0, True, context_attribs); 

    int pBufferAttribs[] = { 
     GLX_PBUFFER_WIDTH, (int)this->initialWidth, 
     GLX_PBUFFER_HEIGHT, (int)this->initialHeight, 
     None 
    }; 

    this->pbuffer = glXCreatePbuffer(display, fbConfigs[0], pBufferAttribs); 
    XFree(fbConfigs); 
    XSync(display, False); 

Mit dem Kontext:

if(!glXMakeContextCurrent(display, pbuffer, pbuffer, openGLContext)){ 
    std::cout << "error with content creation\n"; 
}else{ 
    std::cout << "made a context the current context\n"; 
} 

Danach kann man FBOs normalerweise verwenden, als würde er in einem anderen Anlass. Bis heute ist meine Frage eigentlich unbeantwortet (wenn es eine bessere Alternative gibt), also biete ich nur eine Lösung an, die für mich funktioniert hat. Es scheint mir, dass GLX den Begriff der Pixelpuffer nicht so verwendet wie OpenGL, daher meine Verwirrung. Die bevorzugte Möglichkeit, Offscreen zu rendern, sind FBOs, aber für einen OpenGL-Kontext, der unter Linux erstellt werden soll, muss ein Pixelpuffer (der GLX-Typ) erstellt werden. Danach funktioniert die Verwendung von FBOs mit dem Code, den ich in der Frage bereitgestellt habe, wie erwartet, genauso wie unter OS X.