我有一个800x600的窗口,我想对渲染图像应用一些卷积(即高斯模糊)。
首先,我将场景渲染为1024x1024 float16纹理,其中包含800x600视口和剪刀框。因此,视口外的区域包含垃圾,它在我的机器上看起来像随机颜色。当我使用像这样的片段着色器将此纹理渲染到窗口时:
uniform sampler2D tex;
out vec4 outFragColor;
smooth in vec2 texCoord;
const float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
void main()
{
vec3 color = texture(tex, texCoord).rgb * weight[0];
vec2 texOffset = 1.0f / textureSize(tex, 0);
for (int i = 1; i < 5; ++i) {
color += texture(tex, texCoord + vec2(texOffset.x * i, 0.0f)).rgb * weight[i];
color += texture(tex, texCoord - vec2(texOffset.x * i, 0.0f)).rgb * weight[i];
}
outFragColor = vec4(color, 1.0f);
}
我显然在视口新窗口边界外采样并将垃圾混合到最终图像中。例如,在这里我们看到顶部的随机值和右边的零值:
我考虑过哪些解决方案:
1)使用纹理大小的视口渲染并仅显示子图像。一个坏主意,因为片段着色器会做很多无用的工作。
2)使用稍大的视口,即810x610。看起来像一个疯狂的黑客。
3)使用非幂二纹理扩展。据我所知,他们有一个微妙的性能损失,更糟糕的是,他们缺乏适当的驱动程序支持,可能是特定于供应商。特别是关于float16纹理(对项目至关重要)和WebGL。
那么在没有在视口外采样的情况下,将帧缓冲图像与内核进行卷积的最佳方法是什么?