|
在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
//--------------------------------------------------------------------------------------
- <p>SamplerState samLinear:register(s0);</p><p>
- </p><p>Texture2D txFxaa:register(t0);</p><p>
- </p><p>struct PS_INPUT</p><p>
- </p><p>{</p><p>
- </p><p>float4 Pos:SV_POSITION;</p><p>
- </p><p>float4 PosProj:POSITION;</p><p>
- </p><p>float3 Norm:NORMAL;</p><p>
- </p><p>float4 Diffuse:COLOR0;</p><p>
- </p><p>float2 Tex:TEXCOORD;</p><p>
- </p><p>float3 Tangent:TANGENT;</p><p>
- </p><p>};</p><p>
- </p><p>float4 FxaaPS(PS_INPUT input):SV_Target</p><p>
- </p><p>{</p><p>
- </p><p>float4 texColor=txFxaa.Sample(samLinear,input.Tex);</p><p>
- </p><p>//FXAA 3x3取9个像素</p><p>
- </p><p>float3 luma=float3(0.299,0.587,0.114);</p><p>
- </p><p>//luma=float3(0.33,0.33,0.33);</p><p>
- </p><p>float lumaTL=dot(luma,txFxaa.Sample(samLinear,input.Tex.xy+float2(-1.0,-1.0)).xyz);</p><p>
- </p><p>float lumaTR=dot(luma,txFxaa.Sample(samLinear,input.Tex.xy+float2(1.0,-1.0)).xyz);</p><p>
- </p><p>float lumaBL=dot(luma,txFxaa.Sample(samLinear,input.Tex.xy+float2(-1.0,1.0)).xyz);</p><p>
- </p><p>float lumaBR=dot(luma,txFxaa.Sample(samLinear,input.Tex.xy+float2(1.0,1.0)).xyz);</p><p>
- </p><p>float lumaM=dot(luma,txFxaa.Sample(samLinear,input.Tex.xy).xyz);</p><p>
- </p><p>float2 dir;</p><p>
- </p><p>dir.x=-((lumaTL+lumaTR)-(lumaBL+lumaBR));</p><p>
- </p><p>dir.y=(lumaTL+lumaBL)-(lumaTR+lumaBR);</p><p>
- </p><p>float FXAA_SPAN_MAX=8.0;</p><p>
- </p><p>float direReduce=1.0/128.0;</p><p>
- </p><p>float inverseDir=1.0/(min(abs(dir.x),abs(dir.y))+direReduce);</p><p>
- </p><p>dir=min(float2(FXAA_SPAN_MAX,FXAA_SPAN_MAX),</p><p>
- </p><p>max(float2(-FXAA_SPAN_MAX,-FXAA_SPAN_MAX),dir*inverseDir));</p><p>
- </p><p>float3 res1=(1.0/2.0)*(</p><p>
- </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>
- </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>
- </p><p>float3 res2=res1*(1.0/2.0)+(1.0/4.0)*(</p><p>
- </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>
- </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>
- </p><p>float lumaRes=dot(luma,res2);</p><p>
- </p><p>float lumaMin=min(lumaM,min(min(lumaTL,lumaTR),min(lumaBL,lumaBR)));</p><p>
- </p><p>float lumaMax=max(lumaM,max(max(lumaTL,lumaTR),max(lumaBL,lumaBR)));</p><p>
- </p><p>if(lumaRes<lumaMin||lumaRes>lumaMax)</p><p>
- </p><p>texColor=float4(res2,1.0);</p><p>
- </p><p>else</p><p>
- </p><p>texColor=float4(res1,1.0);</p><p>
- </p><p>return texColor;</p><p>
- </p><p>}</p><p></p>
复制代码
•效果对比(左为无FXAA)
作者:司虎虎
专栏地址:https://zhuanlan.zhihu.com/p/36603489
|
|