无法通过多重采样渲染到纹理 [英] Cannot render to texture with multisampling
问题描述
我在此页-
可能没有必要添加'EXT',但是我也尝试了在没有它们的情况下运行,结果是相同的.我在做什么错了? 现在绑定 如果您检查了帧缓冲区对象的完整性,那么您现在可能已经抓住了这一点...您的深度/模板缓冲区也需要进行多重采样. /p>
如果一个附件的样本数量与其他附件不同,则核心和EXT FBO扩展均将帧缓冲区视为 多样本不完整 依恋.就您而言,您有一个带有 4 个样本的颜色缓冲区附件和一个带有 1 个样本的深度/模板附件.
GL_TEXTURE_2D_MULTISAMPLE
并出现GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
错误!
名称
glCheckFramebufferStatus
—检查帧缓冲区的完整性状态
说明
glCheckFramebufferStatus
查询当前绑定到target
的帧缓冲区对象的完整性状态.target
必须为GL_DRAW_FRAMEBUFFER
,GL_READ_FRAMEBUFFER
或GL_FRAMEBUFFER
.GL_FRAMEBUFFER
等同于GL_DRAW_FRAMEBUFFER
.如果绑定到目标的帧缓冲区已完成,则返回值为
GL_FRAMEBUFFER_COMPLETE
.否则,返回值确定如下:[...]
如果所有附加的渲染缓冲区的GL_RENDERBUFFER_SAMPLES
值都不相同,则返回
GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
;否则,将返回
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
)具有更严格的行为(例如,要求每个附件具有相同的图像尺寸). /em>
I ran the framebuffers example in this page -original code- (using glfw3 and glew in xcode 4.6 in osx 10.8), it worked fine, then I wanted to add multisampling (to avoid jagged edges on cube edges and on the floor, glfwWindowHint (GLFW_SAMPLES, 4)
was enough when rendering directly to the back-buffer), found some answers directing to opengl.org, tried to use glTexImage2DMultisample
but it displayed nothing (black screen). The framebuffer settings and rendering loop is:
// 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 Engine
The 'EXT' additions are probably unnecessary but I also tried to run without them before and the result was the same. What am I doing wrong?
EDIT: Now binding GL_TEXTURE_2D_MULTISAMPLE
and getting GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
error!
If you checked your framebuffer object for completeness, you would probably have caught this by now... your depth/stencil buffer needs to be multisampled as well.
A framebuffer is considered multisample incomplete by both core and the EXT FBO extension if one attachment has a different number of samples than any other attachment. In your case, you have a color buffer attachment with 4 samples and a depth/stencil attachment with 1 sample.
Name
glCheckFramebufferStatus
— check the completeness status of a framebuffer
Description
glCheckFramebufferStatus
queries the completeness status of the framebuffer object currently bound totarget
.target
must beGL_DRAW_FRAMEBUFFER
,GL_READ_FRAMEBUFFER
orGL_FRAMEBUFFER
.GL_FRAMEBUFFER
is equivalent toGL_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 ofGL_RENDERBUFFER_SAMPLES
is not the same for all attached renderbuffers; if the value ofGL_TEXTURE_SAMPLES
is the not same for all attached textures; or, if the attached images are a mix of renderbuffers and textures, the value ofGL_RENDERBUFFER_SAMPLES
does not match the value ofGL_TEXTURE_SAMPLES
.
To fix this, you need to allocate a multisampled depth/stencil attachment with 4 samples:
glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
By the way, since your implementation is >= 3.0, you do not need the EXT suffix on anything. All of the constants defined by the EXT extension are identical to ARB / core FBOs, but some of the EXT functions (such as glCheckFramebufferStatusEXT
) have more restrictive behavior (requiring each attachment to have the same image dimensions, for instance).
这篇关于无法通过多重采样渲染到纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!