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

Opengl 无法使用多重采样渲染到纹理,opengl,graphics,textures,framebuffer,Opengl,Graphics,Textures,Framebuffer,我运行了页面中的帧缓冲区示例——(在osx 10.8的xcode 4.6中使用glfw3和glew),效果很好,然后我想添加多重采样(为了避免立方体边缘和地板上的锯齿状边缘,glfwWindowHint(GLFW_SAMPLES,4)在直接渲染到后缓冲区时就足够了),找到了一些指向opengl.org的答案,尝试使用glTexImage2DMultisample,但未显示任何内容(黑屏)。帧缓冲区设置和渲染循环为: // Create frame buffer GLuint frameBuffe

我运行了页面中的帧缓冲区示例——(在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();
}
  • glVersion:3.2 NVIDIA-8.10.44 304.10.65f03
  • glRenderer:NVIDIA GeForce 9400M OpenGL引擎
“EXT”添加可能是不必要的,但我以前也尝试过在没有它们的情况下运行,结果是一样的。我做错了什么


编辑:现在绑定
GL\u纹理\u 2D\u多样本
并获取
GL\u帧缓冲区\u不完整\u多样本
错误

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

如果一个附件的采样数与任何其他附件的采样数不同,则core和EXT FBO扩展都认为帧缓冲区不完整。在您的示例中,您有一个带有4个样本的颜色缓冲区附件和一个带有1个样本的深度/模具附件

名称 -检查帧缓冲区的完整性状态

描述
glCheckFramebufferStatus
查询当前绑定到
目标的帧缓冲区对象的完整性状态
target
必须是
GL\u DRAW\u FRAMEBUFFER
GL\u READ\u FRAMEBUFFER
GL\u FRAMEBUFFER
GL\u帧缓冲区
相当于
GL\u-DRAW\u帧缓冲区

如果绑定到目标的帧缓冲区已完成,则返回值为
GL\u FRAMEBUFFER\u COMPLETE
。否则,返回值确定如下:

[……]

如果
GL\u RENDERBUFFER\u SAMPLES
GL\u RENDERBUFFER\u SAMPLES的值对于所有附加的renderbuffers不相同,则返回
;如果所有附加纹理的
GL\u纹理\u样本的值不相同;或者,如果附加的图像是渲染缓冲区和纹理的混合,则
GL\u RENDERBUFFER\u SAMPLES
的值与
GL\u TEXTURE\u SAMPLES
的值不匹配


要解决此问题,您需要分配一个包含4个示例的多采样深度/模具附件:
顺便说一句,因为您的实现是=3.0,所以任何东西都不需要EXT后缀。EXT扩展定义的所有常量都与ARB/core FBO相同,但一些EXT函数(如
glCheckFramebufferStatusEXT
)具有更严格的行为(例如,要求每个附件具有相同的图像尺寸)。

我显然错过了它,但我已经在检查了(正确吗?)并且没有得到任何错误!。。不管怎样,我编辑了代码(和问题),但没有任何改变??老实说,我不知道为什么您首先要使用多采样纹理。多采样纹理增加了额外的硬件要求(您的硬件足以支持它们,但您仍然不需要它们)。我将使用多采样渲染缓冲区作为颜色缓冲区,除非您确实希望在着色器中使用多采样颜色缓冲区。无论何种情况,您都应该将
texColorBuffer
绑定到
GL\u TEXTURE\u 2D\u MULTISAMPLE
。同样,您可能会尝试更正
glTexParameteri(GL\u TEXTURE\u 2D,GL\u TEXTURE\u MIN\u FILTER,GL\u LINEAR)要在您使用时应用于
GL\u纹理\u 2D\u多采样
。。。但是不要。在多采样纹理上无法进行纹理过滤。事实上,没有采样器参数适用于多采样纹理,这就是为什么
GL\u TEXTURE\u 2D\u MULTISAMPLE
不是该函数的有效目标。当您从多采样纹理提取时,必须在着色器中使用
texelFetch(…)
,该着色器绕过所有采样器状态。更改了它,现在获得GL\u FRAMEBUFFER\u Complete\u MULTISAMPLE错误?是的,现在您遇到了
GL\u FRAMEBUFFER\u Complete\u MULTISAMPLE
的另一个原因:“
GL\u FRAMEBUFFER\u complete\u MULTISAMPLE
如果所有附加纹理的
GL\u TEXTURE\u FIXED\u SAMPLE\u LOCATIONS
的值不相同,也会返回
;或者,如果附加的图像是渲染缓冲区和纹理的混合体,则
GL_TEXTURE\u FIXED\u SAMPLE\u LOCATIONS
的值对于所有附加的纹理都不是
GL_TRUE
。在调用
glTexImage2DMultisample(…)
时,需要使用
GL_TRUE
而不是
GL_FALSE
glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);