/*------------------. | :: Description :: | '-------------------/ Filmic Anamorph Sharpen PS (version 1.5.0) Copyright: This code © 2018-2023 Jakub Maximilian Fober Some changes by ccritchfield https://github.com/ccritchfield License: This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/ */ /*--------------. | :: Commons :: | '--------------*/ #include "ReShade.fxh" #include "ReShadeUI.fxh" #include "ColorConversion.fxh" #include "LinearGammaWorkflow.fxh" /*-----------. | :: Menu :: | '-----------*/ uniform float Strength < __UNIFORM_SLIDER_FLOAT1 ui_label = "Strength"; ui_min = 0.0; ui_max = 100.0; ui_step = 0.01; > = 60.0; uniform float Offset < __UNIFORM_SLIDER_FLOAT1 ui_units = " pixel"; ui_label = "Radius"; ui_tooltip = "High-pass cross offset in pixels"; ui_min = 0.0; ui_max = 2.0; ui_step = 0.01; > = 0.1; uniform float Clamp < __UNIFORM_SLIDER_FLOAT1 ui_label = "Clamping"; ui_min = 0.5; ui_max = 1.0; ui_step = 0.001; > = 0.65; uniform bool UseMask < __UNIFORM_INPUT_BOOL1 ui_label = "Sharpen only center"; ui_tooltip = "Sharpen only in center of the image"; > = false; uniform bool DepthMask < __UNIFORM_INPUT_BOOL1 ui_label = "Enable depth rim masking"; ui_tooltip = "Depth high-pass mask switch"; ui_category = "Depth mask"; ui_category_closed = true; > = false; uniform int DepthMaskContrast < __UNIFORM_DRAG_INT1 ui_label = "Edges mask strength"; ui_tooltip = "Depth high-pass mask amount"; ui_category = "Depth mask"; ui_min = 0; ui_max = 2000; ui_step = 1; > = 128; uniform bool Preview < __UNIFORM_INPUT_BOOL1 ui_label = "Preview sharpen layer"; ui_tooltip = "Preview sharpen layer and mask for adjustment.\n" "If you don't see red strokes,\n" "try changing Preprocessor Definitions in the Settings tab."; ui_category = "Debug View"; ui_category_closed = true; > = false; /*---------------. | :: Textures :: | '---------------*/ // Define screen texture with mirror tiles sampler BackBuffer { Texture = ReShade::BackBufferTex; AddressU = MIRROR; AddressV = MIRROR; }; /*----------------. | :: Functions :: | '----------------*/ // Overlay blending mode float Overlay(float LayerA, float LayerB) { float MinA = min(LayerA, 0.5); float MinB = min(LayerB, 0.5); float MaxA = max(LayerA, 0.5); float MaxB = max(LayerB, 0.5); return 2f*(MinA*MinB+MaxA+MaxB-MaxA*MaxB)-1.5; } // Overlay blending mode for one input float Overlay(float LayerAB) { float MinAB = min(LayerAB, 0.5); float MaxAB = max(LayerAB, 0.5); return 2f*(MinAB*MinAB+MaxAB+MaxAB-MaxAB*MaxAB)-1.5; } /*--------------. | :: Shaders :: | '--------------*/ // Sharpen pass float3 FilmicAnamorphSharpenPS( float4 pos : SV_Position, float2 UvCoord : TEXCOORD ) : SV_Target { // Sample display image float3 Source = GammaConvert::to_linear(tex2D(BackBuffer, UvCoord).rgb); // Generate radial mask float Mask; if (UseMask) { // Generate radial mask Mask = 1f-length(UvCoord*2f-1f); Mask = Overlay(Mask) * Strength; // Bypass if (Mask<=0) return GammaConvert::to_display(Source); } else Mask = Strength; // Get pixel size float2 Pixel = BUFFER_PIXEL_SIZE; if (DepthMask) { /* // original float2 DepthPixel = Pixel*Offset+Pixel; Pixel *= Offset; */ // !!! calc pixel*offset once, use twice float2 PixelOffset = Pixel * Offset; float2 DepthPixel = PixelOffset + Pixel; Pixel = PixelOffset; // Sample display depth image float SourceDepth = ReShade::GetLinearizedDepth(UvCoord); float2 NorSouWesEst[4] = { float2(UvCoord.x, UvCoord.y + Pixel.y), float2(UvCoord.x, UvCoord.y - Pixel.y), float2(UvCoord.x + Pixel.x, UvCoord.y), float2(UvCoord.x - Pixel.x, UvCoord.y) }; float2 DepthNorSouWesEst[4] = { float2(UvCoord.x, UvCoord.y + DepthPixel.y), float2(UvCoord.x, UvCoord.y - DepthPixel.y), float2(UvCoord.x + DepthPixel.x, UvCoord.y), float2(UvCoord.x - DepthPixel.x, UvCoord.y) }; // Luma high-pass color // Luma high-pass depth float HighPassColor = 0f, DepthMask = 0f; [unroll]for(int s=0; s<4; s++) { HighPassColor += ColorConvert::RGB_to_Luma( GammaConvert::to_linear( tex2D(BackBuffer, NorSouWesEst[s]).rgb )); DepthMask += ReShade::GetLinearizedDepth(NorSouWesEst[s]) +ReShade::GetLinearizedDepth(DepthNorSouWesEst[s]); } HighPassColor = 0.5-0.5*(HighPassColor*0.25-ColorConvert::RGB_to_Luma(Source)); DepthMask = 1f-DepthMask*0.125+SourceDepth; DepthMask = min(1f, DepthMask)+1f-max(1f, DepthMask); DepthMask = saturate(DepthMaskContrast*DepthMask+1f-DepthMaskContrast); // Sharpen strength HighPassColor = lerp(0.5, HighPassColor, Mask*DepthMask); // Clamping sharpen /* // original HighPassColor = Clamp!=1f ? max(min(HighPassColor, Clamp), 1f-Clamp) : HighPassColor; */ // !!! Clamp in settings above is restricted to 0.5 to 1.0 // !!! 1.0 - Clamp is the low value, while Clamp is the high value // !!! so we can literally just use the clamp() func instead of min/max. // !!! not sure if author was trying to take advantage of some kind of // !!! compiler "cheat" using min/max instead of clamp to improve // !!! performance. doesn't make sense to min/max otherwise. HighPassColor = Clamp!=1f ? clamp(HighPassColor, 1f-Clamp, Clamp ) : HighPassColor; float3 Sharpen = float3( Overlay(Source.r, HighPassColor), Overlay(Source.g, HighPassColor), Overlay(Source.b, HighPassColor) ); if(Preview) // Preview mode ON { float PreviewChannel = lerp(HighPassColor, HighPassColor*DepthMask, 0.5); return GammaConvert::to_display(float3( 1f-DepthMask * (1f-HighPassColor), PreviewChannel, PreviewChannel )); } return GammaConvert::to_display(Sharpen); } else { Pixel *= Offset; float2 NorSouWesEst[4] = { float2(UvCoord.x, UvCoord.y + Pixel.y), float2(UvCoord.x, UvCoord.y - Pixel.y), float2(UvCoord.x + Pixel.x, UvCoord.y), float2(UvCoord.x - Pixel.x, UvCoord.y) }; // Luma high-pass color float HighPassColor = 0f; [unroll] for(uint s=0u; s<4u; s++) HighPassColor += ColorConvert::RGB_to_Luma( GammaConvert::to_linear( tex2D(BackBuffer, NorSouWesEst[s]).rgb )); // !!! added space above to make it more obvious // !!! that loop is now a one-liner in this else branch // !!! where-as loop in branch above was multi-part HighPassColor = 0.5-0.5*(HighPassColor*0.25-ColorConvert::RGB_to_Luma(Source)); // Sharpen strength HighPassColor = lerp(0.5, HighPassColor, Mask); // Clamping sharpen /* // original HighPassColor = Clamp!=1f ? max(min(HighPassColor, Clamp), 1f-Clamp) : HighPassColor; */ // !!! Clamp in settings above is restricted to 0.5 to 1.0 // !!! 1.0 - Clamp is the low value, while Clamp is the high value // !!! so we can literally just use the clamp() func instead of min/max. // !!! not sure if author was trying to take advantage of some kind of // !!! compiler "cheat" using min/max instead of clamp to improve // !!! performance. doesn't make sense to min/max otherwise. HighPassColor = Clamp!=1f ? clamp(HighPassColor, 1f-Clamp, Clamp) : HighPassColor; float3 Sharpen = float3( Overlay(Source.r, HighPassColor), Overlay(Source.g, HighPassColor), Overlay(Source.b, HighPassColor) ); return GammaConvert::to_display( Preview // preview mode ON ? HighPassColor : Sharpen ); } } /*-------------. | :: Output :: | '-------------*/ technique FilmicAnamorphSharpen < ui_label = "Filmic Anamorphic Sharpen"; ui_tooltip = "This effect © 2018-2023 Jakub Maksymilian Fober\n" "Licensed under CC BY-SA 4.0"; > { pass { VertexShader = PostProcessVS; PixelShader = FilmicAnamorphSharpenPS; } }