diff --git a/bin/cheats_ws/492CB73E.pnach b/bin/cheats_ws/492CB73E.pnach index e31da1ed4e..ceec50f55d 100644 --- a/bin/cheats_ws/492CB73E.pnach +++ b/bin/cheats_ws/492CB73E.pnach @@ -20,4 +20,4 @@ patch=1,EE,002c4744,word,44810000 patch=1,EE,003892B8,word,24020002 //noise off -patch=1,EE,2047ADC0,extended,00000000 \ No newline at end of file +//patch=1,EE,2047ADC0,extended,00000000 \ No newline at end of file diff --git a/bin/cheats_ws/61A7E622.pnach b/bin/cheats_ws/61A7E622.pnach index e43e281732..1bb8602e57 100644 --- a/bin/cheats_ws/61A7E622.pnach +++ b/bin/cheats_ws/61A7E622.pnach @@ -20,4 +20,4 @@ patch=1,EE,002c455c,word,44810000 patch=1,EE,003890E0,word,24020002 //noise off -patch=1,EE,2047ABC0,extended,00000000 \ No newline at end of file +//patch=1,EE,2047ABC0,extended,00000000 \ No newline at end of file diff --git a/plugins/GSdx/res/fxaa.fx b/plugins/GSdx/res/fxaa.fx index 15d4721e08..a70c20c2c7 100644 --- a/plugins/GSdx/res/fxaa.fx +++ b/plugins/GSdx/res/fxaa.fx @@ -1,31 +1,177 @@ -#if defined(SHADER_MODEL) || defined(FXAA_GLSL_130) // make safe to include in resource file to enforce dependency +/*===============================================================================*\ +|######################## [PCSX2 Fx 2.00 Revised] #########################| +|########################## By Asmodean ###########################| +|| || +|| This program is free software; you can redistribute it and/or || +|| modify it under the terms of the GNU General Public License || +|| as published by the Free Software Foundation; either version 2 || +|| of the License, or (at your option) any later version. || +|| || +|| This program is distributed in the hope that it will be useful, || +|| but WITHOUT ANY WARRANTY; without even the implied warranty of || +|| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the || +|| GNU General Public License for more details. (c)2013 || +|| || +|#################################################################################| +\*===============================================================================*/ -#ifndef FXAA_GLSL_130 - #define FXAA_GLSL_130 0 +#if defined(SHADER_MODEL) // make safe to include in resource file to enforce dependency + +/*------------------------------------------------------------------------------ +[DEFINITIONS & ON/OFF OPTIONS] +------------------------------------------------------------------------------*/ + +//---------------------------#[CHOOSE EFFECTS]#--------------------------------\\ + +//-#[ANTIALIASING TECHNIQUES] [1=ON|0=OFF] #READ: For best results: Use post antialiasing OR FS filtering. Not both. Postfix [2D/3D] after descriptions indicates if it's typically better for 2D, or 3D. +#define UHQ_FXAA 1 //#High Quality Fast Approximate Anti Aliasing. Adapted for GSdx from Timothy Lottes FXAA 3.11. [3D] + +//-#[FS FILTERING TECHNIQUES] [1=ON|0=OFF] #READ: For best results: Only enable one type of filtering at one time. Use post antialiasing OR FS filtering, not both. +#define BILINEAR_FILTERING 0 //#BiLinear Fullscreen Texture Filtering. BiLinear filtering - light to medium filtering of textures. [2D] +#define BICUBIC_FILTERING 0 //#BiCubic Fullscreen Texture Filtering. BiCubic filtering - medium to strong filtering of textures. [2D] +#define GAUSSIAN_FILTERING 0 //#Gaussian Fullscreen Texture Filtering. BiLinear filtering - strong to extra strong filtering of textures. [2D] + +//-#[LIGHTING & COLOUR] [1=ON|0=OFF] #READ: These can all be turned on & off independently of each other. [For High Dynamic Range(HDR) - use Bloom, Tonemapping, & Gamma Correction together] +#define BLENDED_BLOOM 1 //#High Quality Bloom, using blend techniques. Blooms naturally, per environment. [For best results: use bloom, tone mapping, & gamma together]. +#define SCENE_TONEMAPPING 1 //#Scene Tonemapping & RGB Colour Correction. [For best results: use bloom, tone mapping, & gamma together]. +#define GAMMA_CORRECTION 1 //#RGB Post Gamma Correction Curve. [For best results: use bloom, tone mapping, & gamma together]. +#define S_CURVE_CONTRAST 1 //#S-Curve Scene Contrast Enhancement. Naturally adjusts contrast using S-curves. +#define TEXTURE_SHARPENING 1 //#HQ Luma-Based Texture Sharpen, looks similar to a negative mip LOD Bias, enhances texture fidelity. +#define PIXEL_VIBRANCE 0 //#Pixel Vibrance. Intelligently adjusts pixel vibrance depending on original saturation. +#define COLOR_GRADING 0 //#Post-Complement Colour Grading. Alters individual colour components on a scene, to enhance selected colour tones. +#define CEL_SHADING 0 //#Cel Shaded toon look, simulates the look of animation/toon. Typically best suited for animated-style games. (cel edges interfere with post AA.) + +//-#[TV EMU TECHNIQUES] [1=ON|0=OFF] #READ: These can all be turned on & off independently of each other. These effects are typically used to simulated older TVs/CRT etc. +#define SCANLINES 0 //#Scanlines to simulate the look of a CRT TV. Typically best suited for 2D/sprite games. +#define VIGNETTE 0 //#Darkens the edges of the screen, to make it look more like it was shot with a camera lens. +#define DITHERING 0 //#Subpixel Dithering to simulate more colors than your monitor can display. Smoothes gradiants, this can reduce color banding. + +/*------------------------------------------------------------------------------ +[SHADER FX CONFIG OPTIONS] +------------------------------------------------------------------------------*/ + +//-[FXAA OPTIONS] +#define FxaaSubpixMax 0.00 //[0.00 to 1.00] Amount of subpixel aliasing removal. Higher values: more subpixel antialiasing(softer). Lower values: less subpixel antialiasing(sharper). 0.00: Edge only antialiasing (no blurring) +#define FxaaQuality 4 //[1|2|3|4] Overall Fxaa quality preset (pixel coverage). 1: Low, 2: Medium, 3: High, 4: Ultra. I use these labels lightly, as even the 'low coverage' preset is in fact, still pretty high quality. +#define FxaaEarlyExit 1 //[0 or 1] Use Fxaa early exit pathing. This basically tells the algorithm to offset only luma-edge detected pixels. When disabled, the entire scene is antialiased(FSAA). 0 is off, 1 is on. + +//-[BILINEAR OPTIONS] +#define FilterStrength 1.00 //[0.10 to 1.50] Bilinear filtering strength. Controls the overall strength of the filtering. +#define OffsetAmount 0.0 //[0.0 to 1.5] Pixel offset amount. If you want to use an st offset, 0.5 is generally recommended. 0.0 is off. + +//-[BICUBIC OPTIONS] +#define Interpolation Triangular //[CatMullRom, Bell, BSpline, Triangular, Cubic] Type of interpolation to use. From left to right is lighter<-->stronger filtering. Try them out, and use what you prefer. +#define PixelOffset 0.0 //[0.0 to 1.5] Pixel offset amount. If you want to use an st offset, 0.5 is generally recommended. 0.0 is off. + +//-[GAUSSIAN OPTIONS] +#define FilterAmount 0.75 //[0.10 to 1.50] Gaussian filtering strength. Controls the overall strength of the filtering. +#define GaussianSpread 1.00 //[0.50 to 4.00] The filtering spread & offset levels. Controls the sampling spread of the filtering. + +//-[BLOOM OPTIONS] +#define BloomType BlendScreen //[BlendScreen, BlendOverlay, BlendAddLight] The type of blend for the bloom (Default: BlendScreen). If using BlendOverlay set ToneAmount to 2.20, or it may be too dark. +#define BloomPower 0.330 //[0.000 to 2.000] Strength of the bloom. You may need to readjust for each blend type. +#define BlendPower 1.000 //[0.000 to 1.500] Strength of the bloom blend. Lower for less blending, higher for more. Default is 1.000. +#define BlendSpread 4.000 //[0.000 to 8.000] Width of the bloom glow spread. Scales with BloomPower. Raising SharpenClamp affects this. 0.000 = off. +#define BloomMixType 1 //[1|2|3] The interpolation mix type between the base colour, and bloom. (Default is 1) BloomPower/BlendSpread may need re-adjusting depending on type. + +//-[TONEMAP OPTIONS] +#define TonemapType 1 //[1 or 2] Type of tone mapping. 1 is Natural(default), 2 is Filmic(cinematic) You might want to increase/decrease ToneAmount to compensate for diff types. +#define ToneAmount 2.00 //[1.00 to 4.00] Tonemapping & Gamma curve (Tonemapping/Shadow correction). Lower values for darker tones, Higher values for lighter tones. Default: 2.20 +#define Luminance 1.00 //[0.10 to 2.00] Luminance Average (luminance correction) Higher values to decrease luminance average, lower values to increase luminance. Adjust by small amounts, eg: increments of 0.1 +#define Exposure 1.00 //[0.10 to 2.00] White Correction (brightness) Higher values = more Exposure, lower = less Exposure. Adjust by small amounts, eg: increments of 0.1 +#define WhitePoint 1.00 //[0.10 to 2.00] Whitepoint Avg (lum correction) Adjust by small amounts, eg: increments of 0.01. Generally it's best left at 1.00. +#define RedCurve 1.00 //[1.00 to 8.00] Red channel component of the RGB correction curve. Use this to reduce/correct the red colour component. Higher values equals more red reduction. 1.00 is default. +#define GreenCurve 1.00 //[1.00 to 8.00] Green channel component of the RGB correction curve. Use this to reduce/correct the green colour component. Higher values equals more green reduction. 1.00 is default. +#define BlueCurve 1.00 //[1.00 to 8.00] Blue channel component of the RGB correction curve. Use this to reduce/correct the blue colour component. Higher values equals more blue reduction. 1.00 is default. + +//-[CONTRAST OPTIONS] +#define CurveType 0 //[0|1|2] Choose what to apply contrast to. 0 = Luma, 1 = Chroma, 2 = both Luma and Chroma. Default is 0 (Luma) +#define CurvesContrast 0.60 //[0.00 to 2.00] The amount of contrast you want. CurvesFormula 1 typically needs half the amount of CurvesFormula 2, for the same strength. +#define CurvesFormula 1 //[1|2] The contrast s-curve you want to use. 1 is a softer curve. 2 is a harsher curve. + +//-[SHARPEN OPTIONS] +#define SharpeningType 2 //[1 or 2] The type of sharpening to use. Type 1 is the original High Pass Gaussian, and type 2 is a new Bicubic Sampling type. +#define SharpenStrength 0.75 //[0.10 to 2.00] Strength of the texture sharpening effect. This is the maximum strength that will be used. The clamp below limits the minimum, and maximum that is allowed per pixel. +#define SharpenClamp 0.020 //[0.005 to 0.500] Reduces the clamping/limiting on the maximum amount of sharpening each pixel recieves. Raise this to reduce the clamping. +#define SharpenBias 1.25 //[1.00 to 4.00] Sharpening edge bias. Lower values for clean subtle sharpen, and higher values for a deeper textured sharpen. For SharpeningType 2, best stay under ~2.00, or it may look odd. +#define DebugSharpen 0 //[0 or 1] Visualize the sharpening effect. Useful for fine-tuning. + +//-[VIBRANCE OPTIONS] +#define Vibrance 0.10 //[-1.00 to 1.00] Intelligently saturates (or desaturates with negative values) pixels depending on their original saturation. 0.00 is original vibrance. + +//-[GAMMA OPTIONS] +#define Gamma 2.2 //Lower values for more Gamma toning(darker), higher Values for brighter (2.2 correction is generally recommended) + +//-[GRADING OPTIONS] +#define RedGrading 1.02 //[0.0 to 3.0] Red colour grading coefficient. Adjust to influence the red channel coefficients of the grading, and highlight tones. +#define GreenGrading 0.96 //[0.0 to 3.0] Green colour grading coefficient. Adjust to influence the Green channel coefficients of the grading, and highlight tones. +#define BlueGrading 0.88 //[0.0 to 3.0] Blue colour grading coefficient. Adjust to influence the Blue channel coefficients of the grading, and highlight tones. +#define GradingStrength 0.40 //[0.00 to 1.00] The overall max strength of the colour grading effect. Raise to increase, lower to decrease the amount. +#define Correlation 0.50 //[0.10 to 1.00] Correlation between the base colour, and the grading influence. Lower = more of the scene is graded, Higher = less of the scene is graded. + +//-[TOON OPTIONS] +#define EdgeStrength 1.25 //[0.00 to 4.00] Strength of the cel edge outline effect. 0.00 = no outlines. +#define EdgeFilter 0.50 //[0.10 to 2.00] Raise this to filter out fainter cel edges. You might need to increase the power to compensate, when raising this. +#define EdgeThickness 1.00 //[0.50 to 4.00] Thickness of the cel edges. Decrease for thinner outlining, Increase for thicker outlining. 1.00 is default. +#define PaletteType 2 //[1|2|3] The colour palette to use. 1 is Original, 2 is Animated Shading, 3 is Water Painting (Default is 2: Animated Shading). Below options don't affect palette 1. +#define UseYuvLuma 0 //[0 or 1] Uses YUV luma calculations, or base colour luma calculations. 0 is base luma, 1 is Yuv luma. Color luma can be more accurate. Yuv luma can be better for a shaded look. +#define LumaConversion 1 //[0 or 1] Uses BT.601, or BT.709, RGB<-YUV->RGB conversions. Some games prefer 601, but most prefer 709. BT.709 is typically recommended. +#define ColorRounding 0 //[0 or 1] Uses rounding methods on colors. This can emphasise shaded toon colors. Looks good in some games, and odd in others. Try it in-game and see. + +//-[SCANLINE OPTIONS] +#define ScanlineType 3 //[0|1|2|3] The type & orientation of the scanlines. 0 is x(horizontal), 1 is y(vertical), 2 is both(xy), ScanlineType 3 is a different algorithm, to work around PCSX2's IR scaling. +#define ScanlineScale 1.00 //[0.20 to 2.00] The scaling & thickness of the scanlines. Changing this can help with PCSX2 IR scaling problems. Defaults: 0.50 for ScanlineType 0|1|2, (1.20 for ScanlineType 3, use 1.0 with low IR (lower than 3x)). +#define ScanlineIntensity 0.50 //[0.10 to 1.00] The intensity of the scanlines. Defaults: 0.20 for ScanlineType 0|1|2, 0.50 for ScanlineType 3. +#define ScanlineBrightness 1.50 //[0.50 to 2.00] The brightness of the scanlines. Defaults: 1.75 for ScanlineType 0|1|2, 1.50 for ScanlineType 3. + +//-[VIGNETTE OPTIONS] +#define VignetteRatio 1.77 //[0.15 to 6.00] Sets the espect ratio of the vignette. 1.77 for 16:9, 1.60 for 16:10, 1.33 for 4:3, 1.00 for 1:1. +#define VignetteRadius 1.00 //[0.50 to 3.00] Radius of the vignette effect. Lower values for stronger radial effect from center +#define VignetteAmount 0.75 //[0.00 to 2.00] Strength of black edge occlusion. Increase for higher strength, decrease for lower. +#define VignetteSlope 8 //[2|4|8|12|16] How far away from the center the vignetting will start. + +//-[DITHERING OPTIONS] +#define DitherMethod 2 //[1 or 2] 1 is Ordering dithering(faster, lower quality), 2 is Random dithering (better dithering, but not as fast) + +//-[END OF USER OPTIONS] + +/*------------------------------------------------------------------------------ +[GLOBALS|FUNCTIONS] +------------------------------------------------------------------------------*/ + +#if (SHADER_MODEL == 0x500) +#define VS_VERSION vs_5_0 +#define PS_VERSION ps_5_0 +#else +#define VS_VERSION vs_4_0 +#define PS_VERSION ps_4_0 #endif -#define FXAA_PC 1 -#define FXAA_QUALITY_SUBPIX 0.0 - -#ifdef SHADER_MODEL -#if SHADER_MODEL >= 0x400 - -#if SHADER_MODEL >= 0x500 - #define FXAA_HLSL_5 1 -#else - #define FXAA_HLSL_4 1 -#endif - -Texture2D Texture; -SamplerState TextureSampler; +Texture2D Texture : TEXTURE : register(PS_VERSION, t0); +SamplerState TextureSampler : register(PS_VERSION, s0) +{ + Filter = Anisotropic; + MaxAnisotropy = 16; + AddressU = Clamp; + AddressV = Clamp; +}; cbuffer cb0 { - float4 _rcpFrame; - float4 _rcpFrameOpt; + float4 _rcpFrame : VIEWPORT : register(PS_VERSION, b0); + matrixworldMatrix : WORLD; + matrixviewMatrix : VIEW; + matrixprojectionMatrix : PROJECTION; + static const float GammaConst = 2.2; }; -struct PS_INPUT +struct VS_INPUT +{ + float4 p : POSITION; + float2 t : TEXCOORD0; +}; + +struct VS_OUTPUT { float4 p : SV_Position; float2 t : TEXCOORD0; @@ -36,1219 +182,1630 @@ struct PS_OUTPUT float4 c : SV_Target0; }; -#elif SHADER_MODEL <= 0x300 - -#define FXAA_HLSL_3 1 - -sampler Texture : register(s0); - -float4 _rcpFrame : register(c0); -float4 _rcpFrameOpt : register(c1); - -struct PS_INPUT +//experimental, not used currently. +float TrueLuminance(float3 color) { -#if SHADER_MODEL < 0x300 - float4 p : TEXCOORD1; -#else - float4 p : VPOS; -#endif - float2 t : TEXCOORD0; -}; - -struct PS_OUTPUT -{ - float4 c : COLOR; -}; - -#endif -#endif - - -#if (FXAA_GLSL_130 == 1) -struct vertex_basic -{ - vec4 p; - vec2 t; -}; - -#ifdef DISABLE_GL42 -layout(std140) uniform cb13 -#else -layout(std140, binding = 13) uniform cb13 -#endif -{ - vec4 _rcpFrame; - vec4 _rcpFrameOpt; -}; - -#ifdef ENABLE_BINDLESS_TEX -layout(bindless_sampler, location = 0) uniform sampler2D TextureSampler; -#else -#ifdef DISABLE_GL42 -uniform sampler2D TextureSampler; -#else -layout(binding = 0) uniform sampler2D TextureSampler; -#endif -#endif - -#if !GL_ES && __VERSION__ > 140 - -in SHADER -{ - vec4 p; - vec2 t; -} PSin; - -#define PSin_p (PSin.p) -#define PSin_t (PSin.t) - -#else - -#ifdef DISABLE_SSO -in vec4 SHADERp; -in vec2 SHADERt; -#else -layout(location = 0) in vec4 SHADERp; -layout(location = 1) in vec2 SHADERt; -#endif -#define PSin_p SHADERp -#define PSin_t SHADERt - -#endif - -layout(location = 0) out vec4 SV_Target0; - -#endif - -/*============================================================================ - - - NVIDIA FXAA 3.10 by TIMOTHY LOTTES - - ------------------------------------------------------------------------------- -COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. ------------------------------------------------------------------------------- -TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED -*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA -OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR -CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR -LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, -OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE -THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - ------------------------------------------------------------------------------- - INTEGRATION CHECKLIST ------------------------------------------------------------------------------- -(1.) -In the shader source, -setup defines for the desired configuration. -Example, - - #define FXAA_PC 1 - #define FXAA_HLSL_3 1 - #define FXAA_QUALITY_PRESET 12 - #define FXAA_QUALITY_EDGE_THRESHOLD (1.0/6.0) - #define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/12.0) - -(2.) -Then include this file, - - #include "Fxaa3.h" - -(3.) -Then call the FXAA pixel shader from within your desired shader, - - return FxaaPixelShader(pos, posPos, tex, rcpFrame, rcpFrameOpt); - -(4.) -Insure pass prior to FXAA outputs RGBL. -See next section. - -(5.) -Setup engine to provide "rcpFrame" and "rcpFrameOpt" constants. -Not using constants will result in a performance loss. - - // {x_} = 1.0/screenWidthInPixels - // {_y} = 1.0/screenHeightInPixels - float2 rcpFrame - - // This must be from a constant/uniform. - // {x___} = 2.0/screenWidthInPixels - // {_y__} = 2.0/screenHeightInPixels - // {__z_} = 0.5/screenWidthInPixels - // {___w} = 0.5/screenHeightInPixels - float4 rcpFrameOpt - -(5.a.) -Optionally change to this for sharper FXAA Console, - - // This must be from a constant/uniform. - // {x___} = 2.0/screenWidthInPixels - // {_y__} = 2.0/screenHeightInPixels - // {__z_} = 0.333/screenWidthInPixels - // {___w} = 0.333/screenHeightInPixels - float4 rcpFrameOpt - -(6.) -Have FXAA vertex shader run as a full screen triangle, -and output "pos" and "posPos" such that inputs in the pixel shader provide, - - // {xy} = center of pixel - float2 pos, - - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - float4 posPos, - -(7.) -Insure the texture sampler used by FXAA is set to bilinear filtering. - - ------------------------------------------------------------------------------- - INTEGRATION - RGBL AND COLORSPACE ------------------------------------------------------------------------------- -FXAA3 requires RGBL as input. - -RGB should be LDR (low dynamic range). -Specifically do FXAA after tonemapping. - -RGB data as returned by a texture fetch can be linear or non-linear. -Note an "sRGB format" texture counts as linear, -because the result of a texture fetch is linear data. -Regular "RGBA8" textures in the sRGB colorspace are non-linear. - -Luma must be stored in the alpha channel prior to running FXAA. -This luma should be in a perceptual space (could be gamma 2.0). -Example pass before FXAA where output is gamma 2.0 encoded, - - color.rgb = ToneMap(color.rgb); // linear color output - color.rgb = sqrt(color.rgb); // gamma 2.0 color output - return color; - -To use FXAA, - - color.rgb = ToneMap(color.rgb); // linear color output - color.rgb = sqrt(color.rgb); // gamma 2.0 color output - color.a = dot(color.rgb, float3(0.299, 0.587, 0.114)); // compute luma - return color; - -Another example where output is linear encoded, -say for instance writing to an sRGB formated render target, -where the render target does the conversion back to sRGB after blending, - - color.rgb = ToneMap(color.rgb); // linear color output - return color; - -To use FXAA, - - color.rgb = ToneMap(color.rgb); // linear color output - color.a = sqrt(dot(color.rgb, float3(0.299, 0.587, 0.114))); // compute luma - return color; - -Getting luma correct is required for the algorithm to work correctly. - - ------------------------------------------------------------------------------- - BEING LINEARLY CORRECT? ------------------------------------------------------------------------------- -Applying FXAA to a framebuffer with linear RGB color will look worse. -This is very counter intuitive, but happends to be true in this case. -The reason is because dithering artifacts will be more visiable -in a linear colorspace. - - ------------------------------------------------------------------------------- - COMPLEX INTEGRATION ------------------------------------------------------------------------------- -Q. What if the engine is blending into RGB before wanting to run FXAA? - -A. In the last opaque pass prior to FXAA, - have the pass write out luma into alpha. - Then blend into RGB only. - FXAA should be able to run ok - assuming the blending pass did not any add aliasing. - This should be the common case for particles and common blending passes. - -============================================================================*/ - -/*============================================================================ - - INTEGRATION KNOBS - -============================================================================*/ -// -// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). -// FXAA_360_OPT is a prototype for the new optimized 360 version. -// -// 1 = Use API. -// 0 = Don't use API. -// -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_PS3 - #define FXAA_PS3 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_360 - #define FXAA_360 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_360_OPT - #define FXAA_360_OPT 0 -#endif -/*==========================================================================*/ -#ifndef FXAA_PC - // - // FXAA Quality - // The high quality PC algorithm. - // - #define FXAA_PC 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_PC_CONSOLE - // - // The console algorithm for PC is included - // for developers targeting really low spec machines. - // - #define FXAA_PC_CONSOLE 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GLSL_120 - #define FXAA_GLSL_120 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GLSL_130 - #define FXAA_GLSL_130 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_3 - #define FXAA_HLSL_3 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_4 - #define FXAA_HLSL_4 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_5 - #define FXAA_HLSL_5 0 -#endif -/*==========================================================================*/ -#ifndef FXAA_EARLY_EXIT - // - // Controls algorithm's early exit path. - // On PS3 turning this on adds 2 cycles to the shader. - // On 360 turning this off adds 10ths of a millisecond to the shader. - // Turning this off on console will result in a more blurry image. - // So this defaults to on. - // - // 1 = On. - // 0 = Off. - // - #define FXAA_EARLY_EXIT 1 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_DISCARD - // - // Only valid for PC OpenGL currently. - // - // 1 = Use discard on pixels which don't need AA. - // For APIs which enable concurrent TEX+ROP from same surface. - // 0 = Return unchanged color on pixels which don't need AA. - // - #define FXAA_DISCARD 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_FAST_PIXEL_OFFSET - // - // Used for GLSL 120 only. - // - // 1 = GL API supports fast pixel offsets - // 0 = do not use fast pixel offsets - // - #ifdef GL_EXT_gpu_shader4 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifdef GL_NV_gpu_shader5 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifdef GL_ARB_gpu_shader5 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifndef FXAA_FAST_PIXEL_OFFSET - #define FXAA_FAST_PIXEL_OFFSET 0 - #endif -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GATHER4_ALPHA - // - // 1 = API supports gather4 on alpha channel. - // 0 = API does not support gather4 on alpha channel. - // - #if (FXAA_HLSL_5 == 1) - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifdef GL_ARB_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifdef GL_NV_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifndef FXAA_GATHER4_ALPHA - #define FXAA_GATHER4_ALPHA 0 - #endif -#endif - -/*============================================================================ - FXAA CONSOLE - TUNING KNOBS -============================================================================*/ -#ifndef FXAA_CONSOLE_EDGE_SHARPNESS - // - // Consoles the sharpness of edges. - // - // Due to the PS3 being ALU bound, - // there are only two safe values here: 4 and 8. - // These options use the shaders ability to a free *|/ by 4|8. - // - // 8.0 is sharper - // 4.0 is softer - // 2.0 is really soft (good for vector graphics inputs) - // - #if 1 - #define FXAA_CONSOLE_EDGE_SHARPNESS 8.0 - #endif - #if 0 - #define FXAA_CONSOLE_EDGE_SHARPNESS 4.0 - #endif - #if 0 - #define FXAA_CONSOLE_EDGE_SHARPNESS 2.0 - #endif -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_CONSOLE_EDGE_THRESHOLD - // - // The minimum amount of local contrast required to apply algorithm. - // The console setting has a different mapping than the quality setting. - // - // This only applies when FXAA_EARLY_EXIT is 1. - // - // Due to the PS3 being ALU bound, - // there are only two safe values here: 0.25 and 0.125. - // These options use the shaders ability to a free *|/ by 4|8. - // - // 0.125 leaves less aliasing, but is softer - // 0.25 leaves more aliasing, and is sharper - // - #if 1 - #define FXAA_CONSOLE_EDGE_THRESHOLD 0.125 - #else - #define FXAA_CONSOLE_EDGE_THRESHOLD 0.25 - #endif -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_CONSOLE_EDGE_THRESHOLD_MIN - // - // Trims the algorithm from processing darks. - // The console setting has a different mapping than the quality setting. - // - // This only applies when FXAA_EARLY_EXIT is 1. - // - // This does not apply to PS3. - // PS3 was simplified to avoid more shader instructions. - // - #define FXAA_CONSOLE_EDGE_THRESHOLD_MIN 0.05 -#endif - -/*============================================================================ - FXAA QUALITY - TUNING KNOBS -============================================================================*/ -#ifndef FXAA_QUALITY_EDGE_THRESHOLD - // - // The minimum amount of local contrast required to apply algorithm. - // - // 1/3 - too little - // 1/4 - low quality - // 1/6 - default - // 1/8 - high quality (default) - // 1/16 - overkill - // - #define FXAA_QUALITY_EDGE_THRESHOLD (1.0/6.0) -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_QUALITY_EDGE_THRESHOLD_MIN - // - // Trims the algorithm from processing darks. - // - // 1/32 - visible limit - // 1/16 - high quality - // 1/12 - upper limit (default, the start of visible unfiltered edges) - // - #define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/12.0) -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_QUALITY_SUBPIX - // - // Choose the amount of sub-pixel aliasing removal. - // - // 1 - upper limit (softer) - // 3/4 - default amount of filtering - // 1/2 - lower limit (sharper, less sub-pixel aliasing removal) - // - #define FXAA_QUALITY_SUBPIX (3.0/4.0) -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_QUALITY_PRESET - // - // Choose the quality preset. - // - // OPTIONS - // ----------------------------------------------------------------------- - // 10 to 15 - default medium dither (10=fastest, 15=highest quality) - // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) - // 39 - no dither, very expensive - // - // NOTES - // ----------------------------------------------------------------------- - // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) - // 13 = about same speed as FXAA 3.9 and better than 12 - // 23 = closest to FXAA 3.9 visually and performance wise - // _ = the lowest digit is directly related to performance - // _ = the highest digit is directly related to style - // - #define FXAA_QUALITY_PRESET 12 -#endif - - -/*============================================================================ - - FXAA QUALITY - PRESETS - -============================================================================*/ - -/*============================================================================ - FXAA QUALITY - MEDIUM DITHER PRESETS -============================================================================*/ -#if (FXAA_QUALITY_PRESET == 10) - #define FXAA_QUALITY_PS 3 - #define FXAA_QUALITY_P0 1.5 - #define FXAA_QUALITY_P1 3.0 - #define FXAA_QUALITY_P2 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 11) - #define FXAA_QUALITY_PS 4 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 3.0 - #define FXAA_QUALITY_P3 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 12) - #define FXAA_QUALITY_PS 5 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 4.0 - #define FXAA_QUALITY_P4 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 13) - #define FXAA_QUALITY_PS 6 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 4.0 - #define FXAA_QUALITY_P5 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 14) - #define FXAA_QUALITY_PS 7 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 2.0 - #define FXAA_QUALITY_P5 4.0 - #define FXAA_QUALITY_P6 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 15) - #define FXAA_QUALITY_PS 8 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 2.0 - #define FXAA_QUALITY_P5 2.0 - #define FXAA_QUALITY_P6 4.0 - #define FXAA_QUALITY_P7 12.0 -#endif - -/*============================================================================ - FXAA QUALITY - LOW DITHER PRESETS -============================================================================*/ -#if (FXAA_QUALITY_PRESET == 20) - #define FXAA_QUALITY_PS 3 - #define FXAA_QUALITY_P0 1.5 - #define FXAA_QUALITY_P1 2.0 - #define FXAA_QUALITY_P2 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 21) - #define FXAA_QUALITY_PS 4 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 22) - #define FXAA_QUALITY_PS 5 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 23) - #define FXAA_QUALITY_PS 6 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 2.0 - #define FXAA_QUALITY_P5 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 24) - #define FXAA_QUALITY_PS 7 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 2.0 - #define FXAA_QUALITY_P5 3.0 - #define FXAA_QUALITY_P6 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 25) - #define FXAA_QUALITY_PS 8 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 2.0 - #define FXAA_QUALITY_P5 2.0 - #define FXAA_QUALITY_P6 4.0 - #define FXAA_QUALITY_P7 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 26) - #define FXAA_QUALITY_PS 9 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 2.0 - #define FXAA_QUALITY_P5 2.0 - #define FXAA_QUALITY_P6 2.0 - #define FXAA_QUALITY_P7 4.0 - #define FXAA_QUALITY_P8 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 27) - #define FXAA_QUALITY_PS 10 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 2.0 - #define FXAA_QUALITY_P5 2.0 - #define FXAA_QUALITY_P6 2.0 - #define FXAA_QUALITY_P7 2.0 - #define FXAA_QUALITY_P8 4.0 - #define FXAA_QUALITY_P9 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 28) - #define FXAA_QUALITY_PS 11 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 2.0 - #define FXAA_QUALITY_P5 2.0 - #define FXAA_QUALITY_P6 2.0 - #define FXAA_QUALITY_P7 2.0 - #define FXAA_QUALITY_P8 2.0 - #define FXAA_QUALITY_P9 4.0 - #define FXAA_QUALITY_P10 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY_PRESET == 29) - #define FXAA_QUALITY_PS 12 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.5 - #define FXAA_QUALITY_P2 2.0 - #define FXAA_QUALITY_P3 2.0 - #define FXAA_QUALITY_P4 2.0 - #define FXAA_QUALITY_P5 2.0 - #define FXAA_QUALITY_P6 2.0 - #define FXAA_QUALITY_P7 2.0 - #define FXAA_QUALITY_P8 2.0 - #define FXAA_QUALITY_P9 2.0 - #define FXAA_QUALITY_P10 4.0 - #define FXAA_QUALITY_P11 8.0 -#endif - -/*============================================================================ - FXAA QUALITY - EXTREME QUALITY -============================================================================*/ -#if (FXAA_QUALITY_PRESET == 39) - #define FXAA_QUALITY_PS 12 - #define FXAA_QUALITY_P0 1.0 - #define FXAA_QUALITY_P1 1.0 - #define FXAA_QUALITY_P2 1.0 - #define FXAA_QUALITY_P3 1.0 - #define FXAA_QUALITY_P4 1.0 - #define FXAA_QUALITY_P5 1.5 - #define FXAA_QUALITY_P6 2.0 - #define FXAA_QUALITY_P7 2.0 - #define FXAA_QUALITY_P8 2.0 - #define FXAA_QUALITY_P9 2.0 - #define FXAA_QUALITY_P10 4.0 - #define FXAA_QUALITY_P11 8.0 -#endif - - - -/*============================================================================ - - API PORTING - -============================================================================*/ -#if (FXAA_GLSL_120 == 1) - // Requires, - // #version 120 - // And at least, - // #extension GL_EXT_gpu_shader4 : enable - // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) - #define half float - #define half2 vec2 - #define half3 vec3 - #define half4 vec4 - #define int2 ivec2 - #define float2 vec2 - #define float3 vec3 - #define float4 vec4 - #define FxaaInt2 ivec2 - #define FxaaFloat2 vec2 - #define FxaaFloat3 vec3 - #define FxaaFloat4 vec4 - #define FxaaDiscard discard - #define FxaaDot3(a, b) dot(a, b) - #define FxaaSat(x) clamp(x, 0.0, 1.0) - #define FxaaLerp(x,y,s) mix(x,y,s) - #define FxaaTex sampler2D - #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) - #if (FXAA_FAST_PIXEL_OFFSET == 1) - #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) - #else - #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) - #endif - #if (FXAA_GATHER4_ALPHA == 1) - // use #extension GL_ARB_gpu_shader5 : enable - #define FxaaTexAlpha4(t, p, r) textureGather(t, p, 3) - #define FxaaTexOffAlpha4(t, p, o, r) textureGatherOffset(t, p, o, 3) - #endif -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_GLSL_130 == 1) - // Requires "#version 130" or better - #define half float - #define half2 vec2 - #define half3 vec3 - #define half4 vec4 - #define int2 ivec2 - #define float2 vec2 - #define float3 vec3 - #define float4 vec4 - #define FxaaInt2 ivec2 - #define FxaaFloat2 vec2 - #define FxaaFloat3 vec3 - #define FxaaFloat4 vec4 - #define FxaaDiscard discard - #define FxaaDot3(a, b) dot(a, b) - #define FxaaSat(x) clamp(x, 0.0, 1.0) - #define FxaaLerp(x,y,s) mix(x,y,s) - #define FxaaTex sampler2D - #define FxaaTexTop(t, p) textureLod(t, p, 0.0) - #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) - #if (FXAA_GATHER4_ALPHA == 1) - // use #extension GL_ARB_gpu_shader5 : enable - #define FxaaTexAlpha4(t, p, r) textureGather(t, p, 3) - #define FxaaTexOffAlpha4(t, p, o, r) textureGatherOffset(t, p, o, 3) - #endif -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) - #define int2 float2 - #define FxaaInt2 float2 - #define FxaaFloat2 float2 - #define FxaaFloat3 float3 - #define FxaaFloat4 float4 - #define FxaaDiscard clip(-1) - #define FxaaDot3(a, b) dot(a, b) - #define FxaaSat(x) saturate(x) - #define FxaaLerp(x,y,s) lerp(x,y,s) - #define FxaaTex sampler2D - #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) - #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_HLSL_4 == 1) - #define FxaaInt2 int2 - #define FxaaFloat2 float2 - #define FxaaFloat3 float3 - #define FxaaFloat4 float4 - #define FxaaDiscard clip(-1) - #define FxaaDot3(a, b) dot(a, b) - #define FxaaSat(x) saturate(x) - #define FxaaLerp(x,y,s) lerp(x,y,s) - struct FxaaTex { SamplerState smpl; Texture2D tex; }; - #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) - #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_HLSL_5 == 1) - #define FxaaInt2 int2 - #define FxaaFloat2 float2 - #define FxaaFloat3 float3 - #define FxaaFloat4 float4 - #define FxaaDiscard clip(-1) - #define FxaaDot3(a, b) dot(a, b) - #define FxaaSat(x) saturate(x) - #define FxaaLerp(x,y,s) lerp(x,y,s) - struct FxaaTex { SamplerState smpl; Texture2D tex; }; - #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) - #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) - #define FxaaTexAlpha4(t, p, r) t.tex.GatherAlpha(t.smpl, p) - #define FxaaTexOffAlpha4(t, p, o, r) t.tex.GatherAlpha(t.smpl, p, o) -#endif - - - -/*============================================================================ - - FXAA3 QUALITY - PC - -============================================================================*/ -#if (FXAA_PC == 1) -/*--------------------------------------------------------------------------*/ -float4 FxaaPixelShader( - // {xy} = center of pixel - float2 pos, - // {xyzw} = not used on FXAA3 Quality - float4 posPos, - // {rgb_} = color in linear or perceptual color space - // {___a} = luma in perceptual color space (not linear) - FxaaTex tex, - // This must be from a constant/uniform. - // {x_} = 1.0/screenWidthInPixels - // {_y} = 1.0/screenHeightInPixels - float2 rcpFrame, - // {xyzw} = not used on FXAA3 Quality - float4 rcpFrameOpt -) { -/*--------------------------------------------------------------------------*/ - float2 posM; - posM.x = pos.x; - posM.y = pos.y; - #if (FXAA_GATHER4_ALPHA == 1) - #if (FXAA_DISCARD == 0) - float4 rgbyM = FxaaTexTop(tex, posM); - #define lumaM rgbyM.w - #endif - float4 luma4A = FxaaTexAlpha4(tex, posM, rcpFrame.xy); - float4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1), rcpFrame.xy); - #if (FXAA_DISCARD == 1) - #define lumaM luma4A.w - #endif - #define lumaE luma4A.z - #define lumaS luma4A.x - #define lumaSE luma4A.y - #define lumaNW luma4B.w - #define lumaN luma4B.z - #define lumaW luma4B.x - #else - float4 rgbyM = FxaaTexTop(tex, posM); - #define lumaM rgbyM.w - float lumaS = FxaaTexOff(tex, posM, FxaaInt2( 0, 1), rcpFrame.xy).w; - float lumaE = FxaaTexOff(tex, posM, FxaaInt2( 1, 0), rcpFrame.xy).w; - float lumaN = FxaaTexOff(tex, posM, FxaaInt2( 0,-1), rcpFrame.xy).w; - float lumaW = FxaaTexOff(tex, posM, FxaaInt2(-1, 0), rcpFrame.xy).w; - #endif -/*--------------------------------------------------------------------------*/ - float maxSM = max(lumaS, lumaM); - float minSM = min(lumaS, lumaM); - float maxESM = max(lumaE, maxSM); - float minESM = min(lumaE, minSM); - float maxWN = max(lumaN, lumaW); - float minWN = min(lumaN, lumaW); - float rangeMax = max(maxWN, maxESM); - float rangeMin = min(minWN, minESM); - float rangeMaxScaled = rangeMax * FXAA_QUALITY_EDGE_THRESHOLD; - float range = rangeMax - rangeMin; - float rangeMaxClamped = max(FXAA_QUALITY_EDGE_THRESHOLD_MIN, rangeMaxScaled); - bool earlyExit = range < rangeMaxClamped; -/*--------------------------------------------------------------------------*/ - if(earlyExit) - #if (FXAA_DISCARD == 1) - FxaaDiscard; - #else - return rgbyM; - #endif -/*--------------------------------------------------------------------------*/ - #if (FXAA_GATHER4_ALPHA == 0) - float lumaNW = FxaaTexOff(tex, posM, FxaaInt2(-1,-1), rcpFrame.xy).w; - float lumaSE = FxaaTexOff(tex, posM, FxaaInt2( 1, 1), rcpFrame.xy).w; - float lumaNE = FxaaTexOff(tex, posM, FxaaInt2( 1,-1), rcpFrame.xy).w; - float lumaSW = FxaaTexOff(tex, posM, FxaaInt2(-1, 1), rcpFrame.xy).w; - #else - float lumaNE = FxaaTexOff(tex, posM, FxaaInt2(1, -1), rcpFrame.xy).w; - float lumaSW = FxaaTexOff(tex, posM, FxaaInt2(-1, 1), rcpFrame.xy).w; - #endif -/*--------------------------------------------------------------------------*/ - float lumaNS = lumaN + lumaS; - float lumaWE = lumaW + lumaE; - float subpixRcpRange = 1.0/range; - float subpixNSWE = lumaNS + lumaWE; - float edgeHorz1 = (-2.0 * lumaM) + lumaNS; - float edgeVert1 = (-2.0 * lumaM) + lumaWE; -/*--------------------------------------------------------------------------*/ - float lumaNESE = lumaNE + lumaSE; - float lumaNWNE = lumaNW + lumaNE; - float edgeHorz2 = (-2.0 * lumaE) + lumaNESE; - float edgeVert2 = (-2.0 * lumaN) + lumaNWNE; -/*--------------------------------------------------------------------------*/ - float lumaNWSW = lumaNW + lumaSW; - float lumaSWSE = lumaSW + lumaSE; - float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); - float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); - float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; - float edgeVert3 = (-2.0 * lumaS) + lumaSWSE; - float edgeHorz = abs(edgeHorz3) + edgeHorz4; - float edgeVert = abs(edgeVert3) + edgeVert4; -/*--------------------------------------------------------------------------*/ - float subpixNWSWNESE = lumaNWSW + lumaNESE; - float lengthSign = rcpFrame.x; - bool horzSpan = edgeHorz >= edgeVert; - float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; -/*--------------------------------------------------------------------------*/ - if(!horzSpan) lumaN = lumaW; - if(!horzSpan) lumaS = lumaE; - if(horzSpan) lengthSign = rcpFrame.y; - float subpixB = (subpixA * (1.0/12.0)) - lumaM; -/*--------------------------------------------------------------------------*/ - float gradientN = lumaN - lumaM; - float gradientS = lumaS - lumaM; - float lumaNN = lumaN + lumaM; - float lumaSS = lumaS + lumaM; - bool pairN = abs(gradientN) >= abs(gradientS); - float gradient = max(abs(gradientN), abs(gradientS)); - if(pairN) lengthSign = -lengthSign; - float subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); -/*--------------------------------------------------------------------------*/ - float2 posB; - posB.x = posM.x; - posB.y = posM.y; - float2 offNP; - offNP.x = (!horzSpan) ? 0.0 : rcpFrame.x; - offNP.y = ( horzSpan) ? 0.0 : rcpFrame.y; - if(!horzSpan) posB.x += lengthSign * 0.5; - if( horzSpan) posB.y += lengthSign * 0.5; -/*--------------------------------------------------------------------------*/ - float2 posN; - posN.x = posB.x - offNP.x * FXAA_QUALITY_P0; - posN.y = posB.y - offNP.y * FXAA_QUALITY_P0; - float2 posP; - posP.x = posB.x + offNP.x * FXAA_QUALITY_P0; - posP.y = posB.y + offNP.y * FXAA_QUALITY_P0; - float subpixD = ((-2.0)*subpixC) + 3.0; - float lumaEndN = FxaaTexTop(tex, posN).w; - float subpixE = subpixC * subpixC; - float lumaEndP = FxaaTexTop(tex, posP).w; -/*--------------------------------------------------------------------------*/ - if(!pairN) lumaNN = lumaSS; - float gradientScaled = gradient * 1.0/4.0; - float lumaMM = lumaM - lumaNN * 0.5; - float subpixF = subpixD * subpixE; - bool lumaMLTZero = lumaMM < 0.0; -/*--------------------------------------------------------------------------*/ - lumaEndN -= lumaNN * 0.5; - lumaEndP -= lumaNN * 0.5; - bool doneN = abs(lumaEndN) >= gradientScaled; - bool doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P1; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P1; - bool doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P1; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P1; -/*--------------------------------------------------------------------------*/ - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P2; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P2; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P2; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P2; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY_PS > 3) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P3; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P3; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P3; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P3; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY_PS > 4) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P4; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P4; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P4; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P4; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY_PS > 5) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P5; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P5; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P5; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P5; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY_PS > 6) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P6; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P6; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P6; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P6; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY_PS > 7) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P7; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P7; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P7; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P7; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY_PS > 8) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P8; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P8; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P8; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P8; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY_PS > 9) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P9; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P9; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P9; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P9; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY_PS > 10) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P10; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P10; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P10; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P10; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY_PS > 11) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P11; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P11; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P11; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P11; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY_PS > 12) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P12; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P12; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P12; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P12; -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } -/*--------------------------------------------------------------------------*/ - float dstN = posM.x - posN.x; - float dstP = posP.x - posM.x; - if(!horzSpan) dstN = posM.y - posN.y; - if(!horzSpan) dstP = posP.y - posM.y; -/*--------------------------------------------------------------------------*/ - bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; - float spanLength = (dstP + dstN); - bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; - float spanLengthRcp = 1.0/spanLength; -/*--------------------------------------------------------------------------*/ - bool directionN = dstN < dstP; - float dst = min(dstN, dstP); - bool goodSpan = directionN ? goodSpanN : goodSpanP; - float subpixG = subpixF * subpixF; - float pixelOffset = (dst * (-spanLengthRcp)) + 0.5; - float subpixH = subpixG * FXAA_QUALITY_SUBPIX; -/*--------------------------------------------------------------------------*/ - float pixelOffsetGood = goodSpan ? pixelOffset : 0.0; - float pixelOffsetSubpix = max(pixelOffsetGood, subpixH); - if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; - if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; - #if (FXAA_DISCARD == 1) - return FxaaTexTop(tex, posM); - #else - return float4(FxaaTexTop(tex, posM).xyz, lumaM); - #endif + float maxRGB; + float minRGB; + float r = color.x; + float g = color.y; + float b = color.z; + + if (r >= g) { maxRGB = r; } + if (r >= b) { maxRGB = r; } + if (g >= r) { maxRGB = g; } + if (g >= b) { maxRGB = g; } + if (b >= r) { maxRGB = b; } + if (b >= g) { maxRGB = b; } + + if (r <= g) { minRGB = r; } + if (r <= b) { minRGB = r; } + if (g <= r) { minRGB = g; } + if (g <= b) { minRGB = g; } + if (b <= r) { minRGB = b; } + if (b <= g) { minRGB = b; } + + float lumin = ((maxRGB + minRGB) / 2); + return lumin; } -/*==========================================================================*/ + +float RGBLuminance(float3 color) +{ + const float3 lumCoeff = float3(0.2126729, 0.7151522, 0.0721750); + return dot(color.rgb, lumCoeff); +} + +float RGBGammaToLinear(float color, float gamma) +{ + color = abs(color); + color = ((color <= 0.0) ? color / + 12.92 : pow((color + 0.055) / 1.055, gamma)); + + return color; +} + +float LinearToRGBGamma(float color, float gamma) +{ + color = abs(color); + color = (color <= 0.0) ? color * + 12.92 : (1.055 * pow(color, 1.0 / gamma) - 0.055); + + return color; +} + +#define PixelSize float2(_rcpFrame.x, _rcpFrame.y) +#define GammaCorrection(color, gamma) pow(color, gamma) +#define InverseGammaCorrection(color, gamma) pow(color, 1.0/gamma) + +/*------------------------------------------------------------------------------ +[VERTEX CODE SECTION] +------------------------------------------------------------------------------*/ +//Not used currently - here for testing on custom builds. +VS_OUTPUT vs_main(VS_INPUT input) +{ + VS_OUTPUT output; + + output.p = mul(input.p, worldMatrix); + output.p = mul(input.p, viewMatrix); + output.p = mul(input.p, projectionMatrix); + output.p = input.p; + output.t = input.t; + + return output; +} + +/*------------------------------------------------------------------------------ +[GAMMA PREPASS CODE SECTION] +------------------------------------------------------------------------------*/ + +float4 PreGammaPass(float4 color, float2 uv0) +{ + color = Texture.Sample(TextureSampler, uv0); + + color.r = RGBGammaToLinear(color.r, GammaConst); + color.g = RGBGammaToLinear(color.g, GammaConst); + color.b = RGBGammaToLinear(color.b, GammaConst); + + color.r = LinearToRGBGamma(color.r, GammaConst); + color.g = LinearToRGBGamma(color.g, GammaConst); + color.b = LinearToRGBGamma(color.b, GammaConst); + color.a = RGBLuminance(color.rgb); + + return color; +} + +/*------------------------------------------------------------------------------ +[FXAA CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (UHQ_FXAA == 1) +#if (SHADER_MODEL == 0x500) +#define FXAA_HLSL_5 1 +#define FXAA_GATHER4_ALPHA 1 +#elif (SHADER_MODEL == 0x400) +#define FXAA_HLSL_4 1 +#define FXAA_GATHER4_ALPHA 0 #endif -#ifdef SHADER_MODEL -PS_OUTPUT ps_main(PS_INPUT input) +#if (FxaaQuality == 4) +#define FxaaEdgeThreshold (0.033) +#define FxaaEdgeThresholdMin (0.00) +#define FXAA_QUALITY__PS 14 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 2.0 +#define FXAA_QUALITY__P9 2.0 +#define FXAA_QUALITY__P10 4.0 +#define FXAA_QUALITY__P11 8.0 +#define FXAA_QUALITY__P12 8.0 + +#elif (FxaaQuality == 3) +#define FxaaEdgeThreshold (0.125) +#define FxaaEdgeThresholdMin (0.0312) +#define FXAA_QUALITY__PS 12 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 2.0 +#define FXAA_QUALITY__P9 2.0 +#define FXAA_QUALITY__P10 4.0 +#define FXAA_QUALITY__P11 8.0 + +#elif (FxaaQuality == 2) +#define FxaaEdgeThreshold (0.166) +#define FxaaEdgeThresholdMin (0.0625) +#define FXAA_QUALITY__PS 10 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 4.0 +#define FXAA_QUALITY__P9 8.0 + +#elif (FxaaQuality == 1) +#define FxaaEdgeThreshold (0.250) +#define FxaaEdgeThresholdMin (0.0833) +#define FXAA_QUALITY__PS 8 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 4.0 +#define FXAA_QUALITY__P7 12.0 +#endif + +#if (FXAA_HLSL_5 == 1) +struct FxaaTex { SamplerState smpl; Texture2D tex; }; +#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) +#define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) +#define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) +#define FxaaDiscard clip(-1) +#define FxaaSat(x) saturate(x) + +#elif (FXAA_HLSL_4 == 1) +struct FxaaTex { SamplerState smpl; Texture2D tex; }; +#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) +#define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#define FxaaDiscard clip(-1) +#define FxaaSat(x) saturate(x) +#endif + +float FxaaLuma(float4 rgba) { - PS_OUTPUT output; + rgba.w = RGBLuminance(rgba.xyz); + return rgba.w; +} - float2 pos = input.t; - float4 posPos = (float4)0; +float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaSubpix, float fxaaEdgeThreshold, float fxaaEdgeThresholdMin) +{ + float2 posM; + posM.x = pos.x; + posM.y = pos.y; +#if (FXAA_GATHER4_ALPHA == 1) + float4 rgbyM = FxaaTexTop(tex, posM); + float4 luma4A = FxaaTexAlpha4(tex, posM); + float4 luma4B = FxaaTexOffAlpha4(tex, posM, int2(-1, -1)); + rgbyM.w = RGBLuminance(rgbyM.xyz); + +#define lumaM rgbyM.w +#define lumaE luma4A.z +#define lumaS luma4A.x +#define lumaSE luma4A.y +#define lumaNW luma4B.w +#define lumaN luma4B.z +#define lumaW luma4B.x +#else + + float4 rgbyM = FxaaTexTop(tex, posM); + rgbyM.w = RGBLuminance(rgbyM.xyz); +#define lumaM rgbyM.w + + float lumaS = FxaaLuma(FxaaTexOff(tex, posM, int2(0, 1), fxaaRcpFrame.xy)); + float lumaE = FxaaLuma(FxaaTexOff(tex, posM, int2(1, 0), fxaaRcpFrame.xy)); + float lumaN = FxaaLuma(FxaaTexOff(tex, posM, int2(0, -1), fxaaRcpFrame.xy)); + float lumaW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 0), fxaaRcpFrame.xy)); +#endif + + float maxSM = max(lumaS, lumaM); + float minSM = min(lumaS, lumaM); + float maxESM = max(lumaE, maxSM); + float minESM = min(lumaE, minSM); + float maxWN = max(lumaN, lumaW); + float minWN = min(lumaN, lumaW); + float rangeMax = max(maxWN, maxESM); + float rangeMin = min(minWN, minESM); + float rangeMaxScaled = rangeMax * fxaaEdgeThreshold; + float range = rangeMax - rangeMin; + float rangeMaxClamped = max(fxaaEdgeThresholdMin, rangeMaxScaled); + bool earlyExit = range < rangeMaxClamped; + +#if (FxaaEarlyExit == 1) + if (earlyExit) + { + return rgbyM; + } +#endif + +#if (FXAA_GATHER4_ALPHA == 0) + float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, -1), fxaaRcpFrame.xy)); + float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, int2(1, 1), fxaaRcpFrame.xy)); + float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, int2(1, -1), fxaaRcpFrame.xy)); + float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 1), fxaaRcpFrame.xy)); +#else + float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, int2(1, -1), fxaaRcpFrame.xy)); + float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 1), fxaaRcpFrame.xy)); +#endif + + float lumaNS = lumaN + lumaS; + float lumaWE = lumaW + lumaE; + float subpixRcpRange = 1.0 / range; + float subpixNSWE = lumaNS + lumaWE; + float edgeHorz1 = (-2.0 * lumaM) + lumaNS; + float edgeVert1 = (-2.0 * lumaM) + lumaWE; + + float lumaNESE = lumaNE + lumaSE; + float lumaNWNE = lumaNW + lumaNE; + float edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + float edgeVert2 = (-2.0 * lumaN) + lumaNWNE; + + float lumaNWSW = lumaNW + lumaSW; + float lumaSWSE = lumaSW + lumaSE; + float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + float edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + float edgeHorz = abs(edgeHorz3) + edgeHorz4; + float edgeVert = abs(edgeVert3) + edgeVert4; + + float subpixNWSWNESE = lumaNWSW + lumaNESE; + float lengthSign = fxaaRcpFrame.x; + bool horzSpan = edgeHorz >= edgeVert; + float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; + + if (!horzSpan) lumaN = lumaW; + if (!horzSpan) lumaS = lumaE; + if (horzSpan) lengthSign = fxaaRcpFrame.y; + float subpixB = (subpixA * (1.0 / 12.0)) - lumaM; + + float gradientN = lumaN - lumaM; + float gradientS = lumaS - lumaM; + float lumaNN = lumaN + lumaM; + float lumaSS = lumaS + lumaM; + bool pairN = abs(gradientN) >= abs(gradientS); + float gradient = max(abs(gradientN), abs(gradientS)); + if (pairN) lengthSign = -lengthSign; + float subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); + + float2 posB; + posB.x = posM.x; + posB.y = posM.y; + float2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaRcpFrame.x; + offNP.y = (horzSpan) ? 0.0 : fxaaRcpFrame.y; + if (!horzSpan) posB.x += lengthSign * 0.5; + if (horzSpan) posB.y += lengthSign * 0.5; + + float2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + float2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + float subpixD = ((-2.0)*subpixC) + 3.0; + float lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + float subpixE = subpixC * subpixC; + float lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); + + if (!pairN) lumaNN = lumaSS; + float gradientScaled = gradient * 1.0 / 4.0; + float lumaMM = lumaM - lumaNN * 0.5; + float subpixF = subpixD * subpixE; + bool lumaMLTZero = lumaMM < 0.0; + + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + bool doneN = abs(lumaEndN) >= gradientScaled; + bool doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; + bool doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; + + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; + +#if (FXAA_QUALITY__PS > 3) + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; + +#if (FXAA_QUALITY__PS > 4) + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; + +#if (FXAA_QUALITY__PS > 5) + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; + +#if (FXAA_QUALITY__PS > 6) + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; + +#if (FXAA_QUALITY__PS > 7) + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; + +#if (FXAA_QUALITY__PS > 8) + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; + +#if (FXAA_QUALITY__PS > 9) + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; + +#if (FXAA_QUALITY__PS > 10) + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; + +#if (FXAA_QUALITY__PS > 11) + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; + +#if (FXAA_QUALITY__PS > 12) + if (doneNP) { + if (!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if (!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if (!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; + } +#endif + } +#endif + } +#endif + } +#endif + } +#endif + } +#endif + } +#endif + } +#endif + } +#endif + } +#endif + } + + float dstN = posM.x - posN.x; + float dstP = posP.x - posM.x; + if (!horzSpan) dstN = posM.y - posN.y; + if (!horzSpan) dstP = posP.y - posM.y; + + bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + float spanLength = (dstP + dstN); + bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + float spanLengthRcp = 1.0 / spanLength; + + bool directionN = dstN < dstP; + float dst = min(dstN, dstP); + bool goodSpan = directionN ? goodSpanN : goodSpanP; + float subpixG = subpixF * subpixF; + float pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + float subpixH = subpixG * fxaaSubpix; + + float pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + float pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if (!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if (horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + + return float4(FxaaTexTop(tex, posM).xyz, lumaM); +} + +float4 FxaaPass(float4 FxaaColor : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ FxaaTex tex; - - #if SHADER_MODEL >= 0x400 - tex.tex = Texture; tex.smpl = TextureSampler; - #else + Texture.GetDimensions(PixelSize.x, PixelSize.y); - tex = Texture; + FxaaColor = FxaaPixelShader(uv0, tex, 1.0 / PixelSize.xy, FxaaSubpixMax, FxaaEdgeThreshold, FxaaEdgeThresholdMin); - #endif + return FxaaColor; +} +#endif - output.c = FxaaPixelShader(pos, posPos, tex, _rcpFrame.xy, _rcpFrameOpt); +/*------------------------------------------------------------------------------ +[TEXTURE FILTERING FUNCTIONS] +------------------------------------------------------------------------------*/ + +float BSpline(float x) +{ + float f = x; + + if (f < 0.0) + { + f = -f; + } + if (f >= 0.0 && f <= 1.0) + { + return (2.0 / 3.0) + (0.5) * (f* f * f) - (f*f); + } + else if (f > 1.0 && f <= 2.0) + { + return 1.0 / 6.0 * pow((2.0 - f), 3.0); + } + return 1.0; +} + +float CatMullRom(float x) +{ + float b = 0.0; + float c = 0.5; + float f = x; + + if (f < 0.0) + { + f = -f; + } + if (f < 1.0) + { + return ((12.0 - 9.0 * b - 6.0 * c) * (f * f * f) + + (-18.0 + 12.0 * b + 6.0 * c) * (f * f) + + (6.0 - 2.0 * b)) / 6.0; + } + else if (f >= 1.0 && f < 2.0) + { + return ((-b - 6.0 * c) * (f * f * f) + + (6.0 * b + 30.0 * c) * (f *f) + + (-(12.0 * b) - 48.0 * c) * f + + 8.0 * b + 24.0 * c) / 6.0; + } + else + { + return 0.0; + } +} + +float Bell(float x) +{ + float f = (x / 2.0) * 1.5; + + if (f > -1.5 && f < -0.5) + { + return(0.5 * pow(f + 1.5, 2.0)); + } + else if (f > -0.5 && f < 0.5) + { + return 3.0 / 4.0 - (f * f); + } + else if ((f > 0.5 && f < 1.5)) + { + return(0.5 * pow(f - 1.5, 2.0)); + } + return 0.0; +} + +float Triangular(float x) +{ + x = x / 2.0; + + if (x < 0.0) + { + return (x + 1.0); + } + else + { + return (1.0 - x); + } + return 0.0; +} + +float Cubic(float x) +{ + float x2 = x * x; + float x3 = x2 * x; + + float4 c; + c.x = -x3 + 3.0 * x2 - 3.0 * x + 1.0; + c.y = 3.0 * x3 - 6.0 * x2 + 4.0; + c.z = -3.0 * x3 + 3.0 * x2 + 3.0 * x + 1.0; + c.w = x3; + + float f = (lerp(c.x, c.y, 0.5) + lerp(c.z, c.w, 0.5)) / 6.0; + //float f = (c.x + c.y + c.z + c.w) / 6.0; + + return f; +} + +/*------------------------------------------------------------------------------ +[BICUBIC FILTERING CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (BICUBIC_FILTERING == 1) +float4 BiCubicFilter(SamplerState texSample, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + Texture.GetDimensions(PixelSize.x, PixelSize.y); + + float texelSizeX = 1.0 / PixelSize.x; + float texelSizeY = 1.0 / PixelSize.y; + + float4 nSum = (float4)0.0; + float4 nDenom = (float4)0.0; + + float a = frac(uv0.x * PixelSize.x); + float b = frac(uv0.y * PixelSize.y); + + int nX = int(uv0.x * PixelSize.x); + int nY = int(uv0.y * PixelSize.y); + + float2 TexCoord1 = float2(float(nX) / PixelSize.x + PixelOffset / PixelSize.x, + float(nY) / PixelSize.y + PixelOffset / PixelSize.y); + + for (int m = -1; m <= 2; m++) + { + for (int n = -1; n <= 2; n++) + { + float4 Samples = Texture.Sample(texSample, TexCoord1 + + float2(texelSizeX * float(m), texelSizeY * float(n))); + + float vc1 = Interpolation(float(m) - a); + float4 vecCoeff1 = float4(vc1, vc1, vc1, vc1); + + float vc2 = Interpolation(-(float(n) - b)); + float4 vecCoeff2 = float4(vc2, vc2, vc2, vc2); + + nSum = nSum + (Samples * vecCoeff2 * vecCoeff1); + nDenom = nDenom + (vecCoeff2 * vecCoeff1); + } + } + return nSum / nDenom; +} + +float4 BiCubicPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + color = BiCubicFilter(TextureSampler, uv0); + return color; +} +#endif + +/*------------------------------------------------------------------------------ +[BILINEAR FILTERING CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (BILINEAR_FILTERING == 1) +float4 SampleBiLinear(SamplerState texSample, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + Texture.GetDimensions(PixelSize.x, PixelSize.y); + + float texelSizeX = 1.0 / PixelSize.x; + float texelSizeY = 1.0 / PixelSize.y; + + int nX = int(uv0.x * PixelSize.x); + int nY = int(uv0.y * PixelSize.y); + + float2 texCoord_New = float2((float(nX) + OffsetAmount) / PixelSize.x, + (float(nY) + OffsetAmount) / PixelSize.y); + // Take nearest two data in current row. + float4 SampleA = Texture.Sample(texSample, texCoord_New); + float4 SampleB = Texture.Sample(texSample, texCoord_New + float2(texelSizeX, 0.0)); + + // Take nearest two data in bottom row. + float4 SampleC = Texture.Sample(texSample, texCoord_New + float2(0.0, texelSizeY)); + float4 SampleD = Texture.Sample(texSample, texCoord_New + float2(texelSizeX, texelSizeY)); + + float LX = frac(uv0.x * PixelSize.x); //Get Interpolation factor for X direction. + + // Interpolate in X direction. + float4 InterpolateA = lerp(SampleA, SampleB, LX); //Top row in X direction. + float4 InterpolateB = lerp(SampleC, SampleD, LX); //Bottom row in X direction. + + float LY = frac(uv0.y * PixelSize.y); //Get Interpolation factor for Y direction. + + return lerp(InterpolateA, InterpolateB, LY); //Interpolate in Y direction. +} + +float4 BiLinearPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) +{ + float4 bilinear = SampleBiLinear(TextureSampler, uv0); + color = lerp(color, bilinear, FilterStrength); + + return color; +} +#endif + +/*------------------------------------------------------------------------------ +[GAUSSIAN FILTERING CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (GAUSSIAN_FILTERING == 1) +float4 GaussianPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + Texture.GetDimensions(PixelSize.x, PixelSize.y); + + float2 dx = float2(1.0 / PixelSize.x * GaussianSpread, 0.0); + float2 dy = float2(0.0, 1.0 / PixelSize.y * GaussianSpread); + + float2 dx2 = 2.0 * dx; + float2 dy2 = 2.0 * dy; + + float4 gaussian = Texture.Sample(TextureSampler, uv0); + + gaussian += Texture.Sample(TextureSampler, uv0 - dx2 + dy2); + gaussian += Texture.Sample(TextureSampler, uv0 - dx + dy2); + gaussian += Texture.Sample(TextureSampler, uv0 + dy2); + gaussian += Texture.Sample(TextureSampler, uv0 + dx + dy2); + gaussian += Texture.Sample(TextureSampler, uv0 + dx2 + dy2); + + gaussian += Texture.Sample(TextureSampler, uv0 - dx2 + dy); + gaussian += Texture.Sample(TextureSampler, uv0 - dx + dy); + gaussian += Texture.Sample(TextureSampler, uv0 + dy); + gaussian += Texture.Sample(TextureSampler, uv0 + dx + dy); + gaussian += Texture.Sample(TextureSampler, uv0 + dx2 + dy); + + gaussian += Texture.Sample(TextureSampler, uv0 - dx2); + gaussian += Texture.Sample(TextureSampler, uv0 - dx); + gaussian += Texture.Sample(TextureSampler, uv0 + dx); + gaussian += Texture.Sample(TextureSampler, uv0 + dx2); + + gaussian += Texture.Sample(TextureSampler, uv0 - dx2 - dy); + gaussian += Texture.Sample(TextureSampler, uv0 - dx - dy); + gaussian += Texture.Sample(TextureSampler, uv0 - dy); + gaussian += Texture.Sample(TextureSampler, uv0 + dx - dy); + gaussian += Texture.Sample(TextureSampler, uv0 + dx2 - dy); + + gaussian += Texture.Sample(TextureSampler, uv0 - dx2 - dy2); + gaussian += Texture.Sample(TextureSampler, uv0 - dx - dy2); + gaussian += Texture.Sample(TextureSampler, uv0 - dy2); + gaussian += Texture.Sample(TextureSampler, uv0 + dx - dy2); + gaussian += Texture.Sample(TextureSampler, uv0 + dx2 - dy2); + + gaussian /= 25.0; + + color = lerp(color, gaussian, FilterAmount); + + return color; +} +#endif + +/*------------------------------------------------------------------------------ +[GAMMA CORRECTION CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (GAMMA_CORRECTION == 1) +float4 PostGammaPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + color.r = RGBGammaToLinear(color.r, GammaConst); + color.g = RGBGammaToLinear(color.g, GammaConst); + color.b = RGBGammaToLinear(color.b, GammaConst); + + color.r = LinearToRGBGamma(color.r, Gamma); + color.g = LinearToRGBGamma(color.g, Gamma); + color.b = LinearToRGBGamma(color.b, Gamma); + + color.a = RGBLuminance(color.rgb); + + return color; +} +#endif + +/*------------------------------------------------------------------------------ +[TEXTURE SHARPEN CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (TEXTURE_SHARPENING == 1) +#define px 1.0 / PixelSize.x +#define py 1.0 / PixelSize.y +#define SharpenLumCoeff float3(0.2126729, 0.7151522, 0.0721750) + +#if(SharpeningType == 2) +float4 SampleBiCubic(SamplerState texSample, float2 uv0) +{ + Texture.GetDimensions(PixelSize.x, PixelSize.y); + + float texelSizeX = 1.0 / PixelSize.x * SharpenBias; + float texelSizeY = 1.0 / PixelSize.y * SharpenBias; + + float4 nSum = (float4)0.0; + float4 nDenom = (float4)0.0; + + float a = frac(uv0.x * PixelSize.x); + float b = frac(uv0.y * PixelSize.y); + + int nX = int(uv0.x * PixelSize.x); + int nY = int(uv0.y * PixelSize.y); + + float2 uv1 = float2(float(nX) / PixelSize.x, float(nY) / PixelSize.y); + + for (int m = -1; m <= 2; m++) + { + for (int n = -1; n <= 2; n++) + { + float4 Samples = Texture.Sample(texSample, uv1 + + float2(texelSizeX * float(m), texelSizeY * float(n))); + + float vc1 = Cubic(float(m) - a); + float4 vecCoeff1 = float4(vc1, vc1, vc1, vc1); + + float vc2 = Cubic(-(float(n) - b)); + float4 vecCoeff2 = float4(vc2, vc2, vc2, vc2); + + nSum = nSum + (Samples * vecCoeff2 * vecCoeff1); + nDenom = nDenom + (vecCoeff2 * vecCoeff1); + } + } + return nSum / nDenom; +} + +float4 TexSharpenPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + float3 calcSharpen = (SharpenLumCoeff * SharpenStrength); + + float4 blurredColor = SampleBiCubic(TextureSampler, uv0); + float3 sharpenedColor = (color.rgb - blurredColor.rgb); + + float sharpenLuma = dot(sharpenedColor, calcSharpen); + sharpenLuma = clamp(sharpenLuma, -SharpenClamp, SharpenClamp); + + color.rgb = color.rgb + sharpenLuma; + color.a = RGBLuminance(color.rgb); + +#if (DebugSharpen == 1) + color = saturate(0.5f + (sharpenLuma * 4)).rrrr; //visualise sharpening (for debugging) +#endif + + return saturate(color); +} +#else + +float4 TexSharpenPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + float3 blurredColor; + + Texture.GetDimensions(PixelSize.x, PixelSize.y); + + blurredColor = Texture.SampleLevel(TextureSampler, uv0 + float2(-px, py) * SharpenBias, 0.0).rgb; //North West + blurredColor += Texture.SampleLevel(TextureSampler, uv0 + float2(px, -py) * SharpenBias, 0.0).rgb; //South East + blurredColor += Texture.SampleLevel(TextureSampler, uv0 + float2(-px, -py) * SharpenBias, 0.0).rgb; //South West + blurredColor += Texture.SampleLevel(TextureSampler, uv0 + float2(px, py) * SharpenBias, 0.0).rgb; //North East + + blurredColor += Texture.SampleLevel(TextureSampler, uv0 + float2(0.0, py) * SharpenBias, 0.0).rgb; //North + blurredColor += Texture.SampleLevel(TextureSampler, uv0 + float2(0.0, -py) * SharpenBias, 0.0).rgb; //South + blurredColor += Texture.SampleLevel(TextureSampler, uv0 + float2(-px, 0.0) * SharpenBias, 0.0).rgb; //West + blurredColor += Texture.SampleLevel(TextureSampler, uv0 + float2(px, 0.0) * SharpenBias, 0.0).rgb; //East + + blurredColor /= 8.0; + + float3 sharpenedColor = color.rgb - blurredColor; + float3 calcSharpen = (SharpenLumCoeff * SharpenStrength); + + float sharpenLuma = dot(sharpenedColor, calcSharpen); + sharpenLuma = clamp(sharpenLuma, -SharpenClamp, SharpenClamp); + + color.rgb = color.rgb + sharpenLuma; + color.a = RGBLuminance(color.rgb); + +#if (DebugSharpen == 1) + color = saturate(0.5f + (sharpenLuma * 4)).rrrr; //visualise sharpening (for debugging) +#endif + + return saturate(color); +} +#endif +#endif + +/*------------------------------------------------------------------------------ +[VIBRANCE CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (PIXEL_VIBRANCE == 1) +float4 VibrancePass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + float luma = RGBLuminance(color.rgb); + + float colorMax = max(color.r, max(color.g, color.b)); + float colorMin = min(color.r, min(color.g, color.b)); + + float colorSaturation = colorMax - colorMin; + + color.rgb = lerp(luma, color.rgb, (1.0 + (Vibrance * (1.0 - (sign(Vibrance) * colorSaturation))))); + color.a = RGBLuminance(color.rgb); + + return saturate(color); //Debug: return colorSaturation.xxxx; +} +#endif + +/*------------------------------------------------------------------------------ +[BLOOM PASS CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (BLENDED_BLOOM == 1) +float3 BlendScreen(float3 color, float3 bloom) +{ + return (color + bloom) - (color * bloom); +} + +float3 BlendAddLight(float3 color, float3 bloom) +{ + return color + bloom; +} + +float3 BlendOverlay(float3 color, float3 bloom) +{ + return float3((bloom.x <= 0.5) ? (2.0 * color.x * bloom.x) + : (1.0 - 2.0 * (1.0 - bloom.x) * (1.0 - color.x)), + (bloom.y <= 0.5) ? (2.0 * color.y * bloom.y) + : (1.0 - 2.0 * (1.0 - bloom.y) * (1.0 - color.y)), + (bloom.z <= 0.5) ? (2.0 * color.z * bloom.z) + : (1.0 - 2.0 * (1.0 - bloom.z) * (1.0 - color.z))); +} + +float4 BloomPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + float4 bloom; + + float2 dx = float2(1.0 / PixelSize.x * BlendSpread, 0.0); + float2 dy = float2(0.0, 1.0 / PixelSize.y * BlendSpread); + + float2 dx2 = 2.0 * dx; + float2 dy2 = 2.0 * dy; + + float4 bloomBlend = color * 0.22520613262190495; + + bloomBlend += 0.002589001911021066 * Texture.Sample(TextureSampler, uv0 - dx2 + dy2); + bloomBlend += 0.010778807494659370 * Texture.Sample(TextureSampler, uv0 - dx + dy2); + bloomBlend += 0.024146616900339800 * Texture.Sample(TextureSampler, uv0 + dy2); + bloomBlend += 0.010778807494659370 * Texture.Sample(TextureSampler, uv0 + dx + dy2); + bloomBlend += 0.002589001911021066 * Texture.Sample(TextureSampler, uv0 + dx2 + dy2); + + bloomBlend += 0.010778807494659370 * Texture.Sample(TextureSampler, uv0 - dx2 + dy); + bloomBlend += 0.044875475183061630 * Texture.Sample(TextureSampler, uv0 - dx + dy); + bloomBlend += 0.100529757860782610 * Texture.Sample(TextureSampler, uv0 + dy); + bloomBlend += 0.044875475183061630 * Texture.Sample(TextureSampler, uv0 + dx + dy); + bloomBlend += 0.010778807494659370 * Texture.Sample(TextureSampler, uv0 + dx2 + dy); + + bloomBlend += 0.024146616900339800 * Texture.Sample(TextureSampler, uv0 - dx2); + bloomBlend += 0.100529757860782610 * Texture.Sample(TextureSampler, uv0 - dx); + bloomBlend += 0.100529757860782610 * Texture.Sample(TextureSampler, uv0 + dx); + bloomBlend += 0.024146616900339800 * Texture.Sample(TextureSampler, uv0 + dx2); + + bloomBlend += 0.010778807494659370 * Texture.Sample(TextureSampler, uv0 - dx2 - dy); + bloomBlend += 0.044875475183061630 * Texture.Sample(TextureSampler, uv0 - dx - dy); + bloomBlend += 0.100529757860782610 * Texture.Sample(TextureSampler, uv0 - dy); + bloomBlend += 0.044875475183061630 * Texture.Sample(TextureSampler, uv0 + dx - dy); + bloomBlend += 0.010778807494659370 * Texture.Sample(TextureSampler, uv0 + dx2 - dy); + + bloomBlend += 0.002589001911021066 * Texture.Sample(TextureSampler, uv0 - dx2 - dy2); + bloomBlend += 0.010778807494659370 * Texture.Sample(TextureSampler, uv0 - dx - dy2); + bloomBlend += 0.024146616900339800 * Texture.Sample(TextureSampler, uv0 - dy2); + bloomBlend += 0.010778807494659370 * Texture.Sample(TextureSampler, uv0 + dx - dy2); + bloomBlend += 0.002589001911021066 * Texture.Sample(TextureSampler, uv0 + dx2 - dy2); + + bloomBlend = lerp(color, bloomBlend, BlendPower); + bloom.rgb = BloomType(color.rgb, bloomBlend.rgb); + + bloom.r = bloom.r * 1.010778807494659370; + color.a = RGBLuminance(color.rgb); + bloom.a = RGBLuminance(bloom.rgb); + +#if (BloomMixType == 1) + color = lerp(color, bloom, BloomPower); +#elif (BloomMixType == 2) + color = (lerp(color, bloom, BloomPower) + lerp(bloom, bloomBlend, BloomPower)) / 2.0; +#elif (BloomMixType == 3) + color = lerp(color, bloom, lerp(color.a * 0.5, bloom.a, BloomPower)); +#endif + + return saturate(color); +} +#endif + +/*------------------------------------------------------------------------------ +[COLOR CORRECTION/TONE MAPPING PASS CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (SCENE_TONEMAPPING == 1) +float YXYLuminance(float3 YXY) +{ + return (-0.9692660 * YXY.x) + + (1.8760108 * YXY.y) + + (0.0415560 * YXY.z); +} + +float3 FilmicTonemap(float3 x) +{ + float A = 0.10; + float B = 0.36; + float C = 0.10; + float D = 0.30; + float E = 0.02; + float F = 0.30; + + return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F; +} + +float3 ColorCorrection(float3 color) +{ + float X = 1.0 / (1.0 + exp(RedCurve / 2.0)); + float Y = 1.0 / (1.0 + exp(GreenCurve / 2.0)); + float Z = 1.0 / (1.0 + exp(BlueCurve / 2.0)); + + color.r = (1.0 / (1.0 + exp(-RedCurve + * (color.r - 0.5))) - X) / (1.0 - 2.0 * X); + color.g = (1.0 / (1.0 + exp(-GreenCurve + * (color.g - 0.5))) - Y) / (1.0 - 2.0 * Y); + color.b = (1.0 / (1.0 + exp(-BlueCurve + * (color.b - 0.5))) - Z) / (1.0 - 2.0 * Z); + + return color; +} + +float4 TonemapPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + float3 luminanceFactor = 1.0 / FilmicTonemap(Luminance); + + color.rgb = ColorCorrection(color.rgb); + color.rgb = FilmicTonemap(Exposure * color.rgb); + color.rgb = color.rgb * luminanceFactor; + + color.r = RGBGammaToLinear(color.r, GammaConst); + color.g = RGBGammaToLinear(color.g, GammaConst); + color.b = RGBGammaToLinear(color.b, GammaConst); + +#if (TonemapType == 1) + color.r = LinearToRGBGamma(color.r, ToneAmount); + color.g = LinearToRGBGamma(color.g, ToneAmount); + color.b = LinearToRGBGamma(color.b, ToneAmount); +#else + color.r = LinearToRGBGamma(color.r, GammaConst); + color.g = LinearToRGBGamma(color.g, GammaConst); + color.b = LinearToRGBGamma(color.b, GammaConst); +#endif + + float3 lumCoeff = float3(0.2126729, 0.7151522, 0.0721750); + + // RGB -> XYZ conversion + const float3x3 RGB2XYZ = { 0.4124564, 0.3575761, 0.1804375, + 0.2126729, 0.7151522, 0.0721750, + 0.0193339, 0.1191920, 0.9503041 }; + + float3 XYZ = mul(RGB2XYZ, color.rgb); + + // XYZ -> Yxy conversion + float3 Yxy = lumCoeff; + + Yxy.r = XYZ.g; // copy luminance Y + Yxy.g = XYZ.r / (XYZ.r + XYZ.g + XYZ.b); // x = X / (X + Y + Z) + Yxy.b = XYZ.g / (XYZ.r + XYZ.g + XYZ.b); // y = Y / (X + Y + Z) + + // (Lp) Map average luminance to the middlegrey zone by scaling pixel luminance +#if (TonemapType == 1) + float Lp = Yxy.r * Exposure / Luminance; + +#elif (TonemapType == 2) + float Lp = ((Yxy.r * (YXYLuminance(Yxy.rrr) / 1.5)) + (Yxy.g * (YXYLuminance(Yxy.rrr) / 1.5)) + + (Yxy.b *(YXYLuminance(Yxy.rrr) / 1.5))) * ((Exposure / Luminance) * (ToneAmount / 2.2)); +#endif + + // (Ld) Scale all luminance within a displayable range of 0 to 1 + Yxy.r = (Lp * (1.0 + Lp / (WhitePoint * WhitePoint))) / (1.0 + Lp); + + // Yxy -> XYZ conversion + XYZ.r = Yxy.r * Yxy.g / Yxy.b; // X = Y * x / y + XYZ.g = Yxy.r; // copy luminance Y + XYZ.b = Yxy.r * (1.0 - Yxy.g - Yxy.b) / Yxy.b; // Z = Y * (1-x-y) / y + + // XYZ -> RGB conversion + const float3x3 XYZ2RGB = { 3.2404542, -1.5371385, -0.4985314, + -0.9692660, 1.8760108, 0.0415560, + 0.0556434, -0.2040259, 1.0572252 }; + + color.rgb = mul(XYZ2RGB, XYZ); + color.a = RGBLuminance(color.rgb); + + return saturate(color); +} +#endif + +/*------------------------------------------------------------------------------ +[S-CURVE CONTRAST CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (S_CURVE_CONTRAST == 1) +float4 SCurvePass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + float CurveBlend = CurvesContrast; + +#if (CurveType != 2) + float luma = RGBLuminance(color.rgb); + float3 chroma = color.rgb - luma; +#endif + +#if (CurveType == 2) + float3 x = color.rgb; +#elif (CurveType == 1) + float3 x = chroma; + x = x * 0.5 + 0.5; +#else + float x = luma; +#endif + + // -- Curve 1 -- Cubic Bezier spline +#if (CurvesFormula == 1) + float3 a = float3(0.00, 0.00, 0.00); //start point + float3 b = float3(0.25, 0.15, 0.85); //control point 1 + float3 c = float3(0.80, 0.85, 0.15); //control point 2 + float3 d = float3(1.00, 1.00, 1.00); //endpoint + + float3 ab = lerp(a, b, x); // point between a and b (green) + float3 bc = lerp(b, c, x); // point between b and c (green) + float3 cd = lerp(c, d, x); // point between c and d (green) + float3 abbc = lerp(ab, bc, x); // point between ab and bc (blue) + float3 bccd = lerp(bc, cd, x); // point between bc and cd (blue) + float3 dest = lerp(abbc, bccd, x); // point on the bezier-curve (black) + x = dest; +#endif + + // -- Curve 2 -- Cubic Bezier spline II +#if (CurvesFormula == 2) + float a = 0.00; //start point + float b = 0.00; //control point 1 + float c = 1.00; //control point 2 + float d = 1.00; //endpoint + + float r = (1 - x); + float r2 = r*r; + float r3 = r2 * r; + float x2 = x*x; + float x3 = x2*x; + + x = a*(1 - x)*(1 - x)*(1 - x) + 3 * b*(1 - x)*(1 - x)*x + 3 * c*(1 - x)*x*x + d*x*x*x; +#endif + +#if (CurveType == 0) //Only Luma + x = lerp(luma, x, CurveBlend); + color.rgb = x + chroma; +#elif (CurveType == 1) //Only Chroma + x = x * 2 - 1; + float3 LColor = luma + x; + color.rgb = lerp(color.rgb, LColor, CurveBlend); +#elif (CurveType == 2) //Both Luma and Chroma + float3 LColor = x; + color.rgb = lerp(color.rgb, LColor, CurveBlend); +#endif + + color.a = RGBLuminance(color.rgb); + + return saturate(color); +} +#endif + +/*------------------------------------------------------------------------------ +[CEL SHADING CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (CEL_SHADING == 1) +#define RoundingOffset float2(0.20, 0.40) + +static const int NUM = 9; +static const float3 thresholds = float3(5.0, 8.0, 6.0); + +#if (LumaConversion == 1) +#define celLumaCoef float3(0.2126729, 0.7151522, 0.0721750) +#else +#define celLumaCoef float3(0.299, 0.587, 0.114) +#endif + +float3 GetYUV(float3 rgb) +{ +#if (LumaConversion == 1) + float3x3 RGB2YUV = { 0.2126, 0.7152, 0.0722, + -0.09991, -0.33609, 0.436, + 0.615, -0.55861, -0.05639 }; + +#else + float3x3 RGB2YUV = { 0.299, 0.587, 0.114, + -0.14713, -0.28886f, 0.436, + 0.615, -0.51499, -0.10001 }; +#endif + + return mul(RGB2YUV, rgb); +} + +float3 GetRGB(float3 yuv) +{ +#if (LumaConversion == 1) + float3x3 YUV2RGB = { 1.000, 0.000, 1.28033, + 1.000, -0.21482, -0.38059, + 1.000, 2.12798, 0.000 }; + +#else + float3x3 YUV2RGB = { 1.000, 0.000, 1.13983, + 1.000, -0.39465, -0.58060, + 1.000, 2.03211, 0.000 }; +#endif + + return mul(YUV2RGB, yuv); +} + +float GetCelLuminance(float3 rgb) +{ + return dot(rgb, celLumaCoef); +} + +float4 CelPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + float3 yuv; + float3 sum = color.rgb; + + float2 pixel = float2(1.0 / 2560.0, 1.0 / 1440.0) * EdgeThickness; + + float2 c[NUM] = { + float2(-0.0078125, -0.0078125), + float2(0.00, -0.0078125), + float2(0.0078125, -0.0078125), + float2(-0.0078125, 0.00), + float2(0.00, 0.00), + float2(0.0078125, 0.00), + float2(-0.0078125, 0.0078125), + float2(0.00, 0.0078125), + float2(0.0078125, 0.0078125) }; + + float3 col[NUM]; + float lum[NUM]; + + for (int i = 0; i < NUM; i++) + { + col[i] = Texture.Sample(TextureSampler, uv0 + c[i] * RoundingOffset).rgb; + +#if (ColorRounding == 1) + col[i].r = saturate(round(col[i].r * thresholds.r) / thresholds.r); + col[i].g = saturate(round(col[i].g * thresholds.g) / thresholds.g); + col[i].b = saturate(round(col[i].b * thresholds.b) / thresholds.b); +#endif + + lum[i] = GetCelLuminance(col[i].xyz); + + yuv = GetYUV(col[i]); + + if (UseYuvLuma == 0) + { + yuv.r = saturate(round(yuv.r * lum[i]) / thresholds.r + lum[i]); + } + else + { + yuv.r = saturate(round(yuv.r * thresholds.r) / thresholds.r + lum[i] / (255.0 / 5.0)); + } + + yuv = GetRGB(yuv); + + sum += yuv; + } + + float3 shadedColor = (sum / NUM); + + float edgeX = dot(Texture.Sample(TextureSampler, uv0 + pixel).rgb, celLumaCoef); + edgeX = dot(float4(Texture.Sample(TextureSampler, uv0 - pixel).rgb, edgeX), float4(celLumaCoef, -1.0)); + + float edgeY = dot(Texture.Sample(TextureSampler, uv0 + float2(pixel.x, -pixel.y)).rgb, celLumaCoef); + edgeY = dot(float4(Texture.Sample(TextureSampler, uv0 + float2(-pixel.x, pixel.y)).rgb, edgeY), float4(celLumaCoef, -1.0)); + + float edge = dot(float2(edgeX, edgeY), float2(edgeX, edgeY)); + +#if (PaletteType == 1) + color.rgb = lerp(color.rgb, color.rgb + pow(edge, EdgeFilter) * -EdgeStrength, EdgeStrength); +#elif (PaletteType == 2) + color.rgb = lerp(color.rgb + pow(edge, EdgeFilter) * -EdgeStrength, shadedColor, 0.33); +#elif (PaletteType == 3) + color.rgb = lerp(shadedColor + edge * -EdgeStrength, pow(edge, EdgeFilter) * -EdgeStrength + color.rgb, 0.5); +#endif + + color.a = RGBLuminance(color.rgb); + + return saturate(color); +} +#endif + +/*------------------------------------------------------------------------------ +[COLOR GRADING CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (COLOR_GRADING == 1) +float RGBCVtoHUE(float3 RGB, float C, float V) +{ + float3 Delta = (V - RGB) / C; + + Delta.rgb -= Delta.brg; + Delta.rgb += float3(2, 4, 6); + Delta.brg = step(V, RGB) * Delta.brg; + + float H; + H = max(Delta.r, max(Delta.g, Delta.b)); + return frac(H / 6); +} + +float3 RGBtoHSV(float3 RGB) +{ + float3 HSV = 0; + HSV.z = max(RGB.r, max(RGB.g, RGB.b)); + float M = min(RGB.r, min(RGB.g, RGB.b)); + float C = HSV.z - M; + + if (C != 0) + { + HSV.x = RGBCVtoHUE(RGB, C, HSV.z); + HSV.y = C / HSV.z; + } + + return HSV; +} + +float3 HUEtoRGB(float H) +{ + float R = abs(H * 6 - 3) - 1; + float G = 2 - abs(H * 6 - 2); + float B = 2 - abs(H * 6 - 4); + + return saturate(float3(R, G, B)); +} + +float3 HSVtoRGB(float3 HSV) +{ + float3 RGB = HUEtoRGB(HSV.x); + return ((RGB - 1) * HSV.y + 1) * HSV.z; +} + +float3 HSVComplement(float3 HSV) +{ + float3 complement = HSV; + complement.x -= 0.5; + + if (complement.x < 0.0) { complement.x += 1.0; } + return(complement); +} + +float HueLerp(float h1, float h2, float v) +{ + float d = abs(h1 - h2); + + if (d <= 0.5) + { + return lerp(h1, h2, v); + } + else if (h1 < h2) + { + return frac(lerp((h1 + 1.0), h2, v)); + } + else + { + return frac(lerp(h1, (h2 + 1.0), v)); + } +} + +float4 ColorGrading(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target0 +{ + float3 guide = float3(RedGrading, GreenGrading, BlueGrading); + float amount = GradingStrength; + float correlation = Correlation; + float concentration = 2.00; + + float3 colorHSV = RGBtoHSV(color.rgb); + float3 huePoleA = RGBtoHSV(guide); + float3 huePoleB = HSVComplement(huePoleA); + + float dist1 = abs(colorHSV.x - huePoleA.x); if (dist1 > 0.5) dist1 = 1.0 - dist1; + float dist2 = abs(colorHSV.x - huePoleB.x); if (dist2 > 0.5) dist2 = 1.0 - dist2; + + float descent = smoothstep(0.0, correlation, colorHSV.y); + + float3 HSVColor = colorHSV; + + if (dist1 < dist2) + { + float c = descent * amount * (1.0 - pow((dist1 * 2.0), 1.0 / concentration)); + HSVColor.x = HueLerp(colorHSV.x, huePoleA.x, c); + HSVColor.y = lerp(colorHSV.y, huePoleA.y, c); + } + else + { + float c = descent * amount * (1.0 - pow((dist2 * 2.0), 1.0 / concentration)); + HSVColor.x = HueLerp(colorHSV.x, huePoleB.x, c); + HSVColor.y = lerp(colorHSV.y, huePoleB.y, c); + } + + color.rgb = HSVtoRGB(HSVColor); + color.a = RGBLuminance(color.rgb); + + return saturate(color); +} +#endif + +/*------------------------------------------------------------------------------ +[SCANLINES CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (SCANLINES == 1) +float4 ScanlinesPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0, float4 FragCoord : SV_Position) : SV_Target0 +{ + +#if (ScanlineType == 3) + float amount = ScanlineBrightness; + float intensity = ScanlineIntensity; + + float pos0 = ((uv0.y + 1.0) * 170.0 * amount); + float pos1 = cos((frac(pos0 * ScanlineScale) - 0.5) * 3.1415926 * intensity) * 1.2; + + color = lerp(float4(0, 0, 0, 0), color, pos1); +#else + + float4 intensity; + +#if (ScanlineType == 0) + if (frac(FragCoord.y * 0.25) > ScanlineScale) +#elif (ScanlineType == 1) + if (frac(FragCoord.x * 0.25) > ScanlineScale) +#elif (ScanlineType == 2) + if (frac(FragCoord.x * 0.25) > ScanlineScale && frac(FragCoord.y * 0.25) > ScanlineScale) +#endif + { + intensity = float4(0.0, 0.0, 0.0, 0.0); + } + else + { + intensity = smoothstep(0.2, ScanlineBrightness, color) + normalize(float4(color.xyz, RGBLuminance(color.xyz))); + } + + float level = (4.0 - uv0.x) * ScanlineIntensity; + + color = intensity * (0.5 - level) + color * 1.1; +#endif + + return color; +} +#endif + +/*------------------------------------------------------------------------------ +[SUBPIXEL DITHERING CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (DITHERING == 1) +float4 DitherPass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target +{ + float ditherSize = 2.0; + float ditherBits = 8.0; + +#if DitherMethod == 2 //random subpixel dithering + + float seed = dot(uv0, float2(12.9898, 78.233)); + float sine = sin(seed); + float noise = frac(sine * 43758.5453 + uv0.x); + + float ditherShift = (1.0 / (pow(2.0, ditherBits) - 1.0)); + float ditherHalfShift = (ditherShift * 0.5); + ditherShift = ditherShift * noise - ditherHalfShift; + + color.rgb += float3(-ditherShift, ditherShift, -ditherShift); + +#else //Ordered dithering + + float gridPosition = frac(dot(uv0, (PixelSize.xy / ditherSize)) + (0.5 / ditherSize)); + float ditherShift = (0.75) * (1.0 / (pow(2, ditherBits) - 1.0)); + + float3 RGBShift = float3(ditherShift, -ditherShift, ditherShift); + RGBShift = lerp(2.0 * RGBShift, -2.0 * RGBShift, gridPosition); + + color.rgb += RGBShift; +#endif + + color.a = RGBLuminance(color.rgb); + + return color; +} +#endif + +/*------------------------------------------------------------------------------ +[VIGNETTE CODE SECTION] +------------------------------------------------------------------------------*/ + +#if (VIGNETTE == 1) +#define VignetteCenter float2(0.500, 0.500) + +float4 VignettePass(float4 color : COLOR0, float2 uv0 : TEXCOORD0) : SV_Target +{ + float2 tc = uv0 - VignetteCenter; + + tc *= float2((PixelSize.y / PixelSize.x), VignetteRatio); + tc /= VignetteRadius; + + float v = dot(tc, tc); + + color.rgb *= (1.0 + pow(v, VignetteSlope * 0.5) * -VignetteAmount); + + return color; +} +#endif + +/*------------------------------------------------------------------------------ +[MAIN() & COMBINE PASS CODE SECTION] +------------------------------------------------------------------------------*/ + +PS_OUTPUT ps_main(VS_OUTPUT input) +{ + PS_OUTPUT output; + + float4 color = PreGammaPass(color, input.t); + +#if (BILINEAR_FILTERING == 1) + color = BiLinearPass(color, input.t); +#endif + +#if (BICUBIC_FILTERING == 1) + color = BiCubicPass(color, input.t); +#endif + +#if (GAUSSIAN_FILTERING == 1) + color = GaussianPass(color, input.t); +#endif + +#if (UHQ_FXAA == 1) + color = FxaaPass(color, input.t); +#endif + +#if (GAMMA_CORRECTION == 1) + color = PostGammaPass(color, input.t); +#endif + +#if (TEXTURE_SHARPENING == 1) + color = TexSharpenPass(color, input.t); +#endif + +#if (SCANLINES == 1) + color = ScanlinesPass(color, input.t, input.p); +#endif + +#if (PIXEL_VIBRANCE == 1) + color = VibrancePass(color, input.t); +#endif + +#if (COLOR_GRADING == 1) + color = ColorGrading(color, input.t); +#endif + +#if (CEL_SHADING == 1) + color = CelPass(color, input.t); +#endif + +#if (BLENDED_BLOOM == 1) + color = BloomPass(color, input.t); +#endif + +#if (SCENE_TONEMAPPING == 1) + color = TonemapPass(color, input.t); +#endif + +#if (S_CURVE_CONTRAST == 1) + color = SCurvePass(color, input.t); +#endif + +#if (VIGNETTE == 1) + color = VignettePass(color, input.t); +#endif + +#if (DITHERING == 1) + color = DitherPass(color, input.t); +#endif + + output.c = color; return output; } #endif - -#if (FXAA_GLSL_130 == 1) -void ps_main() -{ - vec2 pos = PSin_t; - vec4 posPos = vec4(0.0, 0.0, 0.0, 0.0); - - SV_Target0 = FxaaPixelShader(pos, posPos, TextureSampler, _rcpFrame.xy, _rcpFrameOpt); -} -#endif - -#endif