From 113b1c49b90e573f1134d533f707db806336ba3b Mon Sep 17 00:00:00 2001 From: vladislavbelov Date: Wed, 5 Feb 2020 21:53:10 +0000 Subject: [PATCH] Adds anti-aliasing option with FXAA algorithm. Differential Revision: https://code.wildfiregames.com/D2537 This was SVN commit r23484. --- LICENSE.txt | 3 + binaries/data/config/default.cfg | 3 + .../data/mods/public/gui/options/options.json | 12 + .../data/mods/public/gui/options/options.xml | 2 +- .../data/mods/public/shaders/effects/fxaa.xml | 7 + .../data/mods/public/shaders/glsl/bloom.xml | 2 +- .../data/mods/public/shaders/glsl/dof.xml | 2 +- .../data/mods/public/shaders/glsl/fxaa.fs | 623 ++++++++++++++++++ .../data/mods/public/shaders/glsl/fxaa.xml | 13 + .../data/mods/public/shaders/glsl/hdr.xml | 2 +- .../public/shaders/glsl/{hdr.vs => simple.vs} | 0 source/renderer/PostprocManager.cpp | 34 + source/renderer/PostprocManager.h | 8 +- .../scripting/JSInterface_Renderer.cpp | 7 + .../renderer/scripting/JSInterface_Renderer.h | 1 + 15 files changed, 714 insertions(+), 5 deletions(-) create mode 100644 binaries/data/mods/public/shaders/effects/fxaa.xml create mode 100644 binaries/data/mods/public/shaders/glsl/fxaa.fs create mode 100644 binaries/data/mods/public/shaders/glsl/fxaa.xml rename binaries/data/mods/public/shaders/glsl/{hdr.vs => simple.vs} (100%) diff --git a/LICENSE.txt b/LICENSE.txt index b430904803..937c60e934 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -26,6 +26,9 @@ in particular, let us know and we can try to clarify it. /binaries/data/mods/*/maps/ see LICENSE.txt within those directories + /binaries/data/mods/public/shaders/glsl/fxaa.fs + BSD + /binaries/system Various (unspecified) diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg index 11fe54ec60..278e40f128 100644 --- a/binaries/data/config/default.cfg +++ b/binaries/data/config/default.cfg @@ -114,6 +114,9 @@ smoothlos = false ; Use screen-space postprocessing filters (HDR, bloom, DOF, etc). Incompatible with fixed renderpath. postproc = false +; Use anti-aliasing techniques. +antialiasing = "disabled" + ; Quality level of shader effects (set to 10 to display all effects) materialmgr.quality = 2.0 diff --git a/binaries/data/mods/public/gui/options/options.json b/binaries/data/mods/public/gui/options/options.json index 606a8c7493..c11e1cc992 100644 --- a/binaries/data/mods/public/gui/options/options.json +++ b/binaries/data/mods/public/gui/options/options.json @@ -117,6 +117,18 @@ "config": "postproc", "function": "Renderer_SetPostProcEnabled" }, + { + "type": "dropdown", + "label": "Anti-Aliasing", + "tooltip": "Reduce aliasing effect on edges.", + "dependencies": ["postproc"], + "config": "antialiasing", + "list": [ + { "value": "disabled", "label": "Disabled", "tooltip": "Do not use anti-aliasing." }, + { "value": "fxaa", "label": "FXAA", "tooltip": "Fast, but simple anti-aliasing." } + ], + "function": "Renderer_UpdateAntiAliasingTechnique" + }, { "type": "slider", "label": "Shader effects", diff --git a/binaries/data/mods/public/gui/options/options.xml b/binaries/data/mods/public/gui/options/options.xml index c18992d274..5d6a05445f 100644 --- a/binaries/data/mods/public/gui/options/options.xml +++ b/binaries/data/mods/public/gui/options/options.xml @@ -9,7 +9,7 @@ - + Game Options diff --git a/binaries/data/mods/public/shaders/effects/fxaa.xml b/binaries/data/mods/public/shaders/effects/fxaa.xml new file mode 100644 index 0000000000..ed76b4c8a1 --- /dev/null +++ b/binaries/data/mods/public/shaders/effects/fxaa.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/binaries/data/mods/public/shaders/glsl/bloom.xml b/binaries/data/mods/public/shaders/glsl/bloom.xml index 2bf9003996..7815267748 100644 --- a/binaries/data/mods/public/shaders/glsl/bloom.xml +++ b/binaries/data/mods/public/shaders/glsl/bloom.xml @@ -1,7 +1,7 @@ - + diff --git a/binaries/data/mods/public/shaders/glsl/dof.xml b/binaries/data/mods/public/shaders/glsl/dof.xml index 38b8688a6f..873d0d874b 100644 --- a/binaries/data/mods/public/shaders/glsl/dof.xml +++ b/binaries/data/mods/public/shaders/glsl/dof.xml @@ -1,7 +1,7 @@ - + diff --git a/binaries/data/mods/public/shaders/glsl/fxaa.fs b/binaries/data/mods/public/shaders/glsl/fxaa.fs new file mode 100644 index 0000000000..f4145158ba --- /dev/null +++ b/binaries/data/mods/public/shaders/glsl/fxaa.fs @@ -0,0 +1,623 @@ +#version 120 + +// Our GLSL adoptation of: +// +// * Removed all unrelated code (such as HLSL or console implementations). +// * Removed unused macro (such as FXAA_DISCARD, FXAA_GATHER4_ALPHA, ...). +// * Luma calculated by 3 components instead of the only green one. + +#define FXAA_QUALITY__PRESET 10 + +// +// NVIDIA FXAA 3.11 by TIMOTHY LOTTES +// +// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +/*============================================================================ + 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 + +#define FxaaTexTop(t, p) texture2DLod((t), (p), 0.0) +#define FxaaTexOff(t, p, o, r) texture2DLod((t), (p) + (o) * (r), 0.0) +#define FxaaLuma(rgba) dot((rgba).rgb, vec3(0.299, 0.587, 0.114)) + +vec4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + vec2 pos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + sampler2D tex, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + vec2 fxaaQualityRcpFrame, + // + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + float fxaaQualitySubpix, + // + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + float fxaaQualityEdgeThreshold, + // + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + float fxaaQualityEdgeThresholdMin) +{ +/*--------------------------------------------------------------------------*/ + vec2 posM; + posM.x = pos.x; + posM.y = pos.y; + vec4 rgbyM = FxaaTexTop(tex, posM); + float lumaM = FxaaLuma(rgbyM); + float lumaS = FxaaLuma(FxaaTexOff(tex, posM, vec2(0, 1), fxaaQualityRcpFrame.xy)); + float lumaE = FxaaLuma(FxaaTexOff(tex, posM, vec2(1, 0), fxaaQualityRcpFrame.xy)); + float lumaN = FxaaLuma(FxaaTexOff(tex, posM, vec2(0, -1), fxaaQualityRcpFrame.xy)); + float lumaW = FxaaLuma(FxaaTexOff(tex, posM, vec2(-1, 0), fxaaQualityRcpFrame.xy)); +/*--------------------------------------------------------------------------*/ + 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 * fxaaQualityEdgeThreshold; + float range = rangeMax - rangeMin; + float rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + bool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + return rgbyM; +/*--------------------------------------------------------------------------*/ + float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, vec2(-1,-1), fxaaQualityRcpFrame.xy)); + float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, vec2( 1, 1), fxaaQualityRcpFrame.xy)); + float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, vec2( 1,-1), fxaaQualityRcpFrame.xy)); + float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, vec2(-1, 1), fxaaQualityRcpFrame.xy)); +/*--------------------------------------------------------------------------*/ + 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 = fxaaQualityRcpFrame.x; + bool horzSpan = edgeHorz >= edgeVert; + float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.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 = clamp(abs(subpixB) * subpixRcpRange, 0.0, 1.0); +/*--------------------------------------------------------------------------*/ + vec2 posB; + posB.x = posM.x; + posB.y = posM.y; + vec2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + vec2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + vec2 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 * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + float pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + float pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + return vec4(FxaaTexTop(tex, posM).xyz, lumaM); +} + +uniform sampler2D renderedTex; +uniform float width; +uniform float height; + +varying vec2 v_tex; + +void main() +{ + // See comment for the FxaaPixelShader function. + const float fxaaQualitySubpix = 0.75; + const float fxaaQualityEdgeThreshold = 0.125; + const float fxaaQualityEdgeThresholdMin = 0.0312; + gl_FragColor = FxaaPixelShader( + v_tex, renderedTex, + vec2(1.0, 1.0) / vec2(width, height), + fxaaQualitySubpix, + fxaaQualityEdgeThreshold, + fxaaQualityEdgeThresholdMin); +} diff --git a/binaries/data/mods/public/shaders/glsl/fxaa.xml b/binaries/data/mods/public/shaders/glsl/fxaa.xml new file mode 100644 index 0000000000..2b044e8129 --- /dev/null +++ b/binaries/data/mods/public/shaders/glsl/fxaa.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/binaries/data/mods/public/shaders/glsl/hdr.xml b/binaries/data/mods/public/shaders/glsl/hdr.xml index aaaad6cbf5..9f2d97ec5a 100644 --- a/binaries/data/mods/public/shaders/glsl/hdr.xml +++ b/binaries/data/mods/public/shaders/glsl/hdr.xml @@ -1,7 +1,7 @@ - + diff --git a/binaries/data/mods/public/shaders/glsl/hdr.vs b/binaries/data/mods/public/shaders/glsl/simple.vs similarity index 100% rename from binaries/data/mods/public/shaders/glsl/hdr.vs rename to binaries/data/mods/public/shaders/glsl/simple.vs diff --git a/source/renderer/PostprocManager.cpp b/source/renderer/PostprocManager.cpp index 098dde3dd3..a71bd54a34 100644 --- a/source/renderer/PostprocManager.cpp +++ b/source/renderer/PostprocManager.cpp @@ -25,11 +25,13 @@ #include "lib/bits.h" #include "lib/ogl.h" #include "maths/MathUtil.h" +#include "ps/ConfigDB.h" #include "ps/CLogger.h" #include "ps/Filesystem.h" #include "ps/Game.h" #include "ps/World.h" #include "renderer/Renderer.h" +#include "renderer/RenderingOptions.h" #if !CONFIG2_GLES @@ -78,6 +80,7 @@ void CPostprocManager::Initialize() m_Width = g_Renderer.GetWidth(); m_Height = g_Renderer.GetHeight(); + UpdateAntiAliasingTechnique(); RecreateBuffers(); m_IsInitialized = true; @@ -495,6 +498,12 @@ void CPostprocManager::ApplyPostproc() for (int pass = 0; pass < m_PostProcTech->GetNumPasses(); ++pass) ApplyEffect(m_PostProcTech, pass); + if (m_AATech) + { + for (int pass = 0; pass < m_AATech->GetNumPasses(); ++pass) + ApplyEffect(m_AATech, pass); + } + pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo); pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0); @@ -540,6 +549,27 @@ void CPostprocManager::SetPostEffect(const CStrW& name) m_PostProcEffect = name; } +void CPostprocManager::UpdateAntiAliasingTechnique() +{ + if (!g_RenderingOptions.GetPreferGLSL()) + return; + + CStr newAAName; + CFG_GET_VAL("antialiasing", newAAName); + if (m_AAName == newAAName) + return; + m_AAName = newAAName; + m_AATech.reset(); + + // We have to hardcode names in the engine, because anti-aliasing + // techinques strongly depend on the graphics pipeline. + // We might use enums in future though. + if (m_AAName == "fxaa") + { + m_AATech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("fxaa")); + } +} + void CPostprocManager::SetDepthBufferClipPlanes(float nearPlane, float farPlane) { m_NearPlane = nearPlane; @@ -599,6 +629,10 @@ void CPostprocManager::SetDepthBufferClipPlanes(float UNUSED(nearPlane), float U { } +void CPostprocManager::UpdateAntiAliasingTechnique() +{ +} + void CPostprocManager::CaptureRenderOutput() { } diff --git a/source/renderer/PostprocManager.h b/source/renderer/PostprocManager.h index 08528176f0..9140b92bbf 100644 --- a/source/renderer/PostprocManager.h +++ b/source/renderer/PostprocManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -48,6 +48,9 @@ public: // Sets the current effect. void SetPostEffect(const CStrW& name); + // Triggers update of shaders and FBO if needed. + void UpdateAntiAliasingTechnique(); + void SetDepthBufferClipPlanes(float nearPlane, float farPlane); // Clears the two color buffers and depth buffer, and redirects all rendering @@ -88,6 +91,9 @@ private: CStrW m_PostProcEffect; CShaderTechniquePtr m_PostProcTech; + CStr m_AAName; + CShaderTechniquePtr m_AATech; + // The current screen dimensions in pixels. int m_Width, m_Height; diff --git a/source/renderer/scripting/JSInterface_Renderer.cpp b/source/renderer/scripting/JSInterface_Renderer.cpp index 1cd5861b3e..8aeb9675ae 100644 --- a/source/renderer/scripting/JSInterface_Renderer.cpp +++ b/source/renderer/scripting/JSInterface_Renderer.cpp @@ -20,6 +20,7 @@ #include "JSInterface_Renderer.h" #include "graphics/TextureManager.h" +#include "renderer/PostprocManager.h" #include "renderer/RenderingOptions.h" #include "renderer/Renderer.h" #include "renderer/ShadowMap.h" @@ -66,6 +67,11 @@ void JSI_Renderer::SetRenderPath(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), g_RenderingOptions.SetRenderPath(RenderPathEnum::FromString(name)); } +void JSI_Renderer::UpdateAntiAliasingTechnique(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) +{ + g_Renderer.GetPostprocManager().UpdateAntiAliasingTechnique(); +} + void JSI_Renderer::RecreateShadowMap(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { g_Renderer.GetShadowMap().RecreateTexture(); @@ -85,6 +91,7 @@ void JSI_Renderer::RegisterScriptFunctions(const ScriptInterface& scriptInterfac scriptInterface.RegisterFunction("Renderer_GetRenderPath"); scriptInterface.RegisterFunction("Renderer_SetRenderPath"); scriptInterface.RegisterFunction("Renderer_RecreateShadowMap"); + scriptInterface.RegisterFunction("Renderer_UpdateAntiAliasingTechnique"); scriptInterface.RegisterFunction("TextureExists"); REGISTER_BOOLEAN_SCRIPT_SETTING(Shadows); REGISTER_BOOLEAN_SCRIPT_SETTING(ShadowPCF); diff --git a/source/renderer/scripting/JSInterface_Renderer.h b/source/renderer/scripting/JSInterface_Renderer.h index 2b5efd94aa..c85164389c 100644 --- a/source/renderer/scripting/JSInterface_Renderer.h +++ b/source/renderer/scripting/JSInterface_Renderer.h @@ -28,6 +28,7 @@ namespace JSI_Renderer { std::string GetRenderPath(ScriptInterface::CxPrivate* pCxPrivate); void SetRenderPath(ScriptInterface::CxPrivate* pCxPrivate, const std::string& name); + void UpdateAntiAliasingTechnique(ScriptInterface::CxPrivate* pCxPrivate); void RecreateShadowMap(ScriptInterface::CxPrivate* pCxPrivate); bool TextureExists(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& filename);