Fxaa.glsl
   1  /*============================================================================
   2  
   3  
   4                      NVIDIA FXAA 3.11 by TIMOTHY LOTTES
   5  
   6  
   7  ------------------------------------------------------------------------------
   8  COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED.
   9  ------------------------------------------------------------------------------
  10  TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
  11  *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
  12  OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
  13  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA
  14  OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR
  15  CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR
  16  LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION,
  17  OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE
  18  THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  19  DAMAGES.
  20  
  21  ------------------------------------------------------------------------------
  22                             INTEGRATION CHECKLIST
  23  ------------------------------------------------------------------------------
  24  (1.)
  25  In the shader source, setup defines for the desired configuration.
  26  When providing multiple shaders (for different presets),
  27  simply setup the defines differently in multiple files.
  28  Example,
  29  
  30    #define FXAA_PC 1
  31    #define FXAA_HLSL_5 1
  32    #define FXAA_QUALITY_PRESET 12
  33  
  34  Or,
  35  
  36    #define FXAA_360 1
  37    
  38  Or,
  39  
  40    #define FXAA_PS3 1
  41    
  42  Etc.
  43  
  44  (2.)
  45  Then include this file,
  46  
  47    #include "Fxaa3_11.h"
  48  
  49  (3.)
  50  Then call the FXAA pixel shader from within your desired shader.
  51  Look at the FXAA Quality FxaaPixelShader() for docs on inputs.
  52  As for FXAA 3.11 all inputs for all shaders are the same 
  53  to enable easy porting between platforms.
  54  
  55    return FxaaPixelShader(...);
  56  
  57  (4.)
  58  Insure pass prior to FXAA outputs RGBL (see next section).
  59  Or use,
  60  
  61    #define FXAA_GREEN_AS_LUMA 1
  62  
  63  (5.)
  64  Setup engine to provide the following constants
  65  which are used in the FxaaPixelShader() inputs,
  66  
  67    FxaaFloat2 fxaaQualityRcpFrame,
  68    FxaaFloat4 fxaaConsoleRcpFrameOpt,
  69    FxaaFloat4 fxaaConsoleRcpFrameOpt2,
  70    FxaaFloat4 fxaaConsole360RcpFrameOpt2,
  71    FxaaFloat fxaaQualitySubpix,
  72    FxaaFloat fxaaQualityEdgeThreshold,
  73    FxaaFloat fxaaQualityEdgeThresholdMin,
  74    FxaaFloat fxaaConsoleEdgeSharpness,
  75    FxaaFloat fxaaConsoleEdgeThreshold,
  76    FxaaFloat fxaaConsoleEdgeThresholdMin,
  77    FxaaFloat4 fxaaConsole360ConstDir
  78  
  79  Look at the FXAA Quality FxaaPixelShader() for docs on inputs.
  80  
  81  (6.)
  82  Have FXAA vertex shader run as a full screen triangle,
  83  and output "pos" and "fxaaConsolePosPos" 
  84  such that inputs in the pixel shader provide,
  85  
  86    // {xy} = center of pixel
  87    FxaaFloat2 pos,
  88  
  89    // {xy_} = upper left of pixel
  90    // {_zw} = lower right of pixel
  91    FxaaFloat4 fxaaConsolePosPos,
  92  
  93  (7.)
  94  Insure the texture sampler(s) used by FXAA are set to bilinear filtering.
  95  
  96  
  97  ------------------------------------------------------------------------------
  98                      INTEGRATION - RGBL AND COLORSPACE
  99  ------------------------------------------------------------------------------
 100  FXAA3 requires RGBL as input unless the following is set, 
 101  
 102    #define FXAA_GREEN_AS_LUMA 1
 103  
 104  In which case the engine uses green in place of luma,
 105  and requires RGB input is in a non-linear colorspace.
 106  
 107  RGB should be LDR (low dynamic range).
 108  Specifically do FXAA after tonemapping.
 109  
 110  RGB data as returned by a texture fetch can be non-linear,
 111  or linear when FXAA_GREEN_AS_LUMA is not set.
 112  Note an "sRGB format" texture counts as linear,
 113  because the result of a texture fetch is linear data.
 114  Regular "RGBA8" textures in the sRGB colorspace are non-linear.
 115  
 116  If FXAA_GREEN_AS_LUMA is not set,
 117  luma must be stored in the alpha channel prior to running FXAA.
 118  This luma should be in a perceptual space (could be gamma 2.0).
 119  Example pass before FXAA where output is gamma 2.0 encoded,
 120  
 121    color.rgb = ToneMap(color.rgb); // linear color output
 122    color.rgb = sqrt(color.rgb);    // gamma 2.0 color output
 123    return color;
 124  
 125  To use FXAA,
 126  
 127    color.rgb = ToneMap(color.rgb);  // linear color output
 128    color.rgb = sqrt(color.rgb);     // gamma 2.0 color output
 129    color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma
 130    return color;
 131  
 132  Another example where output is linear encoded,
 133  say for instance writing to an sRGB formated render target,
 134  where the render target does the conversion back to sRGB after blending,
 135  
 136    color.rgb = ToneMap(color.rgb); // linear color output
 137    return color;
 138  
 139  To use FXAA,
 140  
 141    color.rgb = ToneMap(color.rgb); // linear color output
 142    color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma
 143    return color;
 144  
 145  Getting luma correct is required for the algorithm to work correctly.
 146  
 147  
 148  ------------------------------------------------------------------------------
 149                            BEING LINEARLY CORRECT?
 150  ------------------------------------------------------------------------------
 151  Applying FXAA to a framebuffer with linear RGB color will look worse.
 152  This is very counter intuitive, but happends to be true in this case.
 153  The reason is because dithering artifacts will be more visiable 
 154  in a linear colorspace.
 155  
 156  
 157  ------------------------------------------------------------------------------
 158                               COMPLEX INTEGRATION
 159  ------------------------------------------------------------------------------
 160  Q. What if the engine is blending into RGB before wanting to run FXAA?
 161  
 162  A. In the last opaque pass prior to FXAA,
 163     have the pass write out luma into alpha.
 164     Then blend into RGB only.
 165     FXAA should be able to run ok
 166     assuming the blending pass did not any add aliasing.
 167     This should be the common case for particles and common blending passes.
 168  
 169  A. Or use FXAA_GREEN_AS_LUMA.
 170  
 171  ============================================================================*/
 172  
 173  #version 430 core
 174  
 175  layout(local_size_x = 16, local_size_y = 16) in;
 176  layout(rgba8, binding = 0, set = 3) uniform image2D imgOutput;
 177  
 178  layout(binding = 1, set = 2) uniform sampler2D inputImage;
 179  layout(binding = 2) uniform invResolution
 180  {
 181      vec2 invResolution_data;
 182  };
 183  
 184  #define FXAA_QUALITY_PRESET 12
 185  #define FXAA_GREEN_AS_LUMA 1
 186  #define FXAA_PC 1
 187  #define FXAA_GLSL_130 1
 188  
 189  
 190  /*============================================================================
 191  
 192                               INTEGRATION KNOBS
 193  
 194  /*==========================================================================*/
 195  #ifndef FXAA_PC
 196      //
 197      // FXAA Quality
 198      // The high quality PC algorithm.
 199      //
 200      #define FXAA_PC 0
 201  #endif
 202  /*--------------------------------------------------------------------------*/
 203  #ifndef FXAA_GLSL_120
 204      #define FXAA_GLSL_120 0
 205  #endif
 206  /*--------------------------------------------------------------------------*/
 207  #ifndef FXAA_GLSL_130
 208      #define FXAA_GLSL_130 0
 209  #endif
 210  /*==========================================================================*/
 211  #ifndef FXAA_GREEN_AS_LUMA
 212      //
 213      // For those using non-linear color,
 214      // and either not able to get luma in alpha, or not wanting to,
 215      // this enables FXAA to run using green as a proxy for luma.
 216      // So with this enabled, no need to pack luma in alpha.
 217      //
 218      // This will turn off AA on anything which lacks some amount of green.
 219      // Pure red and blue or combination of only R and B, will get no AA.
 220      //
 221      // Might want to lower the settings for both,
 222      //    fxaaConsoleEdgeThresholdMin
 223      //    fxaaQualityEdgeThresholdMin
 224      // In order to insure AA does not get turned off on colors 
 225      // which contain a minor amount of green.
 226      //
 227      // 1 = On.
 228      // 0 = Off.
 229      //
 230      #define FXAA_GREEN_AS_LUMA 0
 231  #endif
 232  /*--------------------------------------------------------------------------*/
 233  #ifndef FXAA_EARLY_EXIT
 234      //
 235      // Controls algorithm's early exit path.
 236      // On PS3 turning this ON adds 2 cycles to the shader.
 237      // On 360 turning this OFF adds 10ths of a millisecond to the shader.
 238      // Turning this off on console will result in a more blurry image.
 239      // So this defaults to on.
 240      //
 241      // 1 = On.
 242      // 0 = Off.
 243      //
 244      #define FXAA_EARLY_EXIT 1
 245  #endif
 246  /*--------------------------------------------------------------------------*/
 247  #ifndef FXAA_DISCARD
 248      //
 249      // Only valid for PC OpenGL currently.
 250      // Probably will not work when FXAA_GREEN_AS_LUMA = 1.
 251      //
 252      // 1 = Use discard on pixels which don't need AA.
 253      //     For APIs which enable concurrent TEX+ROP from same surface.
 254      // 0 = Return unchanged color on pixels which don't need AA.
 255      //
 256      #define FXAA_DISCARD 0
 257  #endif
 258  /*--------------------------------------------------------------------------*/
 259  #ifndef FXAA_FAST_PIXEL_OFFSET
 260      //
 261      // Used for GLSL 120 only.
 262      //
 263      // 1 = GL API supports fast pixel offsets
 264      // 0 = do not use fast pixel offsets
 265      //
 266      #ifdef GL_EXT_gpu_shader4
 267          #define FXAA_FAST_PIXEL_OFFSET 1
 268      #endif
 269      #ifdef GL_NV_gpu_shader5
 270          #define FXAA_FAST_PIXEL_OFFSET 1
 271      #endif
 272      #ifdef GL_ARB_gpu_shader5
 273          #define FXAA_FAST_PIXEL_OFFSET 1
 274      #endif
 275      #ifndef FXAA_FAST_PIXEL_OFFSET
 276          #define FXAA_FAST_PIXEL_OFFSET 0
 277      #endif
 278  #endif
 279  /*--------------------------------------------------------------------------*/
 280  #ifndef FXAA_GATHER4_ALPHA
 281      //
 282      // 1 = API supports gather4 on alpha channel.
 283      // 0 = API does not support gather4 on alpha channel.
 284      //
 285      #if (FXAA_HLSL_5 == 1)
 286          #define FXAA_GATHER4_ALPHA 1
 287      #endif
 288      #ifdef GL_ARB_gpu_shader5
 289          #define FXAA_GATHER4_ALPHA 1
 290      #endif
 291      #ifdef GL_NV_gpu_shader5
 292          #define FXAA_GATHER4_ALPHA 1
 293      #endif
 294      #ifndef FXAA_GATHER4_ALPHA
 295          #define FXAA_GATHER4_ALPHA 0
 296      #endif
 297  #endif
 298  
 299  /*============================================================================
 300                          FXAA QUALITY - TUNING KNOBS
 301  ------------------------------------------------------------------------------
 302  NOTE the other tuning knobs are now in the shader function inputs!
 303  ============================================================================*/
 304  #ifndef FXAA_QUALITY_PRESET
 305      //
 306      // Choose the quality preset.
 307      // This needs to be compiled into the shader as it effects code.
 308      // Best option to include multiple presets is to 
 309      // in each shader define the preset, then include this file.
 310      // 
 311      // OPTIONS
 312      // -----------------------------------------------------------------------
 313      // 10 to 15 - default medium dither (10=fastest, 15=highest quality)
 314      // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)
 315      // 39       - no dither, very expensive 
 316      //
 317      // NOTES
 318      // -----------------------------------------------------------------------
 319      // 12 = slightly faster then FXAA 3.9 and higher edge quality (default)
 320      // 13 = about same speed as FXAA 3.9 and better than 12
 321      // 23 = closest to FXAA 3.9 visually and performance wise
 322      //  _ = the lowest digit is directly related to performance
 323      // _  = the highest digit is directly related to style
 324      // 
 325      #define FXAA_QUALITY_PRESET 12
 326  #endif
 327  
 328  
 329  /*============================================================================
 330  
 331                             FXAA QUALITY - PRESETS
 332  
 333  ============================================================================*/
 334  
 335  /*============================================================================
 336                       FXAA QUALITY - MEDIUM DITHER PRESETS
 337  ============================================================================*/
 338  #if (FXAA_QUALITY_PRESET == 10)
 339      #define FXAA_QUALITY_PS 3
 340      #define FXAA_QUALITY_P0 1.5
 341      #define FXAA_QUALITY_P1 3.0
 342      #define FXAA_QUALITY_P2 12.0
 343  #endif
 344  /*--------------------------------------------------------------------------*/
 345  #if (FXAA_QUALITY_PRESET == 11)
 346      #define FXAA_QUALITY_PS 4
 347      #define FXAA_QUALITY_P0 1.0
 348      #define FXAA_QUALITY_P1 1.5
 349      #define FXAA_QUALITY_P2 3.0
 350      #define FXAA_QUALITY_P3 12.0
 351  #endif
 352  /*--------------------------------------------------------------------------*/
 353  #if (FXAA_QUALITY_PRESET == 12)
 354      #define FXAA_QUALITY_PS 5
 355      #define FXAA_QUALITY_P0 1.0
 356      #define FXAA_QUALITY_P1 1.5
 357      #define FXAA_QUALITY_P2 2.0
 358      #define FXAA_QUALITY_P3 4.0
 359      #define FXAA_QUALITY_P4 12.0
 360  #endif
 361  /*--------------------------------------------------------------------------*/
 362  #if (FXAA_QUALITY_PRESET == 13)
 363      #define FXAA_QUALITY_PS 6
 364      #define FXAA_QUALITY_P0 1.0
 365      #define FXAA_QUALITY_P1 1.5
 366      #define FXAA_QUALITY_P2 2.0
 367      #define FXAA_QUALITY_P3 2.0
 368      #define FXAA_QUALITY_P4 4.0
 369      #define FXAA_QUALITY_P5 12.0
 370  #endif
 371  /*--------------------------------------------------------------------------*/
 372  #if (FXAA_QUALITY_PRESET == 14)
 373      #define FXAA_QUALITY_PS 7
 374      #define FXAA_QUALITY_P0 1.0
 375      #define FXAA_QUALITY_P1 1.5
 376      #define FXAA_QUALITY_P2 2.0
 377      #define FXAA_QUALITY_P3 2.0
 378      #define FXAA_QUALITY_P4 2.0
 379      #define FXAA_QUALITY_P5 4.0
 380      #define FXAA_QUALITY_P6 12.0
 381  #endif
 382  /*--------------------------------------------------------------------------*/
 383  #if (FXAA_QUALITY_PRESET == 15)
 384      #define FXAA_QUALITY_PS 8
 385      #define FXAA_QUALITY_P0 1.0
 386      #define FXAA_QUALITY_P1 1.5
 387      #define FXAA_QUALITY_P2 2.0
 388      #define FXAA_QUALITY_P3 2.0
 389      #define FXAA_QUALITY_P4 2.0
 390      #define FXAA_QUALITY_P5 2.0
 391      #define FXAA_QUALITY_P6 4.0
 392      #define FXAA_QUALITY_P7 12.0
 393  #endif
 394  
 395  /*============================================================================
 396                       FXAA QUALITY - LOW DITHER PRESETS
 397  ============================================================================*/
 398  #if (FXAA_QUALITY_PRESET == 20)
 399      #define FXAA_QUALITY_PS 3
 400      #define FXAA_QUALITY_P0 1.5
 401      #define FXAA_QUALITY_P1 2.0
 402      #define FXAA_QUALITY_P2 8.0
 403  #endif
 404  /*--------------------------------------------------------------------------*/
 405  #if (FXAA_QUALITY_PRESET == 21)
 406      #define FXAA_QUALITY_PS 4
 407      #define FXAA_QUALITY_P0 1.0
 408      #define FXAA_QUALITY_P1 1.5
 409      #define FXAA_QUALITY_P2 2.0
 410      #define FXAA_QUALITY_P3 8.0
 411  #endif
 412  /*--------------------------------------------------------------------------*/
 413  #if (FXAA_QUALITY_PRESET == 22)
 414      #define FXAA_QUALITY_PS 5
 415      #define FXAA_QUALITY_P0 1.0
 416      #define FXAA_QUALITY_P1 1.5
 417      #define FXAA_QUALITY_P2 2.0
 418      #define FXAA_QUALITY_P3 2.0
 419      #define FXAA_QUALITY_P4 8.0
 420  #endif
 421  /*--------------------------------------------------------------------------*/
 422  #if (FXAA_QUALITY_PRESET == 23)
 423      #define FXAA_QUALITY_PS 6
 424      #define FXAA_QUALITY_P0 1.0
 425      #define FXAA_QUALITY_P1 1.5
 426      #define FXAA_QUALITY_P2 2.0
 427      #define FXAA_QUALITY_P3 2.0
 428      #define FXAA_QUALITY_P4 2.0
 429      #define FXAA_QUALITY_P5 8.0
 430  #endif
 431  /*--------------------------------------------------------------------------*/
 432  #if (FXAA_QUALITY_PRESET == 24)
 433      #define FXAA_QUALITY_PS 7
 434      #define FXAA_QUALITY_P0 1.0
 435      #define FXAA_QUALITY_P1 1.5
 436      #define FXAA_QUALITY_P2 2.0
 437      #define FXAA_QUALITY_P3 2.0
 438      #define FXAA_QUALITY_P4 2.0
 439      #define FXAA_QUALITY_P5 3.0
 440      #define FXAA_QUALITY_P6 8.0
 441  #endif
 442  /*--------------------------------------------------------------------------*/
 443  #if (FXAA_QUALITY_PRESET == 25)
 444      #define FXAA_QUALITY_PS 8
 445      #define FXAA_QUALITY_P0 1.0
 446      #define FXAA_QUALITY_P1 1.5
 447      #define FXAA_QUALITY_P2 2.0
 448      #define FXAA_QUALITY_P3 2.0
 449      #define FXAA_QUALITY_P4 2.0
 450      #define FXAA_QUALITY_P5 2.0
 451      #define FXAA_QUALITY_P6 4.0
 452      #define FXAA_QUALITY_P7 8.0
 453  #endif
 454  /*--------------------------------------------------------------------------*/
 455  #if (FXAA_QUALITY_PRESET == 26)
 456      #define FXAA_QUALITY_PS 9
 457      #define FXAA_QUALITY_P0 1.0
 458      #define FXAA_QUALITY_P1 1.5
 459      #define FXAA_QUALITY_P2 2.0
 460      #define FXAA_QUALITY_P3 2.0
 461      #define FXAA_QUALITY_P4 2.0
 462      #define FXAA_QUALITY_P5 2.0
 463      #define FXAA_QUALITY_P6 2.0
 464      #define FXAA_QUALITY_P7 4.0
 465      #define FXAA_QUALITY_P8 8.0
 466  #endif
 467  /*--------------------------------------------------------------------------*/
 468  #if (FXAA_QUALITY_PRESET == 27)
 469      #define FXAA_QUALITY_PS 10
 470      #define FXAA_QUALITY_P0 1.0
 471      #define FXAA_QUALITY_P1 1.5
 472      #define FXAA_QUALITY_P2 2.0
 473      #define FXAA_QUALITY_P3 2.0
 474      #define FXAA_QUALITY_P4 2.0
 475      #define FXAA_QUALITY_P5 2.0
 476      #define FXAA_QUALITY_P6 2.0
 477      #define FXAA_QUALITY_P7 2.0
 478      #define FXAA_QUALITY_P8 4.0
 479      #define FXAA_QUALITY_P9 8.0
 480  #endif
 481  /*--------------------------------------------------------------------------*/
 482  #if (FXAA_QUALITY_PRESET == 28)
 483      #define FXAA_QUALITY_PS 11
 484      #define FXAA_QUALITY_P0 1.0
 485      #define FXAA_QUALITY_P1 1.5
 486      #define FXAA_QUALITY_P2 2.0
 487      #define FXAA_QUALITY_P3 2.0
 488      #define FXAA_QUALITY_P4 2.0
 489      #define FXAA_QUALITY_P5 2.0
 490      #define FXAA_QUALITY_P6 2.0
 491      #define FXAA_QUALITY_P7 2.0
 492      #define FXAA_QUALITY_P8 2.0
 493      #define FXAA_QUALITY_P9 4.0
 494      #define FXAA_QUALITY_P10 8.0
 495  #endif
 496  /*--------------------------------------------------------------------------*/
 497  #if (FXAA_QUALITY_PRESET == 29)
 498      #define FXAA_QUALITY_PS 12
 499      #define FXAA_QUALITY_P0 1.0
 500      #define FXAA_QUALITY_P1 1.5
 501      #define FXAA_QUALITY_P2 2.0
 502      #define FXAA_QUALITY_P3 2.0
 503      #define FXAA_QUALITY_P4 2.0
 504      #define FXAA_QUALITY_P5 2.0
 505      #define FXAA_QUALITY_P6 2.0
 506      #define FXAA_QUALITY_P7 2.0
 507      #define FXAA_QUALITY_P8 2.0
 508      #define FXAA_QUALITY_P9 2.0
 509      #define FXAA_QUALITY_P10 4.0
 510      #define FXAA_QUALITY_P11 8.0
 511  #endif
 512  
 513  /*============================================================================
 514                       FXAA QUALITY - EXTREME QUALITY
 515  ============================================================================*/
 516  #if (FXAA_QUALITY_PRESET == 39)
 517      #define FXAA_QUALITY_PS 12
 518      #define FXAA_QUALITY_P0 1.0
 519      #define FXAA_QUALITY_P1 1.0
 520      #define FXAA_QUALITY_P2 1.0
 521      #define FXAA_QUALITY_P3 1.0
 522      #define FXAA_QUALITY_P4 1.0
 523      #define FXAA_QUALITY_P5 1.5
 524      #define FXAA_QUALITY_P6 2.0
 525      #define FXAA_QUALITY_P7 2.0
 526      #define FXAA_QUALITY_P8 2.0
 527      #define FXAA_QUALITY_P9 2.0
 528      #define FXAA_QUALITY_P10 4.0
 529      #define FXAA_QUALITY_P11 8.0
 530  #endif
 531  
 532  
 533  
 534  /*============================================================================
 535  
 536                                  API PORTING
 537  
 538  ============================================================================*/
 539  #if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1)
 540      #define FxaaBool bool
 541      #define FxaaDiscard discard
 542      #define FxaaFloat float
 543      #define FxaaFloat2 vec2
 544      #define FxaaFloat3 vec3
 545      #define FxaaFloat4 vec4
 546      #define FxaaHalf float
 547      #define FxaaHalf2 vec2
 548      #define FxaaHalf3 vec3
 549      #define FxaaHalf4 vec4
 550      #define FxaaInt2 ivec2
 551      #define FxaaSat(x) clamp(x, 0.0, 1.0)
 552      #define FxaaTex sampler2D
 553  #else
 554      #define FxaaBool bool
 555      #define FxaaDiscard clip(-1)
 556      #define FxaaFloat float
 557      #define FxaaFloat2 float2
 558      #define FxaaFloat3 float3
 559      #define FxaaFloat4 float4
 560      #define FxaaHalf half
 561      #define FxaaHalf2 half2
 562      #define FxaaHalf3 half3
 563      #define FxaaHalf4 half4
 564      #define FxaaSat(x) saturate(x)
 565  #endif
 566  /*--------------------------------------------------------------------------*/
 567  #if (FXAA_GLSL_120 == 1)
 568      // Requires,
 569      //  #version 120
 570      // And at least,
 571      //  #extension GL_EXT_gpu_shader4 : enable
 572      //  (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9)
 573      #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)
 574      #if (FXAA_FAST_PIXEL_OFFSET == 1)
 575          #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)
 576      #else
 577          #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)
 578      #endif
 579      #if (FXAA_GATHER4_ALPHA == 1)
 580          // use #extension GL_ARB_gpu_shader5 : enable
 581          #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
 582          #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
 583          #define FxaaTexGreen4(t, p) textureGather(t, p, 1)
 584          #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
 585      #endif
 586  #endif
 587  /*--------------------------------------------------------------------------*/
 588  #if (FXAA_GLSL_130 == 1)
 589      // Requires "#version 130" or better
 590      #define FxaaTexTop(t, p) textureLod(t, p, 0.0)
 591      #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
 592      #if (FXAA_GATHER4_ALPHA == 1)
 593          // use #extension GL_ARB_gpu_shader5 : enable
 594          #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
 595          #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
 596          #define FxaaTexGreen4(t, p) textureGather(t, p, 1)
 597          #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
 598      #endif
 599  #endif
 600  
 601  
 602  /*============================================================================
 603                     GREEN AS LUMA OPTION SUPPORT FUNCTION
 604  ============================================================================*/
 605  #if (FXAA_GREEN_AS_LUMA == 0)
 606      FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }
 607  #else
 608      FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }
 609  #endif    
 610  
 611  
 612  
 613  
 614  /*============================================================================
 615  
 616                               FXAA3 QUALITY - PC
 617  
 618  ============================================================================*/
 619  #if (FXAA_PC == 1)
 620  /*--------------------------------------------------------------------------*/
 621  FxaaFloat4 FxaaPixelShader(
 622      //
 623      // Use noperspective interpolation here (turn off perspective interpolation).
 624      // {xy} = center of pixel
 625      FxaaFloat2 pos,
 626      //
 627      // Used only for FXAA Console, and not used on the 360 version.
 628      // Use noperspective interpolation here (turn off perspective interpolation).
 629      // {xy_} = upper left of pixel
 630      // {_zw} = lower right of pixel
 631      FxaaFloat4 fxaaConsolePosPos,
 632      //
 633      // Input color texture.
 634      // {rgb_} = color in linear or perceptual color space
 635      // if (FXAA_GREEN_AS_LUMA == 0)
 636      //     {__a} = luma in perceptual color space (not linear)
 637      FxaaTex tex,
 638      //
 639      // Only used on the optimized 360 version of FXAA Console.
 640      // For everything but 360, just use the same input here as for "tex".
 641      // For 360, same texture, just alias with a 2nd sampler.
 642      // This sampler needs to have an exponent bias of -1.
 643      FxaaTex fxaaConsole360TexExpBiasNegOne,
 644      //
 645      // Only used on the optimized 360 version of FXAA Console.
 646      // For everything but 360, just use the same input here as for "tex".
 647      // For 360, same texture, just alias with a 3nd sampler.
 648      // This sampler needs to have an exponent bias of -2.
 649      FxaaTex fxaaConsole360TexExpBiasNegTwo,
 650      //
 651      // Only used on FXAA Quality.
 652      // This must be from a constant/uniform.
 653      // {x_} = 1.0/screenWidthInPixels
 654      // {_y} = 1.0/screenHeightInPixels
 655      FxaaFloat2 fxaaQualityRcpFrame,
 656      //
 657      // Only used on FXAA Console.
 658      // This must be from a constant/uniform.
 659      // This effects sub-pixel AA quality and inversely sharpness.
 660      //   Where N ranges between,
 661      //     N = 0.50 (default)
 662      //     N = 0.33 (sharper)
 663      // {x__} = -N/screenWidthInPixels  
 664      // {_y_} = -N/screenHeightInPixels
 665      // {_z_} =  N/screenWidthInPixels  
 666      // {__w} =  N/screenHeightInPixels 
 667      FxaaFloat4 fxaaConsoleRcpFrameOpt,
 668      //
 669      // Only used on FXAA Console.
 670      // Not used on 360, but used on PS3 and PC.
 671      // This must be from a constant/uniform.
 672      // {x__} = -2.0/screenWidthInPixels  
 673      // {_y_} = -2.0/screenHeightInPixels
 674      // {_z_} =  2.0/screenWidthInPixels  
 675      // {__w} =  2.0/screenHeightInPixels 
 676      FxaaFloat4 fxaaConsoleRcpFrameOpt2,
 677      //
 678      // Only used on FXAA Console.
 679      // Only used on 360 in place of fxaaConsoleRcpFrameOpt2.
 680      // This must be from a constant/uniform.
 681      // {x__} =  8.0/screenWidthInPixels  
 682      // {_y_} =  8.0/screenHeightInPixels
 683      // {_z_} = -4.0/screenWidthInPixels  
 684      // {__w} = -4.0/screenHeightInPixels 
 685      FxaaFloat4 fxaaConsole360RcpFrameOpt2,
 686      //
 687      // Only used on FXAA Quality.
 688      // This used to be the FXAA_QUALITY_SUBPIX define.
 689      // It is here now to allow easier tuning.
 690      // Choose the amount of sub-pixel aliasing removal.
 691      // This can effect sharpness.
 692      //   1.00 - upper limit (softer)
 693      //   0.75 - default amount of filtering
 694      //   0.50 - lower limit (sharper, less sub-pixel aliasing removal)
 695      //   0.25 - almost off
 696      //   0.00 - completely off
 697      FxaaFloat fxaaQualitySubpix,
 698      //
 699      // Only used on FXAA Quality.
 700      // This used to be the FXAA_QUALITY_EDGE_THRESHOLD define.
 701      // It is here now to allow easier tuning.
 702      // The minimum amount of local contrast required to apply algorithm.
 703      //   0.333 - too little (faster)
 704      //   0.250 - low quality
 705      //   0.166 - default
 706      //   0.125 - high quality 
 707      //   0.063 - overkill (slower)
 708      FxaaFloat fxaaQualityEdgeThreshold,
 709      //
 710      // Only used on FXAA Quality.
 711      // This used to be the FXAA_QUALITY_EDGE_THRESHOLD_MIN define.
 712      // It is here now to allow easier tuning.
 713      // Trims the algorithm from processing darks.
 714      //   0.0833 - upper limit (default, the start of visible unfiltered edges)
 715      //   0.0625 - high quality (faster)
 716      //   0.0312 - visible limit (slower)
 717      // Special notes when using FXAA_GREEN_AS_LUMA,
 718      //   Likely want to set this to zero.
 719      //   As colors that are mostly not-green
 720      //   will appear very dark in the green channel!
 721      //   Tune by looking at mostly non-green content,
 722      //   then start at zero and increase until aliasing is a problem.
 723      FxaaFloat fxaaQualityEdgeThresholdMin,
 724      // 
 725      // Only used on FXAA Console.
 726      // This used to be the FXAA_CONSOLE_EDGE_SHARPNESS define.
 727      // It is here now to allow easier tuning.
 728      // This does not effect PS3, as this needs to be compiled in.
 729      //   Use FXAA_CONSOLE_PS3_EDGE_SHARPNESS for PS3.
 730      //   Due to the PS3 being ALU bound,
 731      //   there are only three safe values here: 2 and 4 and 8.
 732      //   These options use the shaders ability to a free *|/ by 2|4|8.
 733      // For all other platforms can be a non-power of two.
 734      //   8.0 is sharper (default!!!)
 735      //   4.0 is softer
 736      //   2.0 is really soft (good only for vector graphics inputs)
 737      FxaaFloat fxaaConsoleEdgeSharpness,
 738      //
 739      // Only used on FXAA Console.
 740      // This used to be the FXAA_CONSOLE_EDGE_THRESHOLD define.
 741      // It is here now to allow easier tuning.
 742      // This does not effect PS3, as this needs to be compiled in.
 743      //   Use FXAA_CONSOLE_PS3_EDGE_THRESHOLD for PS3.
 744      //   Due to the PS3 being ALU bound,
 745      //   there are only two safe values here: 1/4 and 1/8.
 746      //   These options use the shaders ability to a free *|/ by 2|4|8.
 747      // The console setting has a different mapping than the quality setting.
 748      // Other platforms can use other values.
 749      //   0.125 leaves less aliasing, but is softer (default!!!)
 750      //   0.25 leaves more aliasing, and is sharper
 751      FxaaFloat fxaaConsoleEdgeThreshold,
 752      //
 753      // Only used on FXAA Console.
 754      // This used to be the FXAA_CONSOLE_EDGE_THRESHOLD_MIN define.
 755      // It is here now to allow easier tuning.
 756      // Trims the algorithm from processing darks.
 757      // The console setting has a different mapping than the quality setting.
 758      // This only applies when FXAA_EARLY_EXIT is 1.
 759      // This does not apply to PS3, 
 760      // PS3 was simplified to avoid more shader instructions.
 761      //   0.06 - faster but more aliasing in darks
 762      //   0.05 - default
 763      //   0.04 - slower and less aliasing in darks
 764      // Special notes when using FXAA_GREEN_AS_LUMA,
 765      //   Likely want to set this to zero.
 766      //   As colors that are mostly not-green
 767      //   will appear very dark in the green channel!
 768      //   Tune by looking at mostly non-green content,
 769      //   then start at zero and increase until aliasing is a problem.
 770      FxaaFloat fxaaConsoleEdgeThresholdMin,
 771      //    
 772      // Extra constants for 360 FXAA Console only.
 773      // Use zeros or anything else for other platforms.
 774      // These must be in physical constant registers and NOT immedates.
 775      // Immedates will result in compiler un-optimizing.
 776      // {xyzw} = float4(1.0, -1.0, 0.25, -0.25)
 777      FxaaFloat4 fxaaConsole360ConstDir
 778  ) {
 779  /*--------------------------------------------------------------------------*/
 780      FxaaFloat2 posM;
 781      posM.x = pos.x;
 782      posM.y = pos.y;
 783      #if (FXAA_GATHER4_ALPHA == 1)
 784          #if (FXAA_DISCARD == 0)
 785              FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
 786              #if (FXAA_GREEN_AS_LUMA == 0)
 787                  #define lumaM rgbyM.w
 788              #else
 789                  #define lumaM rgbyM.y
 790              #endif
 791          #endif
 792          #if (FXAA_GREEN_AS_LUMA == 0)
 793              FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);
 794              FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));
 795          #else
 796              FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);
 797              FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));
 798          #endif
 799          #if (FXAA_DISCARD == 1)
 800              #define lumaM luma4A.w
 801          #endif
 802          #define lumaE luma4A.z
 803          #define lumaS luma4A.x
 804          #define lumaSE luma4A.y
 805          #define lumaNW luma4B.w
 806          #define lumaN luma4B.z
 807          #define lumaW luma4B.x
 808      #else
 809          FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
 810          #if (FXAA_GREEN_AS_LUMA == 0)
 811              #define lumaM rgbyM.w
 812          #else
 813              #define lumaM rgbyM.y
 814          #endif
 815          FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));
 816          FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));
 817          FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));
 818          FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));
 819      #endif
 820  /*--------------------------------------------------------------------------*/
 821      FxaaFloat maxSM = max(lumaS, lumaM);
 822      FxaaFloat minSM = min(lumaS, lumaM);
 823      FxaaFloat maxESM = max(lumaE, maxSM);
 824      FxaaFloat minESM = min(lumaE, minSM);
 825      FxaaFloat maxWN = max(lumaN, lumaW);
 826      FxaaFloat minWN = min(lumaN, lumaW);
 827      FxaaFloat rangeMax = max(maxWN, maxESM);
 828      FxaaFloat rangeMin = min(minWN, minESM);
 829      FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
 830      FxaaFloat range = rangeMax - rangeMin;
 831      FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
 832      FxaaBool earlyExit = range < rangeMaxClamped;
 833  /*--------------------------------------------------------------------------*/
 834      if(earlyExit)
 835          #if (FXAA_DISCARD == 1)
 836              FxaaDiscard;
 837          #else
 838              return rgbyM;
 839          #endif
 840  /*--------------------------------------------------------------------------*/
 841      #if (FXAA_GATHER4_ALPHA == 0)
 842          FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));
 843          FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));
 844          FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));
 845          FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
 846      #else
 847          FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));
 848          FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
 849      #endif
 850  /*--------------------------------------------------------------------------*/
 851      FxaaFloat lumaNS = lumaN + lumaS;
 852      FxaaFloat lumaWE = lumaW + lumaE;
 853      FxaaFloat subpixRcpRange = 1.0/range;
 854      FxaaFloat subpixNSWE = lumaNS + lumaWE;
 855      FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;
 856      FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;
 857  /*--------------------------------------------------------------------------*/
 858      FxaaFloat lumaNESE = lumaNE + lumaSE;
 859      FxaaFloat lumaNWNE = lumaNW + lumaNE;
 860      FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
 861      FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
 862  /*--------------------------------------------------------------------------*/
 863      FxaaFloat lumaNWSW = lumaNW + lumaSW;
 864      FxaaFloat lumaSWSE = lumaSW + lumaSE;
 865      FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
 866      FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
 867      FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
 868      FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
 869      FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;
 870      FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;
 871  /*--------------------------------------------------------------------------*/
 872      FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;
 873      FxaaFloat lengthSign = fxaaQualityRcpFrame.x;
 874      FxaaBool horzSpan = edgeHorz >= edgeVert;
 875      FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
 876  /*--------------------------------------------------------------------------*/
 877      if(!horzSpan) lumaN = lumaW;
 878      if(!horzSpan) lumaS = lumaE;
 879      if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
 880      FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;
 881  /*--------------------------------------------------------------------------*/
 882      FxaaFloat gradientN = lumaN - lumaM;
 883      FxaaFloat gradientS = lumaS - lumaM;
 884      FxaaFloat lumaNN = lumaN + lumaM;
 885      FxaaFloat lumaSS = lumaS + lumaM;
 886      FxaaBool pairN = abs(gradientN) >= abs(gradientS);
 887      FxaaFloat gradient = max(abs(gradientN), abs(gradientS));
 888      if(pairN) lengthSign = -lengthSign;
 889      FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
 890  /*--------------------------------------------------------------------------*/
 891      FxaaFloat2 posB;
 892      posB.x = posM.x;
 893      posB.y = posM.y;
 894      FxaaFloat2 offNP;
 895      offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
 896      offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
 897      if(!horzSpan) posB.x += lengthSign * 0.5;
 898      if( horzSpan) posB.y += lengthSign * 0.5;
 899  /*--------------------------------------------------------------------------*/
 900      FxaaFloat2 posN;
 901      posN.x = posB.x - offNP.x * FXAA_QUALITY_P0;
 902      posN.y = posB.y - offNP.y * FXAA_QUALITY_P0;
 903      FxaaFloat2 posP;
 904      posP.x = posB.x + offNP.x * FXAA_QUALITY_P0;
 905      posP.y = posB.y + offNP.y * FXAA_QUALITY_P0;
 906      FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;
 907      FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
 908      FxaaFloat subpixE = subpixC * subpixC;
 909      FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
 910  /*--------------------------------------------------------------------------*/
 911      if(!pairN) lumaNN = lumaSS;
 912      FxaaFloat gradientScaled = gradient * 1.0/4.0;
 913      FxaaFloat lumaMM = lumaM - lumaNN * 0.5;
 914      FxaaFloat subpixF = subpixD * subpixE;
 915      FxaaBool lumaMLTZero = lumaMM < 0.0;
 916  /*--------------------------------------------------------------------------*/
 917      lumaEndN -= lumaNN * 0.5;
 918      lumaEndP -= lumaNN * 0.5;
 919      FxaaBool doneN = abs(lumaEndN) >= gradientScaled;
 920      FxaaBool doneP = abs(lumaEndP) >= gradientScaled;
 921      if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P1;
 922      if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P1;
 923      FxaaBool doneNP = (!doneN) || (!doneP);
 924      if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P1;
 925      if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P1;
 926  /*--------------------------------------------------------------------------*/
 927      if(doneNP) {
 928          if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 929          if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 930          if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 931          if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 932          doneN = abs(lumaEndN) >= gradientScaled;
 933          doneP = abs(lumaEndP) >= gradientScaled;
 934          if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P2;
 935          if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P2;
 936          doneNP = (!doneN) || (!doneP);
 937          if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P2;
 938          if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P2;
 939  /*--------------------------------------------------------------------------*/
 940          #if (FXAA_QUALITY_PS > 3)
 941          if(doneNP) {
 942              if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 943              if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 944              if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 945              if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 946              doneN = abs(lumaEndN) >= gradientScaled;
 947              doneP = abs(lumaEndP) >= gradientScaled;
 948              if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P3;
 949              if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P3;
 950              doneNP = (!doneN) || (!doneP);
 951              if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P3;
 952              if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P3;
 953  /*--------------------------------------------------------------------------*/
 954              #if (FXAA_QUALITY_PS > 4)
 955              if(doneNP) {
 956                  if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 957                  if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 958                  if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 959                  if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 960                  doneN = abs(lumaEndN) >= gradientScaled;
 961                  doneP = abs(lumaEndP) >= gradientScaled;
 962                  if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P4;
 963                  if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P4;
 964                  doneNP = (!doneN) || (!doneP);
 965                  if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P4;
 966                  if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P4;
 967  /*--------------------------------------------------------------------------*/
 968                  #if (FXAA_QUALITY_PS > 5)
 969                  if(doneNP) {
 970                      if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 971                      if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 972                      if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 973                      if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 974                      doneN = abs(lumaEndN) >= gradientScaled;
 975                      doneP = abs(lumaEndP) >= gradientScaled;
 976                      if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P5;
 977                      if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P5;
 978                      doneNP = (!doneN) || (!doneP);
 979                      if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P5;
 980                      if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P5;
 981  /*--------------------------------------------------------------------------*/
 982                      #if (FXAA_QUALITY_PS > 6)
 983                      if(doneNP) {
 984                          if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 985                          if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 986                          if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 987                          if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 988                          doneN = abs(lumaEndN) >= gradientScaled;
 989                          doneP = abs(lumaEndP) >= gradientScaled;
 990                          if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P6;
 991                          if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P6;
 992                          doneNP = (!doneN) || (!doneP);
 993                          if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P6;
 994                          if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P6;
 995  /*--------------------------------------------------------------------------*/
 996                          #if (FXAA_QUALITY_PS > 7)
 997                          if(doneNP) {
 998                              if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 999                              if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
1000                              if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
1001                              if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
1002                              doneN = abs(lumaEndN) >= gradientScaled;
1003                              doneP = abs(lumaEndP) >= gradientScaled;
1004                              if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P7;
1005                              if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P7;
1006                              doneNP = (!doneN) || (!doneP);
1007                              if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P7;
1008                              if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P7;
1009  /*--------------------------------------------------------------------------*/
1010      #if (FXAA_QUALITY_PS > 8)
1011      if(doneNP) {
1012          if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
1013          if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
1014          if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
1015          if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
1016          doneN = abs(lumaEndN) >= gradientScaled;
1017          doneP = abs(lumaEndP) >= gradientScaled;
1018          if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P8;
1019          if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P8;
1020          doneNP = (!doneN) || (!doneP);
1021          if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P8;
1022          if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P8;
1023  /*--------------------------------------------------------------------------*/
1024          #if (FXAA_QUALITY_PS > 9)
1025          if(doneNP) {
1026              if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
1027              if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
1028              if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
1029              if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
1030              doneN = abs(lumaEndN) >= gradientScaled;
1031              doneP = abs(lumaEndP) >= gradientScaled;
1032              if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P9;
1033              if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P9;
1034              doneNP = (!doneN) || (!doneP);
1035              if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P9;
1036              if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P9;
1037  /*--------------------------------------------------------------------------*/
1038              #if (FXAA_QUALITY_PS > 10)
1039              if(doneNP) {
1040                  if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
1041                  if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
1042                  if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
1043                  if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
1044                  doneN = abs(lumaEndN) >= gradientScaled;
1045                  doneP = abs(lumaEndP) >= gradientScaled;
1046                  if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P10;
1047                  if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P10;
1048                  doneNP = (!doneN) || (!doneP);
1049                  if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P10;
1050                  if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P10;
1051  /*--------------------------------------------------------------------------*/
1052                  #if (FXAA_QUALITY_PS > 11)
1053                  if(doneNP) {
1054                      if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
1055                      if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
1056                      if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
1057                      if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
1058                      doneN = abs(lumaEndN) >= gradientScaled;
1059                      doneP = abs(lumaEndP) >= gradientScaled;
1060                      if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P11;
1061                      if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P11;
1062                      doneNP = (!doneN) || (!doneP);
1063                      if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P11;
1064                      if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P11;
1065  /*--------------------------------------------------------------------------*/
1066                      #if (FXAA_QUALITY_PS > 12)
1067                      if(doneNP) {
1068                          if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
1069                          if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
1070                          if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
1071                          if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
1072                          doneN = abs(lumaEndN) >= gradientScaled;
1073                          doneP = abs(lumaEndP) >= gradientScaled;
1074                          if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P12;
1075                          if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P12;
1076                          doneNP = (!doneN) || (!doneP);
1077                          if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P12;
1078                          if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P12;
1079  /*--------------------------------------------------------------------------*/
1080                      }
1081                      #endif
1082  /*--------------------------------------------------------------------------*/
1083                  }
1084                  #endif
1085  /*--------------------------------------------------------------------------*/
1086              }
1087              #endif
1088  /*--------------------------------------------------------------------------*/
1089          }
1090          #endif
1091  /*--------------------------------------------------------------------------*/
1092      }
1093      #endif
1094  /*--------------------------------------------------------------------------*/
1095                          }
1096                          #endif
1097  /*--------------------------------------------------------------------------*/
1098                      }
1099                      #endif
1100  /*--------------------------------------------------------------------------*/
1101                  }
1102                  #endif
1103  /*--------------------------------------------------------------------------*/
1104              }
1105              #endif
1106  /*--------------------------------------------------------------------------*/
1107          }
1108          #endif
1109  /*--------------------------------------------------------------------------*/
1110      }
1111  /*--------------------------------------------------------------------------*/
1112      FxaaFloat dstN = posM.x - posN.x;
1113      FxaaFloat dstP = posP.x - posM.x;
1114      if(!horzSpan) dstN = posM.y - posN.y;
1115      if(!horzSpan) dstP = posP.y - posM.y;
1116  /*--------------------------------------------------------------------------*/
1117      FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
1118      FxaaFloat spanLength = (dstP + dstN);
1119      FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
1120      FxaaFloat spanLengthRcp = 1.0/spanLength;
1121  /*--------------------------------------------------------------------------*/
1122      FxaaBool directionN = dstN < dstP;
1123      FxaaFloat dst = min(dstN, dstP);
1124      FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;
1125      FxaaFloat subpixG = subpixF * subpixF;
1126      FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
1127      FxaaFloat subpixH = subpixG * fxaaQualitySubpix;
1128  /*--------------------------------------------------------------------------*/
1129      FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
1130      FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
1131      if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
1132      if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
1133      #if (FXAA_DISCARD == 1)
1134          return FxaaTexTop(tex, posM);
1135      #else
1136          return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);
1137      #endif
1138  }
1139  /*==========================================================================*/
1140  #endif
1141  
1142  vec4 mainImage(vec2 fragCoord)
1143  {
1144      vec2 rcpFrame = 1./invResolution_data.xy;
1145    	vec2 uv2 = fragCoord.xy / invResolution_data.xy;
1146  
1147      float fxaaQualitySubpix = 0.75;  // [0..1], default 0.75
1148      float fxaaQualityEdgeThreshold = 0.166;  // [0.125..0.33], default 0.166
1149      float fxaaQualityEdgeThresholdMin = 0.02;//0.0625; // ?
1150      vec4 dummy4 =  vec4(0.0,0.0,0.0,0.0);
1151      float dummy1 = 0.0;
1152  
1153      vec4 col = FxaaPixelShader(uv2, dummy4,
1154                                      inputImage, inputImage, inputImage,
1155                                      rcpFrame, dummy4, dummy4, dummy4,
1156                                      fxaaQualitySubpix, fxaaQualityEdgeThreshold,
1157                                      fxaaQualityEdgeThresholdMin,
1158                                      dummy1, dummy1, dummy1, dummy4);
1159  
1160      vec4 fragColor = vec4( col.xyz, 1. );
1161  
1162      return fragColor;
1163  }
1164  
1165  void main()
1166  {
1167      ivec2 loc = ivec2(gl_GlobalInvocationID.x * 4, gl_GlobalInvocationID.y * 4);
1168      for(int i = 0; i < 4; i++)
1169      {
1170          for(int j = 0; j < 4; j++)
1171          {
1172              ivec2 texelCoord = ivec2(loc.x + i, loc.y + j);
1173              vec4 outColor = mainImage(texelCoord + vec2(0.5));
1174              imageStore(imgOutput, texelCoord, outColor);
1175          }
1176      }
1177  }