使用OpenGL 3.2+和FBOs在Linux上进行离屏渲染

5
我有一台Ubuntu机器,还有一个在OS X上编写的命令行应用程序,使用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);

"系统提供者"是围绕OS X的NSOpenGLContext的C++包装器,仅用于创建渲染上下文并使其当前,而不将其与窗口关联。所有渲染都发生在FBO中。
我正在尝试使用相同的方法来使用GLX在Linux(Ubuntu)上进行操作,但我很难做到这一点,因为我发现GLX需要像素缓冲区。
我正在尝试按照此教程进行操作:

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

在最后,它使用像素缓冲区来使上下文当前,我听说这已经被弃用了,我们应该放弃它,转而使用帧缓冲对象,是这样吗(我可能错了)?
有没有更好的方法或想法?

我希望你能详细说明一下替代方案,以及为什么你认为它们不是很有用,因为通过简单的谷歌搜索,人们说其中最好的方法之一是使用FBO,不仅可以进行离屏渲染,还可以进行纹理渲染效果。我很想听听你的替代方案。 - csotiriou
帧缓冲通常更加灵活,自从ES3以来,我认为它们支持渲染缓冲区所支持的一切,因此我个人认为在不支持它们的硬件上使用渲染缓冲区是没有意义的。 - Bartek Banachewicz
2
@BartekBanachewicz 我相信他在谈论像素缓冲区,而不是渲染缓冲区。我正在尝试在Ubuntu上使用GLX做完全相同的事情。OP提到的链接使用像素缓冲区来生成上下文。但是像素缓冲区已经被弃用,现在首选FBOs。他所问的是,如果我们想使用FBOs,需要做什么。 - informer2000
@csotiriou 我也在研究同样的事情。你找到解决方案了吗? - informer2000
是的,请查看答案。 - csotiriou
显示剩余3条评论
1个回答

4

我不知道这是否是最佳解决方案,但对于我来说它确实有效。

将函数绑定到可用的本地变量上

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

我们的对象作为类属性:
Display *display;
GLXPbuffer pbuffer;
GLXContext openGLContext;

设置上下文:

在IT技术相关内容中建立适当的环境:
    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);

使用上下文:

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

之后,一个人可以像在任何其他情况下一样正常使用FBOs。直到今天,我的问题实际上还没有得到答案(如果有更好的替代方案),所以我只是提供了一个对我有效的解决方案。在我看来,GLX没有像OpenGL一样使用像素缓冲区的概念,因此我感到困惑。渲染离屏的首选方式是FBOs,但要在Linux上创建OpenGL上下文,必须创建一个像素缓冲区(即GLX类型)。之后,使用我在问题中提供的代码与FBOs将按预期工作,就像在OS X上一样。


我的编译器告诉我'glXCreateContextAttribsARBProc'是一个未知的类型名称。(Ubuntu 16.04) - Zendel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接