zoukankan      html  css  js  c++  java
  • Filtering Approaches for Real-Time Anti-Aliasing(2011 SIGGRAPH)

    Filtering Approaches for Real-Time Anti-Aliasing(2011 SIGGRAPH)

    image

    在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!

    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

    image

    • 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))
    

    image

    • extra taps
    dir.x = -((NW+NE)-(SW+SE))
    dir.y = ((NW+SW)-(NE+SE))
    dir.xy = normalize(dir.xy) * scale
    

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

    image

    • Optional extra 2 taps
      缩放dir.xy,扩展到8个像素
    minDir = min(|dir.x|, |dir.y|) * sharpness
    

    image

    • 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
    
    

    image

    • 效果展示
      image

    image

    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)

    image

    image

  • 相关阅读:
    反向代理实例
    nginx常用命令和配置
    nginx的安装
    Can Live View boot up images acquired from 64bit OS evidence?
    What is the behavior of lnk files?
    EnCase v7 search hits in compound files?
    How to search compound files
    iOS 8.3 JB ready
    Sunglasses
    现代福尔摩斯
  • 原文地址:https://www.cnblogs.com/SeekHit/p/9010571.html
Copyright © 2011-2022 走看看