【ShaderToy】基础篇之再谈抗锯齿(antialiasing,AA)

写在前面在之前的基础篇中,我们讲到了在绘制点线时如何处理边缘的锯齿,也就是使用smoothstep函数。而模糊参数是一些定值,或者是跟屏幕分辨率相关的数值,例如分辨率宽度的5%等等。但这种方法其实是有一种问题的。这需要我们从绘制的图像说起。ShaderToy中绘制的很多图像可以说是一种Procedure Texture,过程纹理,即是计算机生成的纹理。拿之前画的圆和线来说,这些圆和线的绘制过程,是
摘要由CSDN通过智能技术生成


写在前面


在之前的基础篇中,我们讲到了在绘制点线时如何处理边缘的锯齿,也就是使用smoothstep函数。而模糊参数是一些定值,或者是跟屏幕分辨率相关的数值,例如分辨率宽度的5%等等。但这种方法其实是有一种问题的。这需要我们从绘制的图像说起。


ShaderToy中绘制的很多图像可以说是一种Procedure Texture,过程纹理,即是计算机生成的纹理。拿之前画的圆和线来说,这些圆和线的绘制过程,是我们计算每个fragment到“期望图像”的距离,然后根据距离来判断使用哪种颜色。如果这个距离是在欧式空间,即圆和线的例子中那样,那么直接使用定制或者和屏幕系数相关的值作为模糊参数是没有问题的。但一旦这个距离无法用欧氏距离来表示(有很多这样的情况,例如判断到一条正弦曲线的距离,就无法使用点到直线的距离这样简单的公式了),使用这种参数是无法得到很好的模糊效果的。在ShaderToy中,很多处理方法其实就是在进行图片处理工作。


这种时候,我们就可以利用另一个函数fwidth,和smoothstep等函数合作来达到抗锯齿的目的,而这种方法实际上更加通用。这里还将介绍一种新的函数clamp


本篇涉及到的原ShaderToy中的例子主要有:

https://www.shadertoy.com/view/4ssSRl

https://www.shadertoy.com/view/ldsSRX

https://www.shadertoy.com/view/ldlSzS

https://www.shadertoy.com/view/MsjSzy


我编写的效果如下:

https://www.shadertoy.com/view/XtB3zw

https://www.shadertoy.com/view/4tB3zm

https://www.shadertoy.com/view/4t2GRm


以及GPU Gems的一篇文章:

http://http.developer.nvidia.com/GPUGems/gpugems_ch24.html



纹理采样的抗锯齿


我们一定听说过抗锯齿这件事情,而不出意外的话,我们肯定也听说过多重采样这个抗锯齿途径。多重采样简单来说就是像素点的颜色是和其相邻的一些像素值有关的。我们把多重采样再一般化,实际上是是一个对图像求卷积的过程。输入图像A,经过某个定义的kernel进行卷积处理后,得到B,我们希望B中的锯齿尽可能少。很多GPU已经提供了一些快速的滤波操作,例如线性滤波等等。多重采样使用的kernel往往是一个长方形,每个点对应的权重是一样的,然后对原图像进行卷积,就可以输出抗锯齿后的图像B了。但是如果我们想要进行更复杂的滤波,就需要自定义kernel。当然,kernel的用处不仅仅是抗锯齿,还可以进行边界检测等等,我后面的文章可能会讲到。这里,我们仅讨论用于抗锯齿的kernel。


举个例子,我们要渲染一个有纹理的长方形,当知道了该像素对应的纹理UV坐标后,如果我们直接利用texture2D访问纹理,那么最终在长方形的边界就会出现明显锯齿。而如果我们利用多重采样的思想,就会在每次计算时,不仅仅对该像素对应的UV进行采样,还会调用多次texture2D函数,最后将结果相加取平均值。


常见的抗锯齿kernel有Box、Cubic等等。更多内容可以参考上面的GPU Gems中的文章。


复杂的滤波操作大都只依赖于,“我们应该对图像滤波多少(也可以理解成模糊多大的范围)”。很容易理解,例如在如果相邻像素的UV值是一样的,那么我们就不需要采样啦,也就是说,这时可以不进行滤波。而现代很多GPU提供了偏导数函数给我们,在GLSL中,这个函数就是fwidth。当调用这个函数时,我们相当于问GPU:“嘿伙计,我想知道,参数这个值在屏幕的横纵方向的像素之间变化了多少?”fwidth函数返回的是X和Y方向偏导数的绝对值的和,而单方向的偏导可以通过ddx

  • 23
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值