少年辛苦终身事,莫向光阴惰寸功。这篇文章主要讲述Filtering Approaches for Real-Time Anti-Aliasing(2011 SIGGRAPH)相关的知识,希望能为你提供帮助。
Filtering Approaches for Real-Time Anti-Aliasing(2011 SIGGRAPH)
文章图片
在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
- One shader pass, only color input, only color output
- Run on all APIs (GL, DX9, through DX11, etc)
- Certainly better can be done under other constraints!
FXAA3.11在之前FXAA1,2的基础上做了一些改进。
- FXAA1:最早最基础的版本,也是在PC游戏中使用最广泛的,已用于《孤岛危机2》、《无主之地》。
- FXAA2:针对Xbox 360游戏机专门设计。
- FXAA3:Quality质量版本面向PC,Console主机版本则面向Xbox 360、PS3。
2.How FXAA Working
文章图片
- Early exit for pixels
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
//--------------------------------------------------------------------------------------SamplerState samLinear : register(s0);
Texture2D txFxaa : register(t0);
struct PS_INPUT
{
float4 Pos: SV_POSITION;
float4 PosProj: POSITION;
float3 Norm: NORMAL;
float4 Diffuse: COLOR0;
float2 Tex: TEXCOORD;
float3 Tangent: TANGENT;
};
float4 FxaaPS(PS_INPUT input) : SV_Target
{
float4 texColor = txFxaa.Sample(samLinear, input.Tex);
// FXAA 3x3取9个像素
float3 luma = float3(0.299, 0.587, 0.114);
//luma = float3(0.33, 0.33, 0.33);
float lumaTL = dot(luma, txFxaa.Sample(samLinear, input.Tex.xy + float2(-1.0, -1.0)).xyz);
float lumaTR = dot(luma, txFxaa.Sample(samLinear, input.Tex.xy + float2(1.0, -1.0)).xyz);
float lumaBL = dot(luma, txFxaa.Sample(samLinear, input.Tex.xy + float2(-1.0, 1.0)).xyz);
float lumaBR = dot(luma, txFxaa.Sample(samLinear, input.Tex.xy + float2(1.0, 1.0)).xyz);
float lumaM = dot(luma, txFxaa.Sample(samLinear, input.Tex.xy).xyz);
float2 dir;
dir.x = -((lumaTL + lumaTR) - (lumaBL + lumaBR));
dir.y = (lumaTL + lumaBL) - (lumaTR + lumaBR);
float FXAA_SPAN_MAX = 8.0;
float direReduce = 1.0 / 128.0;
float inverseDir = 1.0 / (min(abs(dir.x), abs(dir.y)) + direReduce);
dir = min(float2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
max(float2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir*inverseDir));
float3 res1 = (1.0 / 2.0) * (
txFxaa.Sample(samLinear, input.Tex.xy + (dir * float2(1.0 / 3.0 - 0.5, 1.0 / 3.0 - 0.5))).xyz +
txFxaa.Sample(samLinear, input.Tex.xy + (dir * float2(2.0 / 3.0 - 0.5, 2.0 / 3.0 - 0.5))).xyz);
float3 res2 = res1 * (1.0 / 2.0) + (1.0 / 4.0) * (
txFxaa.Sample(samLinear, input.Tex.xy + (dir * float2(0.0 / 3.0 - 0.5, 0.0 / 3.0 - 0.5))).xyz +
txFxaa.Sample(samLinear, input.Tex.xy + (dir * float2(3.0 / 3.0 - 0.5, 3.0 / 3.0 - 0.5))).xyz);
float lumaRes = dot(luma, res2);
float lumaMin = min(lumaM, min(min(lumaTL, lumaTR), min(lumaBL, lumaBR)));
float lumaMax = max(lumaM, max(max(lumaTL, lumaTR), max(lumaBL, lumaBR)));
if (lumaRes <
lumaMin || lumaRes >
lumaMax)
texColor = float4(res2, 1.0);
else
texColor = float4(res1, 1.0);
return texColor;
}
- 效果对比(左为无FXAA)
文章图片
文章图片
推荐阅读
- bzoj 2100: [Usaco2010 Dec]Apple Deliveryspfa
- Android 验证码倒计时两种方案
- Android font
- Appium升级后安装UnicodeIME-debug.apk 提示
- Android使用adb命令查看CPU信息
- Perl函数和子例程
- Perl do-while循环
- (OK) 编译libiconv-1.14(静态库)—CentOS 7— android-ndk
- (OK—C++程序) Eclipse C/C++ — CentOS 7 + android-ndk + eclipse-cpp-mars-R