opengl - 无法使用多重采样渲染到纹理

标签 opengl graphics textures framebuffer

我在 this 中运行了帧缓冲区示例页 - original code -(在 osx 10.8 中的 xcode 4.6 中使用 glfw3 和 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();
}
  • gl版本:3.2 NVIDIA-8.10.44 304.10.65f03
  • glRenderer:NVIDIA GeForce 9400M OpenGL 引擎

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

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

最佳答案

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

如果一个附件的样本数量与其他任何附件的样本数量不同,核心和 EXT FBO 扩展都会将帧缓冲区视为多样本不完整附件。在您的情况下,您有一个包含 4 样本的颜色缓冲区附件和一个包含 1 样本的深度/模板附件。

Name

glCheckFramebufferStatus — check the completeness status of a framebuffer

描述

glCheckFramebufferStatus queries the completeness status of the framebuffer object currently bound to target. target must be GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER. GL_FRAMEBUFFER is equivalent to GL_DRAW_FRAMEBUFFER.

The return value is GL_FRAMEBUFFER_COMPLETE if the framebuffer bound to target is complete. Otherwise, the return value is determined as follows:

[...]

GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE is returned if the value of GL_RENDERBUFFER_SAMPLES is not the same for all attached renderbuffers; if the value of GL_TEXTURE_SAMPLES is the not same for all attached textures; or, if the attached images are a mix of renderbuffers and textures, the value of GL_RENDERBUFFER_SAMPLES does not match the value of GL_TEXTURE_SAMPLES.


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

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

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

关于opengl - 无法使用多重采样渲染到纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24072447/

相关文章:

OpenGL渐变 "banding"工件

c++ - 使用 ASSIMP 进行骨骼动画

java - 球离开屏幕

opengl - 如何在 OpenGL 3.2 中使用 GL_TEXTURE_2D_ARRAY

c++ - openGL光照随相机旋转

c++ - 在 GLSL 中优化光线追踪着色器

python中点线裁剪算法

python - 需要帮助实现洪水填充算法

opengl topdown<->bottomup 纹理?

ios - iPad2 复制 1K 图像需要 0.5 秒——这是我能做的最好的吗?