只是为了确保没有混乱。您不能只创建一个大 x 倍的纹理,然后希望滤镜能够发挥魔力。因为GL_LINEAR
等仅平均最接近纹理像素中心的四个纹理像素.
要创建多重采样纹理,您可以使用glTexImage2DMultisample()(从 3.2 开始在核心中可用)。你可以这样设置。
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA8, width, height, false);
它应该是不言自明的samples
是多样本纹理中的样本数量。还要更改internalformat
如你所愿。
要将纹理附加到帧缓冲区,您同样可以使用glFramebufferTexture2D()。但不是设置textarget
as GL_TEXTURE_2D
你把它设置为GL_TEXTURE_2D_MULTISAMPLE
.
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
请记住检查帧缓冲区的状态。
在你的着色器中你还必须使用sampler2DMS
能够访问多重采样纹理。但请注意,与常规纹理相比,多重采样纹理的工作方式完全不同。如果你想从纹理中读取,你必须使用texelFetch().
因此,如果您想从多重采样纹理中采样,那么您不能使用texture()但必须利用texelFetch()与类似的东西。
uniform int texSamples;
uniform sampler2DMS tex;
vec4 textureMultisample(sampler2DMS sampler, ivec2 coord)
{
vec4 color = vec4(0.0);
for (int i = 0; i < texSamples; i++)
color += texelFetch(sampler, coord, i);
color /= float(texSamples);
return color;
}
注意texelFetch()不采用标准化坐标,您可以使用以下方法来规避此问题:
vec2 uv = vec2(0.5, 0.5); // normalized coordinates
ivec2 texSize = textureSize(tex, 0);
ivec2 texCoord = ivec2(uv * texSize);
vec4 color = textureMultisample(tex, texCoord);
最终,如果您想显示清晰的抗锯齿结果,则必须将其传输到屏幕上。
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glDrawBuffer(GL_BACK);
glBlitFramebuffer(0, 0, src_width, src_height, 0, 0, dst_width, dst_height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
如果您需要多重采样深度缓冲区,请查看glRenderbufferStorageMultisample().
还要确保glEnable(GL_MULTISAMPLE)
。然而,如今大多数驱动程序默认启用它。
最后但并非最不重要的一点是,这里还有一些您可能会感兴趣的与多重采样相关的其他 Stack Overflow/Exchange 问题。
- 过滤
- texelFetch() vs texture()
- 多重采样窗口缓冲区