如何找到有效的 OpenGL 帧缓冲区配置/文档

Posted

技术标签:

【中文标题】如何找到有效的 OpenGL 帧缓冲区配置/文档【英文标题】:How to find valid OpenGL framebuffer configuration/documentation 【发布时间】:2017-04-10 16:19:12 【问题描述】:

我使用的是 2011 年初的 MacBook Pro,装有 macOS Sierra 10.12.4 和 Intel HD Graphics 3000 512 MB,并且我使用的是 JOGL。根据OS X 10.9 Core Profile OpenGL Information(不幸的是,他们还没有更新版本的信息),我的系统支持 0、16 或 24 bpp 深度缓冲区和 0 或 8 bpp 模板缓冲区。然而,我创建用户帧缓冲区时的实际工作似乎是任何人的猜测:

我可以让它与 GL_DEPTH_COMPONENT_32 渲染缓冲区一起工作。 我无法让它与GL_STENCIL_INDEX8 渲染缓冲区一起工作——无论我使用的是16 位、24 位还是32 位深度缓冲区,我总是会收到GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENTGL_FRAMEBUFFER_UNSUPPORTED 错误。 但我可以让它与 GL_DEPTH24_STENCIL8 渲染缓冲区一起使用。

我无法在任何地方找到针对 OS X 的 GL_DEPTH24_STENCIL8 的具体提及。我想确保我的程序可以在各种系统上运行(包括 Windows 和 Linux,因为它是一个 JOGL 应用程序),但似乎我所能做的就是猜测并检查各种帧缓冲区配置,直到找到一个可行的.

真的没有更好的方法来决定使用什么帧缓冲区配置吗?有没有我没有找到的更好文档的网站?供应商是否因为某种原因难以记录?

代码示例

配置失败
    int[] temps = new int[3];
    this.width = width;
    this.height = height;

    gl3.glGenFramebuffers(1, temps, 0);
    framebuffer = temps[0];
    gl3.glBindFramebuffer(GL.GL_FRAMEBUFFER, framebuffer);

    int numBuffers = 2;
    if (desiredUseStencilBuffer) 
        numBuffers++;
    
    gl3.glGenRenderbuffers(numBuffers, temps, 0);
    colorBuffer = temps[0];
    depthBuffer = temps[1];
    stencilBuffer = temps[2];

    numSamples = targetNumSamples;
    useStencilBuffer = desiredUseStencilBuffer;

    if (numSamples > 1) 
        gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
        gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL.GL_RGBA8,
                width, height);

        gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
        gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
                GL.GL_DEPTH_COMPONENT24, width, height);
        if (useStencilBuffer) 
            gl3.glBindRenderbuffer(GL_RENDERBUFFER, stencilBuffer);
            gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
                    GL3.GL_STENCIL_INDEX8, width, height);
        
     else 
        gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
        gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_RGBA8, width, height);

        gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
        gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT24, width, height);
        if (useStencilBuffer) 
            gl3.glBindRenderbuffer(GL_RENDERBUFFER, stencilBuffer);
            gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL3.GL_STENCIL_INDEX8,
                    width, height);
        
    

    gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
    gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL2ES3.GL_DEPTH_ATTACHMENT,
            GL_RENDERBUFFER, depthBuffer);
    if (useStencilBuffer) 
        gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL2ES3.GL_STENCIL_ATTACHMENT,
                GL_RENDERBUFFER, stencilBuffer);
    

    int status = gl3.glCheckFramebufferStatus(GL_FRAMEBUFFER);
    switch (status) 
    case GL.GL_FRAMEBUFFER_COMPLETE:
        break;

    case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
        throw new RuntimeException("An attachment could not be bound to frame buffer object!");
配置成功
    int[] temps = new int[3];
    this.width = width;
    this.height = height;

    gl3.glGenFramebuffers(1, temps, 0);
    framebuffer = temps[0];
    gl3.glBindFramebuffer(GL.GL_FRAMEBUFFER, framebuffer);

    gl3.glGenRenderbuffers(2, temps, 0);
    colorBuffer = temps[0];
    depthBuffer = temps[1];

    numSamples = targetNumSamples;
    useStencilBuffer = desiredUseStencilBuffer;

    if (numSamples > 1) 
        gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
        gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL.GL_RGBA8,
                width, height);

        gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
        if (useStencilBuffer) 
            gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
                    GL.GL_DEPTH24_STENCIL8, width, height);
         else 
            gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
                    GL.GL_DEPTH_COMPONENT32, width, height);
        
     else 
        gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
        gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_RGBA8, width, height);

        gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
        if (useStencilBuffer) 
            gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8,
                    width, height);
         else 
            gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT32,
                    width, height);
        
    

    gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
    if (useStencilBuffer) 
        gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL2ES3.GL_DEPTH_STENCIL_ATTACHMENT,
                GL_RENDERBUFFER, depthBuffer);
     else 
        gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                GL_RENDERBUFFER, depthBuffer);
    

    int status = gl3.glCheckFramebufferStatus(GL_FRAMEBUFFER);
    switch (status) 
    case GL.GL_FRAMEBUFFER_COMPLETE:
        break;

    case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
        throw new RuntimeException("An attachment could not be bound to frame buffer object!");
    ...

【问题讨论】:

【参考方案1】:

OpenGL 规范不要求您可以将单独的深度和模板图像附加到帧缓冲区。 API 允许您尝试它,但个别实现可以通过为您提供不受支持的完成状态来选择禁止它。

3.0 规范添加了required image formats 的概念,其实现为required to accept 用于它们的帧缓冲配置。其中有GL_DEPTH24_STENCIL8。因此,需要任何兼容的 OpenGL 实现来支持组合的深度/模板缓冲区。

【讨论】:

谢谢,很高兴知道。何时(如果有)通常使用单独的模板附件?在他们自己单独的帧缓冲区中? @Andy:它们不是“常用的”。它们仅在需要时使用:当您渲染到不需要深度缓冲区的东西时。

以上是关于如何找到有效的 OpenGL 帧缓冲区配置/文档的主要内容,如果未能解决你的问题,请参考以下文章

来自 OpenGL ES 帧缓冲区 (iOS) 的 CGImageRef

如何定义 QT Opengl 帧缓冲区的大小

实现 pyglet 会破坏我曾经工作的帧缓冲区 OpenGL 代码

将OpenGL帧缓冲区对象与Qt(QOpenGLWidget)一起使用,绘制到帧缓冲区时如何禁用多重采样

openGL 中的帧速率和绘制流程

OpenGL:如何通过 API 知道顶点是不是正在命中帧缓冲区