【问题标题】:Cannot render to texture with multisampling无法使用多重采样渲染到纹理
【发布时间】:2014-06-06 00:37:53
【问题描述】:

我在this 页面 -original code- 中运行了帧缓冲区示例(在 osx 10.8 中使用 glfw3 和 xcode 4.6 中的 glew),它运行良好,然后我想添加多重采样(以避免立方体边缘上的锯齿状边缘和在地板上,glfwWindowHint (GLFW_SAMPLES, 4) 直接渲染到后台缓冲区时就足够了),找到了一些指向 opengl.org 的答案,尝试使用 glTexImage2DMultisample 但它什么也没显示(黑屏)。帧缓冲设置和渲染循环是:

// Create frame buffer
GLuint frameBuffer;
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);

// Create texture to hold color buffer
GLuint texColorBuffer;
glGenTextures(1, &texColorBuffer);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texColorBuffer);

//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, width, height, GL_FALSE);

/*
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
*/

//glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texColorBuffer, 0);

// Create Renderbuffer Object to hold depth and stencil buffers
GLuint rboDepthStencil;
glGenRenderbuffers(1, &rboDepthStencil);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthStencil);
//glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboDepthStencil);

// ...

while (!window->shouldClose()) {
    static int rot = 0;

    // Bind our framebuffer and draw 3D scene (spinning cube)
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
    auto err_res = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if(err_res != GL_FRAMEBUFFER_COMPLETE) {
        ERR("Incomplete frameBuffer:%X!", err_res);
        goto end;
    }

    glBindVertexArray(vaoCube);
    glEnable(GL_DEPTH_TEST);
    glUseProgram(sceneShaderProgram);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texKitten);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texPuppy);

    // Clear the screen to white
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
    glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));

    // Draw cube
    glEnable(GL_MULTISAMPLE);

    glDrawArrays(GL_TRIANGLES, 0, 36);

    glEnable(GL_STENCIL_TEST);

    // Draw floor
    glStencilFunc(GL_ALWAYS, 1, 0xFF);
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    glStencilMask(0xFF);
    glDepthMask(GL_FALSE);
    glClear(GL_STENCIL_BUFFER_BIT);

    glDrawArrays(GL_TRIANGLES, 36, 6);

    // Draw cube reflection
    glStencilFunc(GL_EQUAL, 1, 0xFF);
    glStencilMask(0x00);
    glDepthMask(GL_TRUE);

    model = glm::scale(glm::translate(model, glm::vec3(0, 0, -1)), glm::vec3(1, 1, -1));
    glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));

    glUniform3f(uniColor, 0.3f, 0.3f, 0.3f);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glUniform3f(uniColor, 1.0f, 1.0f, 1.0f);

    glDisable(GL_STENCIL_TEST);                

    /*
    // Bind default framebuffer and draw contents of our framebuffer
    glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
    glBindVertexArray(vaoQuad);
    glDisable(GL_DEPTH_TEST);
    glUseProgram(screenShaderProgram);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texColorBuffer);

    glDrawArrays(GL_TRIANGLES, 0, 6);
    */

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);   // Make sure no FBO is set as the draw framebuffer
    glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBuffer); // Make sure your multisampled FBO is the read framebuffer
    glDrawBuffer(GL_BACK);                       // Set the back buffer as the draw buffer
    glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);

    // Swap buffers
    glfwSwapBuffers(window->getHandle());
    glfwPollEvents();
}
  • glVersion: 3.2 NVIDIA-8.10.44 304.10.65f03
  • glRenderer:NVIDIA GeForce 9400M OpenGL 引擎

“EXT”添加可能是不必要的,但我之前也尝试在没有它们的情况下运行,结果是一样的。我做错了什么?

编辑:现在绑定GL_TEXTURE_2D_MULTISAMPLE 并得到GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 错误!

【问题讨论】:

    标签: opengl graphics textures framebuffer


    【解决方案1】:

    如果您检查了帧缓冲区对象的完整性,您现在可能已经发现了这一点……您的深度/模板缓冲区也需要进行多重采样。

    如果一个附件的样本数量与其他附件不同附件。在您的情况下,您有一个带有 4 个样本的颜色缓冲区附件和一个带有 1 个样本的深度/模板附件。

    名称

    glCheckFramebufferStatus — 检查帧缓冲区的完整性状态

    说明

    glCheckFramebufferStatus查询当前绑定到target的framebuffer对象的完整性状态。 target 必须是 GL_DRAW_FRAMEBUFFERGL_READ_FRAMEBUFFERGL_FRAMEBUFFERGL_FRAMEBUFFER 等价于 GL_DRAW_FRAMEBUFFER

    如果绑定到目标的帧缓冲区完整,则返回值为GL_FRAMEBUFFER_COMPLETE。否则,返回值确定如下:

    [...]

    如果 GL_RENDERBUFFER_SAMPLES 的值对于所有附加的渲染缓冲区都不相同,则返回

    GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;如果 GL_TEXTURE_SAMPLES 的值对于所有附加纹理都不相同;或者,如果附加的图像是渲染缓冲区和纹理的混合,则 GL_RENDERBUFFER_SAMPLES 的值与 GL_TEXTURE_SAMPLES 的值不匹配。


    要解决此问题,您需要分配具有 4 个样本的多重采样深度/模板附件:

    glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
    

    顺便说一句,由于您的实现是 >= 3.0,因此您不需要任何 EXT 后缀。 EXT 扩展定义的所有常量都与 ARB / 核心 FBO 相同,但某些 EXT 函数(例如glCheckFramebufferStatusEXT)具有更多限制性行为(例如,要求每个附件具有相同的图像尺寸)。

    【讨论】:

    • 我显然错过了它,但我已经在检查(正确吗?)并且没有收到任何错误!..无论如何,我编辑了代码(和问题),但没有任何改变??
    • 老实说,我不确定你为什么首先使用多重采样纹理。多重采样纹理增加了额外的硬件要求(您的硬件足以支持它们,但您仍然不需要它们)。除非您真的想在着色器中使用 multisampled 颜色缓冲区,否则我会为颜色缓冲区使用多重采样渲染缓冲区。无论如何,您都应该将texColorBuffer 绑定到GL_TEXTURE_2D_MULTISAMPLE
    • 同样,您可能会想纠正glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 以申请GL_TEXTURE_2D_MULTISAMPLE...但不要。纹理过滤在多重采样纹理上是不可能的。事实上,没有采样器参数适用于多重采样纹理,这就是为什么GL_TEXTURE_2D_MULTISAMPLE 不是该函数的有效目标。当您从多重采样纹理中获取时,您必须在着色器中使用 texelFetch (...) 这样做,这会绕过所有采样器状态。
    • 已更改,现在出现 GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 错误?
    • 是的,现在您遇到了GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 的另一个原因:如果所有附加纹理的GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 的值不同,"GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 也会返回;或者,如果附加的图像是渲染缓冲区和纹理的混合,则GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 的值不是 GL_TRUE 对于所有附加的纹理"。当您调用glTexImage2DMultisample (...) 时,您需要使用GL_TRUE 而不是GL_FALSE ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-12
    • 2018-03-11
    • 1970-01-01
    • 2011-05-03
    • 2019-01-14
    • 2016-05-01
    相关资源
    最近更新 更多