当我使用 glBlitFramebuffer 实现 MSAA 时收到 INVALID OPERATION

Posted

技术标签:

【中文标题】当我使用 glBlitFramebuffer 实现 MSAA 时收到 INVALID OPERATION【英文标题】:I receive INVALID OPERATION when I use glBlitFramebuffer to implement MSAA 【发布时间】:2017-09-12 07:56:41 【问题描述】:

也许我有一些愚蠢的问题。如果有人可以回复他们,我将不胜感激。 所有问题都是基于android环境和OpenGL ES。

    如何验证我是否打开了 MSAA?如果我画一些点大小为 50 的GL_POINTS,就会有一些小方块。如果我启用了 4x MSAA,小方块可以变成圆点吗?

    我尽了最大的努力来启用带有 FBO 和 BlitFBO 的 MSAA。但它什么也没画,glBlitFramebuffer() 调用后出现错误 INVALID_OPERATION。

这是我上面提到的完整项目:https://github.com/Enoch-Liu/GL

以下是关键代码:

void Renderer::MultisampleAntiAliasing() 
    glGenRenderbuffers(1, &m_MSColor);
    glBindRenderbuffer(GL_RENDERBUFFER, m_MSColor);
    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, m_width, m_height);
    checkGLError("GenMSColorBuffer");

    glGenFramebuffers(1, &m_MSFBO);
    glBindFramebuffer(GL_FRAMEBUFFER, m_MSFBO);


    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_MSColor);
    checkGLError("FboRbo,COLORATTACHMENT");

    glGenRenderbuffers(1, &m_MSDepth);
    glBindRenderbuffer(GL_RENDERBUFFER, m_MSDepth);
    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, m_width, m_height);
    checkGLError("GenDepthBuffer");

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_MSDepth);
    checkGLError("DepthBuffer,Renderbuffer");
    GLenum drawBufs[] = GL_COLOR_ATTACHMENT0;
    glDrawBuffers(1, drawBufs);
    checkGLError("DrawBuffer");

    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
        LOG_ERROR("failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
    



void Renderer::drawFrame() 
    //LOG_INFO("drawFrame %d x %d", width, height);
    static float r=0.9f;
    static float g=0.2f;
    static float b=0.2f;

    LOG_INFO("xxx %d, %d", m_width,m_height);
    if (OPENMSAA)
    
        glBindFramebuffer(GL_FRAMEBUFFER, m_MSFBO);
        glBindRenderbuffer(GL_RENDERBUFFER, m_MSColor);
        checkGLError("BindTwoBuffers");
    

    glViewport(0,0,m_width,m_height);
    glScissor(0,0,m_width,m_height);

    glClearColor(r, g, b, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_DEPTH_TEST);

    const GLfloat landscapeOrientationMatrix[16] = 
            1.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f ;
    const GLfloat color[4] = 
            1.0f, 0.0f, 0.0f, 1.0f
    ;
    glUseProgram( m_program );
    glUniformMatrix4fv(m_uMvp, 1, GL_FALSE, landscapeOrientationMatrix);
    glUniform4fv(m_uColor, 1, color);
    m_p = glGetAttribLocation(m_program, "vPosition");
    m_p1 = glGetAttribLocation(m_program, "vPosition1");

    glEnableVertexAttribArray( m_p );
    glVertexAttribPointer( m_p , 3, GL_FLOAT, false, 3 * sizeof( float ), squareCoords);

    glDrawArrays(GL_POINTS, 0, 4);
    glDisableVertexAttribArray( m_p );
    glFlush();
    checkGLError("Before Blit");
    if (OPENMSAA)
    
        glBindFramebuffer(GL_READ_FRAMEBUFFER, m_MSFBO);
        checkGLError("BindReadBuffer");
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
        checkGLError("BindFramebuffer");
        glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
        checkGLError("BlitFramebufferColor");
        glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
        checkGLError("BlitFramebufferDepth");
        glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    

帧缓冲区已完成。

【问题讨论】:

MSAA 不会影响点是呈现为圆形还是正方形。它可以在亚像素的基础上平滑边缘。 非常感谢,BDL。 【参考方案1】:

深度缓冲区的内部格式必须匹配:https://www.opengl.org/discussion_boards/showthread.php/173275-Alternative-to-glBlitFramebuffer%28%29

查看您的 github 项目,您根本没有配置深度缓冲区。来自您的项目:

const EGLint attribs[] = 

//        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,

        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,

        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,

        EGL_BLUE_SIZE, 8,

        EGL_GREEN_SIZE, 8,

        EGL_RED_SIZE, 8,

        EGL_ALPHA_SIZE, 8,

        EGL_SAMPLE_BUFFERS, 1,

        EGL_SAMPLES, 4,

        EGL_NONE

;

【讨论】:

是的!你说的对 !但是,在我的代码中,实现 FBO-Blit MSAA 的属性应该更少。 EGL_SAMPLE_BUFFERS 和 EGL_SAMPLES 也应该被删除。正确代码如下: const EGLint attribs[] = EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE ;

以上是关于当我使用 glBlitFramebuffer 实现 MSAA 时收到 INVALID OPERATION的主要内容,如果未能解决你的问题,请参考以下文章

将深度渲染缓冲区复制到深度缓冲区

Intel和Nvidia之间的OpenGL fbo blitting不一致

从一个帧缓冲区读取到另一个帧缓冲区时出现问题

为啥当我使用hibernate时这个类应该实现java.io.Serializable?

当我可以从静态实现相同的目标时,为啥我需要使用动态内存分配?

当我使用反应钩子实现选择任何复选框时,启用按钮有啥问题? [复制]