Index: binaries/data/config/default.cfg =================================================================== --- binaries/data/config/default.cfg +++ binaries/data/config/default.cfg @@ -117,6 +117,9 @@ ; Use anti-aliasing techniques. antialiasing = "disabled" +; Use sharpening techniques. +sharpening = "disabled" + ; Quality level of shader effects (set to 10 to display all effects) materialmgr.quality = 2.0 Index: binaries/data/mods/public/gui/options/options.json =================================================================== --- binaries/data/mods/public/gui/options/options.json +++ binaries/data/mods/public/gui/options/options.json @@ -130,6 +130,18 @@ "function": "Renderer_UpdateAntiAliasingTechnique" }, { + "type": "dropdown", + "label": "Sharpening", + "tooltip": "Reduce blurry effects.", + "dependencies": ["postproc"], + "config": "sharpening", + "list": [ + { "value": "disabled", "label": "Disabled", "tooltip": "Do not use sharpening." }, + { "value": "cas", "label": "CAS", "tooltip": "Contrast adaptive sharpening, a fast, contrast based sharpening pass, developed by AMD." } + ], + "function": "Renderer_UpdateSharpeningTechnique" + }, + { "type": "slider", "label": "Shader effects", "tooltip": "Number of shader effects. REQUIRES GAME RESTART", Index: binaries/data/mods/public/gui/options/options.xml =================================================================== --- binaries/data/mods/public/gui/options/options.xml +++ binaries/data/mods/public/gui/options/options.xml @@ -9,7 +9,7 @@ - + Game Options Index: binaries/data/mods/public/shaders/effects/cas.xml =================================================================== --- binaries/data/mods/public/shaders/effects/cas.xml +++ binaries/data/mods/public/shaders/effects/cas.xml @@ -0,0 +1,7 @@ + + + + + + + Index: binaries/data/mods/public/shaders/glsl/cas.fs =================================================================== --- binaries/data/mods/public/shaders/glsl/cas.fs +++ binaries/data/mods/public/shaders/glsl/cas.fs @@ -0,0 +1,87 @@ +// LICENSE +// ======= +// Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved. +// ------- +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// ------- +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +// Software. +// ------- +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +uniform sampler2D renderedTex; +uniform float width; +uniform float height; + +varying vec2 v_tex; + +float saturate(float inputFloat){ + return clamp(inputFloat, 0.0, 1.0); +} + +vec3 saturate(vec3 inputFloat){ + return vec3(saturate(inputFloat.x), saturate(inputFloat.y), saturate(inputFloat.z)); +} + +vec3 sharpen(float sharpness) +{ + vec2 invSSize = vec2(1.0 / width, 1.0 / height); + + // fetch a 3x3 neighborhood around the pixel 'e', + // a b c + // d(e)f + // g h i + vec3 a = texture2D(renderedTex, v_tex + vec2(-1, -1) * invSSize).rgb; + vec3 b = texture2D(renderedTex, v_tex + vec2(0, -1) * invSSize).rgb; + vec3 c = texture2D(renderedTex, v_tex + vec2(1, -1) * invSSize).rgb; + vec3 d = texture2D(renderedTex, v_tex + vec2(-1, 0) * invSSize).rgb; + vec3 e = texture2D(renderedTex, v_tex + vec2(0, 0) * invSSize).rgb; + vec3 f = texture2D(renderedTex, v_tex + vec2(1, 0) * invSSize).rgb; + vec3 g = texture2D(renderedTex, v_tex + vec2(-1, 1) * invSSize).rgb; + vec3 h = texture2D(renderedTex, v_tex + vec2(0, 1) * invSSize).rgb; + vec3 i = texture2D(renderedTex, v_tex + vec2(1, 1) * invSSize).rgb; + + // Soft min and max. + // a b c b + // d e f * 0.5 + d e f * 0.5 + // g h i h + // These are 2.0x bigger (factored out the extra multiply). + vec3 mnRGB = min(min(min(d, e), min(f, b)), h); + vec3 mnRGB2 = min(mnRGB, min(min(a, c), min(g, i))); + mnRGB += mnRGB2; + + vec3 mxRGB = max(max(max(d, e), max(f, b)), h); + vec3 mxRGB2 = max(mxRGB, max(max(a, c), max(g, i))); + mxRGB += mxRGB2; + + // Smooth minimum distance to signal limit divided by smooth max. + vec3 rcpMRGB = rcp(mxRGB); + vec3 ampRGB = saturate(min(mnRGB, 2.0 - mxRGB) * rcpMRGB); + + // Shaping amount of sharpening. + ampRGB = sqrt(ampRGB); + + float peak = -rcp(8.0 - 3.0 * sharpness); + vec3 wRGB = ampRGB * peak; + + vec3 rcpWeightRGB = rcp(1.0 + 4.0 * wRGB); + + // 0 w 0 + // Filter shape: w 1 w + // 0 w 0 + vec3 window = (b + d) + (f + h); + vec3 outColor = saturate((window * wRGB + e) * rcpWeightRGB); + + return outColor; +} + +void main() +{ + gl_FragColor.rgb = sharpen(0.5); +} Index: binaries/data/mods/public/shaders/glsl/cas.xml =================================================================== --- binaries/data/mods/public/shaders/glsl/cas.xml +++ binaries/data/mods/public/shaders/glsl/cas.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + Index: source/renderer/PostprocManager.h =================================================================== --- source/renderer/PostprocManager.h +++ source/renderer/PostprocManager.h @@ -50,6 +50,7 @@ // Triggers update of shaders and FBO if needed. void UpdateAntiAliasingTechnique(); + void UpdateSharpeningTechnique(); void SetDepthBufferClipPlanes(float nearPlane, float farPlane); @@ -91,6 +92,9 @@ CStrW m_PostProcEffect; CShaderTechniquePtr m_PostProcTech; + CStr m_SharpName; + CShaderTechniquePtr m_SharpTech; + CStr m_AAName; CShaderTechniquePtr m_AATech; Index: source/renderer/PostprocManager.cpp =================================================================== --- source/renderer/PostprocManager.cpp +++ source/renderer/PostprocManager.cpp @@ -81,6 +81,7 @@ m_Height = g_Renderer.GetHeight(); UpdateAntiAliasingTechnique(); + UpdateSharpeningTechnique(); RecreateBuffers(); m_IsInitialized = true; @@ -504,6 +505,12 @@ ApplyEffect(m_AATech, pass); } + if (m_SharpTech) + { + for (int pass = 0; pass < m_SharpTech->GetNumPasses(); ++pass) + ApplyEffect(m_SharpTech, pass); + } + pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo); pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0); @@ -570,6 +577,24 @@ } } +void CPostprocManager::UpdateSharpeningTechnique() +{ + if (!g_RenderingOptions.GetPreferGLSL()) + return; + + CStr newSharpName; + CFG_GET_VAL("sharpening", newSharpName); + if (m_SharpName == newSharpName) + return; + m_SharpName = newSharpName; + m_SharpTech.reset(); + + if (m_SharpName == "cas") + { + m_SharpTech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("cas")); + } +} + void CPostprocManager::SetDepthBufferClipPlanes(float nearPlane, float farPlane) { m_NearPlane = nearPlane; @@ -633,6 +658,10 @@ { } +void CPostprocManager::UpdateSharpeningTechnique() +{ +} + void CPostprocManager::CaptureRenderOutput() { } Index: source/renderer/scripting/JSInterface_Renderer.h =================================================================== --- source/renderer/scripting/JSInterface_Renderer.h +++ source/renderer/scripting/JSInterface_Renderer.h @@ -29,6 +29,7 @@ std::string GetRenderPath(ScriptInterface::CxPrivate* pCxPrivate); void SetRenderPath(ScriptInterface::CxPrivate* pCxPrivate, const std::string& name); void UpdateAntiAliasingTechnique(ScriptInterface::CxPrivate* pCxPrivate); + void UpdateSharpeningTechnique(ScriptInterface::CxPrivate* pCxPrivate); void RecreateShadowMap(ScriptInterface::CxPrivate* pCxPrivate); bool TextureExists(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& filename); Index: source/renderer/scripting/JSInterface_Renderer.cpp =================================================================== --- source/renderer/scripting/JSInterface_Renderer.cpp +++ source/renderer/scripting/JSInterface_Renderer.cpp @@ -72,6 +72,11 @@ g_Renderer.GetPostprocManager().UpdateAntiAliasingTechnique(); } +void JSI_Renderer::UpdateSharpeningTechnique(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) +{ + g_Renderer.GetPostprocManager().UpdateSharpeningTechnique(); +} + void JSI_Renderer::RecreateShadowMap(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { g_Renderer.GetShadowMap().RecreateTexture(); @@ -92,6 +97,7 @@ scriptInterface.RegisterFunction("Renderer_SetRenderPath"); scriptInterface.RegisterFunction("Renderer_RecreateShadowMap"); scriptInterface.RegisterFunction("Renderer_UpdateAntiAliasingTechnique"); + scriptInterface.RegisterFunction("Renderer_UpdateSharpeningTechnique"); scriptInterface.RegisterFunction("TextureExists"); REGISTER_BOOLEAN_SCRIPT_SETTING(Shadows); REGISTER_BOOLEAN_SCRIPT_SETTING(ShadowPCF);