Unity Anti-aliasing shader (SDF)

分享下最近通过论文研究基于SDF的Anti-aliasing。
  • 什么是SDF?

    SDF=signed distance field,其实就是判断一个点是否在区域内。 (通过signed distance function)

  • Signed Distance Field=distance(target,targetNearestForeground)-distance(target,targetNearestBackground)
    SDF只做介绍,详细可以Google。

shader SDFAnti-aliasing原理(参考于https://www.zhihu.com/question/267382412/answer/338371372):

  • 利用的是 uv值做的SDF,多边形中心点,uv值为(0,0),边上的点uv值为(1,0)。这时候,从中心到边缘,uv的x值边缘为1,非边缘在0~1之间。这时候只要利用 uv.x在x和y方向上的偏导数来取出 几个像素做下边缘alpha模糊即可。

首先在构建mesh uv的时候,uv是从本身中心点(0,0)到各边缘(1,0)。(也就是此shader的适用范围,需要使用到可以让美术,或者自己修改uv值)
如下图:


Unity Anti-aliasing shader (SDF)_第1张图片
image.png

shader 实现:Alpha Blend+Smoothstep实现半透明渐变

image.png
  • 计算当前像素点在x,y方向上的偏导值,其值等于临近像素上的变化率,因为纹理坐标的梯度可以用来确定纹理当前被缩放的程度,作为需要渐变像素的offset(DX11 上,fwidth())。

原理:


Unity Anti-aliasing shader (SDF)_第2张图片
image.png
  • ddx=p(x+1,y)-p(x,y) p点像素与它x方向上相邻像素颜色的差。
  • ddy=p(x+1,y)-p(x,y) p点像素与它y方向上相邻像素颜色的差。
  • delta=|ddx|+|ddy|

由于uv coordinate [0,1] rgba 也是[0,1]。 则所求的delta是以uv coordinate内与目标有颜色差异的单个像素的宽度(从颜色到uv的mapping过程)。 而_Delta则是需要参与计算的像素个数(uv变化是线性的,所以每个像素之间的差异都是一样的)。

简单的偏移计算 : float u = i.uv.x+delta
y=x+a;
x=y-a;


Unity Anti-aliasing shader (SDF)_第3张图片
image.png

i.uv.x=u-delta (在i.uv.x位置时,距离u点的delta距离内的范围)
(也就是当u为1时,i.uv.x等于为1-delta)

所求范围的像素,需要进行接下来的alpha 渐变。

接着通过smoothstep实现非线性的渐变递增。(alpha渐变)

image.png
  • 从uv coordinate 的[1-delta,1]区间向[0,1]区间的线性映射(用于插值计算)。
Unity Anti-aliasing shader (SDF)_第4张图片
image.png

原理:线性插值


Unity Anti-aliasing shader (SDF)_第5张图片
image.png

“(u-1)/delta ” 线性映射(方便插值运算,插值一般都是0-1):

目的为了将由上图的 [1-delta,1]的区间映射到[0,1]的区间用于插值运算。

公式变换:
Unity Anti-aliasing shader (SDF)_第6张图片
image.png

则:
由于:u=i.uv.x+delta则:

线性映射为:(u-1)/delta
通过 (u-1)/delta 完成线性映射:


Unity Anti-aliasing shader (SDF)_第7张图片
image.png
最后进行smoothstep插值计算(非线性的渐变):
  • smoothstep 函数将用于在一段时间范围内逐渐但非线性地增加属性,例如,“不透明度”(Opacity)从 0 增加到 1。
Unity Anti-aliasing shader (SDF)_第8张图片
image.png
  • a=smoothstep(a,0.0f,smoothValue)
  • 由于我们是向0插值,则函数曲线大概是这样(随便画的):


    Unity Anti-aliasing shader (SDF)_第9张图片
    image.png
Smoothstep函数原型:
Unity Anti-aliasing shader (SDF)_第10张图片
image.png

最终效果:

  • 抗锯齿前:


    Unity Anti-aliasing shader (SDF)_第11张图片
    image.png
  • 抗锯齿后:


    Unity Anti-aliasing shader (SDF)_第12张图片
    image.png

相关文献地址:
An introduction to shader derivative functions(fwidth()):
http://www.aclockworkberry.com/shader-derivative-functions/

signed distance function:
https://en.wikipedia.org/wiki/Signed_distance_function

smoothstep:
https://en.wikipedia.org/wiki/Smoothstep

你可能感兴趣的:(Unity Anti-aliasing shader (SDF))