在图形学渲染中,由于采样频率不足会导致信号失真的问题。其中有两类问题比较常见:
- 由于纹理尺寸过小而导致的失真问题
- 由于纹理尺寸过大而导致的失真问题
上面的过大和过小都是和我们的视口相比较而言的。也就是最终我们绘制到屏幕上或者缓冲区对应的大小。
其中第一种问题的解决方案可以参照图形学抗锯齿:插值法(一)
这篇文章
这里介绍的是应用解决上述第二种:由于纹理尺寸过大(绘制的分辨率而言)而导致的锯齿问题。
纹理尺寸过大产生锯齿的原因
当纹理尺寸较绘制目标的分辨率尺寸要大时,目标上某个像素点在采样时将整个像素区域直接用纹理上对应的值代替。因为目标分辨率相对较小,导致每个像素之间的最终像素值无法平滑过渡。所以该种情况产生锯齿的原因是因为采样频率不足。在纹理上的某个区域内(包含了比较多的纹理像素),只采样一个值。在绘制目标的体现相当于用该值代替原先纹理对应的整个区域。
多重采样
既然知道了锯齿产生原因是因为采样不足导致,那么我们的一种解决方法就是多重采样。只要我们提高采样频率,那么原信号的失真率就小了。
下面我们做个实验来看下多重采样的效果。实验步骤是通过多重采样将一幅原图绘制到比原图小的目标缓冲上,最后将该目标图绘制回同样尺寸的图,对比效果。
现在我们要把原图绘制到比原图小的目标缓冲区上()。期间,我们应用多重采样的方法来计算得到每个目标像素的像素值。代码如下:
uniform sampler2D inputTexture0;
uniform vec2 material_size;
varying vec2 v_texCoord;
const int sampler_points = 3;
float offset = 1.0 / float(sampler_points);
void main()
{
vec2 st = v_texCoord * material_size;
vec2 f_co = fract(st);
vec2 i_co = (st - f_co);
vec2 co_ori = i_co / material_size;
vec3 res_color = vec3(0.0);
float sum = 0.0;
for (int j = 0; j < sampler_points; j++){
for (int i = 0; i < sampler_points; i++){
sum += 1.0;
res_color += texture2D(inputTexture0, co_ori + offset * vec2(float(i), float(j))/material_size).rgb;
}
}
gl_FragColor = vec4(res_color/sum, 1.0);
}
上面采取了采样了9个点求平均的方法。
最终再将该图绘制回原图尺寸。结果图如下:
多重采样结果图
对比下直接压缩到后并绘制回原来尺寸的结果图:
网友评论