Unity渲染教程——实时抗锯齿滤波

作者:司虎虎 2019-03-11

在2011的SIGGRAPH上,NVIDA提出了FXAA3.1,本文主要介绍FXAA实现思路,提供部分简单实现的代码。

1.What is FXAA 3.11

•Fast approXimate Anti-Aliasing

•Two algorithms

-FXAA 3.11 Console(360 and PS3)

-FXAA 3.11 Quality(PC)

•Fixed set of constraints

o One shader pass,only color input,only color output

o Run on all APIs(GL,DX9,through DX11,etc)

o Certainly better can be done under other constraints!

FXAA全称“Fast Approximate Anti-Aliasing”,翻译成中文就是“快速近似抗锯齿”。

FXAA3.11在之前FXAA1,2的基础上做了一些改进。

•FXAA1:最早最基础的版本,也是在PC游戏中使用最广泛的,已用于《孤岛危机2》、《无主之地》。

•FXAA2:针对Xbox 360游戏机专门设计。

•FXAA3:Quality质量版本面向PC,Console主机版本则面向Xbox 360、PS3。

FXAA是一种单程像素着色器,和MLAA一样运行于目标游戏渲染管线的后期处理阶段,但不像后者那样使用DirectCompute,而只是单纯的后期处理着色器,不依赖于任何GPU计算API。正因为如此,FXAA技术对显卡没有特殊要求,完全兼容NVIDIA、AMD的不同显卡(MLAA仅支持A卡)和DX9、DX10、DX11。

2.How FXAA Working


•Early exit for pixels

取4个方向以及中间像素,对5个位置的值做滤波操作,对于范围之外进行分段线性变换。对于差异较大的像素,进行AA。

maxLuma=max(nw,ne,sw,se)

contrast=max(nw,ne,sw,se,m)-min(nw,ne,sw,se,m)

if(contrast>=max(minThreshold,maxLuma*threshold))


•extra taps

dir.x=-((NW+NE)-(SW+SE))

dir.y=((NW+SW)-(NE+SE))

dir.xy=normalize(dir.xy)*scale

使用2x2的区域,计算像素边界,做向量运算。得到dir之后归一化长度。


•Optional extra 2 taps

缩放dir.xy,扩展到8个像素

minDir=min(|dir.x|,|dir.y|)*sharpness


•Compare 4-tap filter luma to neighborhood luma

比较4个方向的luma和相邻luma的值。

//Use the min and max luma range of the original 4 samples

*{NW,NE,SW,SE}

//If 4-tap filter luma exceeds this range,

*Assume invalid and use just the first 2 taps


•效果展示



3.简单实现

我自己再Direct11的环境下,参考FXAA思路,实现了简单版本的FXAA,相比自带d3d实现的4xMSAA,效果较为不明显,仅供交流学习。

//--------------------------------------------------------------------------------------

//File:FXAA.fx

//--------------------------------------------------------------------------------------

  1. <p>SamplerState samLinear:register(s0);</p><p>
  2. </p><p>Texture2D txFxaa:register(t0);</p><p>
  3. </p><p>struct PS_INPUT</p><p>
  4. </p><p>{</p><p>
  5. </p><p>float4 Pos:SV_POSITION;</p><p>
  6. </p><p>float4 PosProj:POSITION;</p><p>
  7. </p><p>float3 Norm:NORMAL;</p><p>
  8. </p><p>float4 Diffuse:COLOR0;</p><p>
  9. </p><p>float2 Tex:TEXCOORD;</p><p>
  10. </p><p>float3 Tangent:TANGENT;</p><p>
  11. </p><p>};</p><p>
  12. </p><p>float4 FxaaPS(PS_INPUT input):SV_Target</p><p>
  13. </p><p>{</p><p>
  14. </p><p>float4 texColor=txFxaa.Sample(samLinear,input.Tex);</p><p>
  15. </p><p>//FXAA 3x3取9个像素</p><p>
  16. </p><p>float3 luma=float3(0.299,0.587,0.114);</p><p>
  17. </p><p>//luma=float3(0.33,0.33,0.33);</p><p>
  18. </p><p>float lumaTL=dot(luma,txFxaa.Sample(samLinear,input.Tex.xy+float2(-1.0,-1.0)).xyz);</p><p>
  19. </p><p>float lumaTR=dot(luma,txFxaa.Sample(samLinear,input.Tex.xy+float2(1.0,-1.0)).xyz);</p><p>
  20. </p><p>float lumaBL=dot(luma,txFxaa.Sample(samLinear,input.Tex.xy+float2(-1.0,1.0)).xyz);</p><p>
  21. </p><p>float lumaBR=dot(luma,txFxaa.Sample(samLinear,input.Tex.xy+float2(1.0,1.0)).xyz);</p><p>
  22. </p><p>float lumaM=dot(luma,txFxaa.Sample(samLinear,input.Tex.xy).xyz);</p><p>
  23. </p><p>float2 dir;</p><p>
  24. </p><p>dir.x=-((lumaTL+lumaTR)-(lumaBL+lumaBR));</p><p>
  25. </p><p>dir.y=(lumaTL+lumaBL)-(lumaTR+lumaBR);</p><p>
  26. </p><p>float FXAA_SPAN_MAX=8.0;</p><p>
  27. </p><p>float direReduce=1.0/128.0;</p><p>
  28. </p><p>float inverseDir=1.0/(min(abs(dir.x),abs(dir.y))+direReduce);</p><p>
  29. </p><p>dir=min(float2(FXAA_SPAN_MAX,FXAA_SPAN_MAX),</p><p>
  30. </p><p>max(float2(-FXAA_SPAN_MAX,-FXAA_SPAN_MAX),dir*inverseDir));</p><p>
  31. </p><p>float3 res1=(1.0/2.0)*(</p><p>
  32. </p><p>txFxaa.Sample(samLinear,input.Tex.xy+(dir*float2(1.0/3.0-0.5,1.0/3.0-0.5))).xyz+</p><p>
  33. </p><p>txFxaa.Sample(samLinear,input.Tex.xy+(dir*float2(2.0/3.0-0.5,2.0/3.0-0.5))).xyz);</p><p>
  34. </p><p>float3 res2=res1*(1.0/2.0)+(1.0/4.0)*(</p><p>
  35. </p><p>txFxaa.Sample(samLinear,input.Tex.xy+(dir*float2(0.0/3.0-0.5,0.0/3.0-0.5))).xyz+</p><p>
  36. </p><p>txFxaa.Sample(samLinear,input.Tex.xy+(dir*float2(3.0/3.0-0.5,3.0/3.0-0.5))).xyz);</p><p>
  37. </p><p>float lumaRes=dot(luma,res2);</p><p>
  38. </p><p>float lumaMin=min(lumaM,min(min(lumaTL,lumaTR),min(lumaBL,lumaBR)));</p><p>
  39. </p><p>float lumaMax=max(lumaM,max(max(lumaTL,lumaTR),max(lumaBL,lumaBR)));</p><p>
  40. </p><p>if(lumaRes&lt;lumaMin||lumaRes&gt;lumaMax)</p><p>
  41. </p><p>texColor=float4(res2,1.0);</p><p>
  42. </p><p>else</p><p>
  43. </p><p>texColor=float4(res1,1.0);</p><p>
  44. </p><p>return texColor;</p><p>
  45. </p><p>}</p><p></p>
复制代码

•效果对比(左为无FXAA)



作者:司虎虎
专栏地址:https://zhuanlan.zhihu.com/p/36603489

最新评论
暂无评论
参与评论

商务合作 查看更多

编辑推荐 查看更多