如何在OpenGL FBO中使用多重采样

时间:2020-12-02 19:39:30

I'm trying to enable mutlisampling and alpha-to-coverage for an FBO. Using the default framebuffer, all I have to do is call glEnable(GL_MULTISAMPLE) and glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE). However, I am unable to achieve the same effect using my own FBO.

我正在尝试为FBO启用mutlisampling和alpha-to-coverage。使用默认的帧缓冲区,我所要做的就是调用glEnable(GL_MULTISAMPLE)和glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE)。但是,我无法使用自己的FBO达到同样的效果。

My goal: Draw the scene to an FBO the same way it would be drawn to the default framebuffer with the above properties. From there I want to be able to use the image as a texture for future passes through a shader.

我的目标:将场景绘制到FBO,就像使用上述属性绘制到默认帧缓冲区一样。从那里我希望能够将图像用作未来通过着色器的纹理。

This works: Code for making an FBO without multisampling/alpha-to-coverage, 1 color attachment, 1 depth attachment:

这适用:制作没有多重采样/ alpha到覆盖的FBO的代码,1种颜色附件,1种深度附件:

// Generate the color attachment
glGenTextures(1,&defaultColorAttachment0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,defaultColorAttachment0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,screenWidth,screenHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);

// Bind the texture to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, defaultColorAttachment0,0);

// Generate the depth attachment
glGenRenderbuffers(1,&defaultDepthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, defaultDepthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, screenWidth, screenHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, defaultDepthBuffer);

This doesn't work. Code trying to make a multisampled FBO:

这不起作用。试图制作多重采样FBO的代码:

// Generate the color attachment
glGenTextures(1,&defaultColorAttachment0);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, defaultColorAttachment0);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA, screenWidth, screenHeight, GL_FALSE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, defaultColorAttachment0,0);

// Generate the depth attachment
glGenRenderbuffers(1,&defaultDepthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, defaultDepthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, screenWidth, screenHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, defaultDepthBuffer);

I have tried looking through the OpenGL wiki on this, although the it's incomplete (various unfinished headings make it look unprofessional). glGetError never complains. I've tried messing around with this, but I either get a black screen or a screen full of garbage pixels.

我试过通过OpenGL wiki查看,虽然它不完整(各种未完成的标题使它看起来不专业)。 glGetError永远不会抱怨。我试过搞乱这个,但我得到一个黑屏或一个充满垃圾像素的屏幕。

Main Question: What things do I need to consider/change and where (FBO creation, textures, shaders) in order to get multisampling and alpha-to-coverage to work with an FBO?

主要问题:为了使多重采样和alpha-to-coverage与FBO一起工作,我需要考虑/更改哪些内容(FBO创建,纹理,着色器)?

1 个解决方案

#1


22  

You need to allocate a multisampled depth buffer for this to work correctly and give it the same number of samples as your color buffer. In other words, you should be calling glRenderbufferStorageMultisample (...) instead of glRenderbufferStorage (...).

您需要为此分配一个多重采样深度缓冲区才能正常工作,并为其提供与颜色缓冲区相同数量的样本。换句话说,你应该调用glRenderbufferStorageMultisample(...)而不是glRenderbufferStorage(...)。

Your FBO should be failing a completeness check the way it is allocated right now. A call to glCheckFramebufferStatus (...) ought to return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE because your depth buffer has exactly 1 sample and your color buffer attachment has 4.

你的FBO应该没有完整性检查它现在分配的方式。对glCheckFramebufferStatus(...)的调用应该返回GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,因为深度缓冲区只有1个样本,而颜色缓冲区附件有4个。


Since you are also using a multisampled texture attachment in this FBO, you should be aware of differences between sampling a single-sampled texture vs. multisampled in GLSL shaders.

由于您还在此FBO中使用多重采样纹理附件,因此您应该了解在GLSL着色器中采样单采样纹理与多采样之间的差异。

Multisampled textures have a special sampler uniform type (e.g. sampler2DMS) and you have to explicitly fetch each sample in the texture by its integer (non-normalized) texel coordinate and sample index using texelFetch (...). This also means that they cannot be filtered or mip-mapped.

多重采样纹理具有特殊的采样器统一类型(例如sampler2DMS),您必须使用texelFetch(...)通过其整数(非标准化)纹素坐标和样本索引显式获取纹理中的每个样本。这也意味着它们不能被过滤或mip映射。

You probably do not want a multisampled texture in this case, you probably want to use glBlitFramebuffer (...) to do the MSAA resolve into a single-sampled FBO. If you do this instead you can read the anti-aliased results in your shaders rather than having to fetch each sample and implement the anti-aliasing yourself.

在这种情况下,您可能不需要多重采样纹理,您可能希望使用glBlitFramebuffer(...)将MSAA解析为单个采样的FBO。如果您这样做,您可以在着色器中读取消除锯齿的结果,而不必自己获取每个样本并实现抗锯齿。

#1


22  

You need to allocate a multisampled depth buffer for this to work correctly and give it the same number of samples as your color buffer. In other words, you should be calling glRenderbufferStorageMultisample (...) instead of glRenderbufferStorage (...).

您需要为此分配一个多重采样深度缓冲区才能正常工作,并为其提供与颜色缓冲区相同数量的样本。换句话说,你应该调用glRenderbufferStorageMultisample(...)而不是glRenderbufferStorage(...)。

Your FBO should be failing a completeness check the way it is allocated right now. A call to glCheckFramebufferStatus (...) ought to return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE because your depth buffer has exactly 1 sample and your color buffer attachment has 4.

你的FBO应该没有完整性检查它现在分配的方式。对glCheckFramebufferStatus(...)的调用应该返回GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,因为深度缓冲区只有1个样本,而颜色缓冲区附件有4个。


Since you are also using a multisampled texture attachment in this FBO, you should be aware of differences between sampling a single-sampled texture vs. multisampled in GLSL shaders.

由于您还在此FBO中使用多重采样纹理附件,因此您应该了解在GLSL着色器中采样单采样纹理与多采样之间的差异。

Multisampled textures have a special sampler uniform type (e.g. sampler2DMS) and you have to explicitly fetch each sample in the texture by its integer (non-normalized) texel coordinate and sample index using texelFetch (...). This also means that they cannot be filtered or mip-mapped.

多重采样纹理具有特殊的采样器统一类型(例如sampler2DMS),您必须使用texelFetch(...)通过其整数(非标准化)纹素坐标和样本索引显式获取纹理中的每个样本。这也意味着它们不能被过滤或mip映射。

You probably do not want a multisampled texture in this case, you probably want to use glBlitFramebuffer (...) to do the MSAA resolve into a single-sampled FBO. If you do this instead you can read the anti-aliased results in your shaders rather than having to fetch each sample and implement the anti-aliasing yourself.

在这种情况下,您可能不需要多重采样纹理,您可能希望使用glBlitFramebuffer(...)将MSAA解析为单个采样的FBO。如果您这样做,您可以在着色器中读取消除锯齿的结果,而不必自己获取每个样本并实现抗锯齿。