OpenGL - 如何绘制到多采样帧缓冲区,然后将结果用作普通纹理?
OpenGL - How to draw to a multisample framebuffer and then use the result as a normal texture?
我正在开发一个小游戏开发库。该库的元素之一是 Canvas(屏幕外绘图区域),它是通过 OpenGL 帧缓冲区实现的。到目前为止,一切都很好,我生成了一个纹理,将其附加到帧缓冲区,对其进行渲染,然后将帧缓冲区的纹理用作 Texture2D。
现在,我想在我的库中添加抗锯齿功能,因此我希望能够在 Canvas 上设置多重采样。现在我很困惑,因为我发现您需要更改着色器才能使用多重采样纹理等等。
那么,我应该怎么做才能为我的帧缓冲区启用多重采样,以便最大限度地减少对库的其余代码的更改?如果可能的话,我只想将渲染结果用作常规 Texture2D。
只是为了确保没有混淆。您不能只创建一个大 x 倍的纹理,然后希望过滤器能够发挥作用。因为GL_LINEAR
,等只有averages the four texels closest to the center of the pixel being textured.
要创建多重采样纹理,您将使用 glTexImage2DMultisample()
(自 3.2 起在核心中可用)。你会像这样设置它。
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA8, width, height, false);
它应该是不言自明的,因为 samples
是多重采样纹理中的采样数量。还请根据需要更改 internalformat
。
要将纹理附加到帧缓冲区,您同样可以使用 glFramebufferTexture2D()
。但不是将 textarget
设置为 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);
在一天结束的时候,如果你想显示清晰的抗锯齿结果,你必须将它 blit 到屏幕上。
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 问题。
我正在开发一个小游戏开发库。该库的元素之一是 Canvas(屏幕外绘图区域),它是通过 OpenGL 帧缓冲区实现的。到目前为止,一切都很好,我生成了一个纹理,将其附加到帧缓冲区,对其进行渲染,然后将帧缓冲区的纹理用作 Texture2D。
现在,我想在我的库中添加抗锯齿功能,因此我希望能够在 Canvas 上设置多重采样。现在我很困惑,因为我发现您需要更改着色器才能使用多重采样纹理等等。
那么,我应该怎么做才能为我的帧缓冲区启用多重采样,以便最大限度地减少对库的其余代码的更改?如果可能的话,我只想将渲染结果用作常规 Texture2D。
只是为了确保没有混淆。您不能只创建一个大 x 倍的纹理,然后希望过滤器能够发挥作用。因为GL_LINEAR
,等只有averages the four texels closest to the center of the pixel being textured.
要创建多重采样纹理,您将使用 glTexImage2DMultisample()
(自 3.2 起在核心中可用)。你会像这样设置它。
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA8, width, height, false);
它应该是不言自明的,因为 samples
是多重采样纹理中的采样数量。还请根据需要更改 internalformat
。
要将纹理附加到帧缓冲区,您同样可以使用 glFramebufferTexture2D()
。但不是将 textarget
设置为 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);
在一天结束的时候,如果你想显示清晰的抗锯齿结果,你必须将它 blit 到屏幕上。
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 问题。