/** * DepthSharpenconstDof v1.11 * by OVNI * * Based on : * LumaSharpen version 1.5.0 * by Christian Cann Schuldt Jensen ~ CeeJay.dk * * It blurs the original pixel with the surrounding pixels and then subtracts this blur to sharpen the image. * It does this in luma to avoid color artifacts and allows limiting the maximum sharpning to avoid or lessen halo artifacts. * This is similar to using Unsharp Mask in Photoshop. * * OVNI modifications : * - depth test for sharpening so it doesn't generate too much aliasing * - reuse blur do implement poor man's const DoF * - reuse blur do implement poor man's antialiasing between objects (trees) and sky * * * Copyright (c) 2014 CeeJayDK * * 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. */ // Lightly optimized by Marot Satil for the GShade project. uniform float sharp_strength < ui_type = "slider"; ui_min = 0.1; ui_max = 10.0; ui_tooltip = "Strength of the sharpening"; > = 3.0; uniform float sharp_clamp < ui_type = "slider"; ui_min = 0.0; ui_max = 1.0; ui_step = 0.005; ui_tooltip = "Limits maximum amount of sharpening a pixel receives"; > = 0.035; uniform int pattern < ui_type = "combo"; ui_items = "Fast\0Normal\0Wider\0Pyramid shaped\0"; ui_tooltip = "Choose a sample pattern"; > = 2; uniform float offset_bias < ui_type = "slider"; ui_min = 0.0; ui_max = 6.0; ui_tooltip = "Offset bias adjusts the radius of the sampling pattern. I designed the pattern for offset_bias 1.0, but feel free to experiment."; > = 1.0; uniform bool debug < ui_tooltip = "Debug view."; > = false; uniform float sharpenEndDepth < ui_type = "slider"; ui_min = 0.0; ui_max = 1.0; ui_tooltip = "Max depth for sharpening"; > = 0.3; uniform float sharpenMaxDeltaDepth < ui_type = "slider"; ui_min = 0.0; ui_max = 1.0; ui_tooltip = "Max depth difference between 2 samples to apply sharpen filter."; > = 0.0025; uniform float dofStartDepth < ui_type = "slider"; ui_min = 0.0; ui_max = 1.0; ui_tooltip = "Min depth for Depth of Field effect."; > = 0.7; uniform float dofTransitionDepth < ui_type = "slider"; ui_min = 0.0; ui_max = 1.0; ui_tooltip = "Distance of interpolation between no blur and full blur."; > = 0.3; uniform float contourBlurMinDeltaDepth < ui_type = "slider"; ui_min = 0.0; ui_max = 1.0; ui_tooltip = "Min depth difference between 2 samples to apply blur filter"; > = 0.05; uniform float contourDepthExponent < ui_type = "slider"; ui_min = 0.0; ui_max = 4.0; ui_tooltip = "Influence of depth on coutour bluring (higher value will reduce blur on close object's contours)"; > = 2.0; //Used to avoid bluring the sky (espetially stars/moon) and some UI parts, This should be as high as possible. uniform float maxDepth = 0.999; #include "ReShade.fxh" /*-----------------------------------------------------------. / Developer settings / '-----------------------------------------------------------*/ #define CoefLuma float3(0.2126, 0.7152, 0.0722) // BT.709 & sRBG luma coefficient (Monitors and HD Television) //#define CoefLuma float3(0.299, 0.587, 0.114) // BT.601 luma coefficient (SD Television) //#define CoefLuma float3(1.0/3.0, 1.0/3.0, 1.0/3.0) // Equal weight coefficient /*-----------------------------------------------------------. / Main code / '-----------------------------------------------------------*/ float3 DepthSharpenconstDofPass(float4 position : SV_Position, float2 tex : TEXCOORD) : SV_Target { // -- Get the original pixel -- const float3 ori = tex2D(ReShade::BackBuffer, tex).rgb; /*-----------------------------------------------------------. / Determine if we should sharpen / blur '-----------------------------------------------------------*/ const float depth = ReShade::GetLinearizedDepth(tex).r; if( depth > maxDepth ) return ori; const float depthTL = ReShade::GetLinearizedDepth( tex + float2(-BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y) ).r; const float depthTR = ReShade::GetLinearizedDepth( tex + float2(BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y) ).r; const float deltaA = abs(depth-depthTL); const float deltaB = abs(depth-depthTR); float blurPercent = 0; bool bluredEdge = false; const bool shouldSharpen = depth < sharpenEndDepth && deltaA <= sharpenMaxDeltaDepth && deltaB <= sharpenMaxDeltaDepth; if( deltaA >= contourBlurMinDeltaDepth || deltaB >= contourBlurMinDeltaDepth ) { blurPercent = saturate( (deltaA+deltaB)/2.0 * 10 ) * pow(abs(depth), contourDepthExponent); bluredEdge = true; } else blurPercent = (depth - dofStartDepth)/dofTransitionDepth; if( blurPercent <= 0 && !shouldSharpen ) if (debug) return float3(0,1,0)*ori; else return ori; // -- Combining the strength and luma multipliers -- float3 sharp_strength_luma = (CoefLuma * sharp_strength); //I'll be combining even more multipliers with it later on /*-----------------------------------------------------------. / Sampling patterns / '-----------------------------------------------------------*/ float3 blur_ori; // [ NW, , NE ] Each texture lookup (except ori) // [ ,ori, ] samples 4 pixels // [ SW, , SE ] // -- Pattern 1 -- A (fast) 7 tap gaussian using only 2+1 texture fetches. if (pattern == 0) { // -- Gaussian filter -- // [ 1/9, 2/9, ] [ 1 , 2 , ] // [ 2/9, 8/9, 2/9] = [ 2 , 8 , 2 ] // [ , 2/9, 1/9] [ , 2 , 1 ] blur_ori = tex2D(ReShade::BackBuffer, tex + (BUFFER_PIXEL_SIZE / 3.0) * offset_bias).rgb; // North West blur_ori += tex2D(ReShade::BackBuffer, tex + (-BUFFER_PIXEL_SIZE / 3.0) * offset_bias).rgb; // South East blur_ori /= 2; //Divide by the number of texture fetches sharp_strength_luma *= 1.5; // Adjust strength to aproximate the strength of pattern 2 } // -- Pattern 2 -- A 9 tap gaussian using 4+1 texture fetches. if (pattern == 1) { // -- Gaussian filter -- // [ .25, .50, .25] [ 1 , 2 , 1 ] // [ .50, 1, .50] = [ 2 , 4 , 2 ] // [ .25, .50, .25] [ 1 , 2 , 1 ] blur_ori = tex2D(ReShade::BackBuffer, tex + float2(BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y) * 0.5 * offset_bias).rgb; // South East blur_ori += tex2D(ReShade::BackBuffer, tex - BUFFER_PIXEL_SIZE * 0.5 * offset_bias).rgb; // South West blur_ori += tex2D(ReShade::BackBuffer, tex + BUFFER_PIXEL_SIZE * 0.5 * offset_bias).rgb; // North East blur_ori += tex2D(ReShade::BackBuffer, tex - float2(BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y) * 0.5 * offset_bias).rgb; // North West blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches } // -- Pattern 3 -- An experimental 17 tap gaussian using 4+1 texture fetches. if (pattern == 2) { // -- Gaussian filter -- // [ , 4 , 6 , , ] // [ ,16 ,24 ,16 , 4 ] // [ 6 ,24 , ,24 , 6 ] // [ 4 ,16 ,24 ,16 , ] // [ , , 6 , 4 , ] blur_ori = tex2D(ReShade::BackBuffer, tex + BUFFER_PIXEL_SIZE * float2(0.4, -1.2) * offset_bias).rgb; // South South East blur_ori += tex2D(ReShade::BackBuffer, tex - BUFFER_PIXEL_SIZE * float2(1.2, 0.4) * offset_bias).rgb; // West South West blur_ori += tex2D(ReShade::BackBuffer, tex + BUFFER_PIXEL_SIZE * float2(1.2, 0.4) * offset_bias).rgb; // East North East blur_ori += tex2D(ReShade::BackBuffer, tex - BUFFER_PIXEL_SIZE * float2(0.4, -1.2) * offset_bias).rgb; // North North West blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches sharp_strength_luma *= 0.51; } // -- Pattern 4 -- A 9 tap high pass (pyramid filter) using 4+1 texture fetches. if (pattern == 3) { // -- Gaussian filter -- // [ .50, .50, .50] [ 1 , 1 , 1 ] // [ .50, , .50] = [ 1 , , 1 ] // [ .50, .50, .50] [ 1 , 1 , 1 ] blur_ori = tex2D(ReShade::BackBuffer, tex + float2(0.5 * BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y * offset_bias)).rgb; // South South East blur_ori += tex2D(ReShade::BackBuffer, tex + float2(offset_bias * -BUFFER_PIXEL_SIZE.x, 0.5 * -BUFFER_PIXEL_SIZE.y)).rgb; // West South West blur_ori += tex2D(ReShade::BackBuffer, tex + float2(offset_bias * BUFFER_PIXEL_SIZE.x, 0.5 * BUFFER_PIXEL_SIZE.y)).rgb; // East North East blur_ori += tex2D(ReShade::BackBuffer, tex + float2(0.5 * -BUFFER_PIXEL_SIZE.x, BUFFER_PIXEL_SIZE.y * offset_bias)).rgb; // North North West blur_ori /= 4.0; //Divide by the number of texture fetches sharp_strength_luma *= 0.666; // Adjust strength to aproximate the strength of pattern 2 } /*-----------------------------------------------------------. / '-----------------------------------------------------------*/ // Apply blur if needed if( blurPercent > 0 ) { blurPercent = saturate(blurPercent); if( debug ) if (bluredEdge) return blurPercent * float3(0,0,1); else return blurPercent * float3(1,0,0); return blur_ori*blurPercent + ori*(1.0-blurPercent); } // Modify sharping Strength depending of depth if( sharpenEndDepth < 1.0 ) sharp_strength_luma *= 1.0 - depth/sharpenEndDepth; // depth reranged in [0,sharpenEndDepth] /*-----------------------------------------------------------. / Sharpen / '-----------------------------------------------------------*/ // -- Calculate the sharpening -- const float3 sharp = ori - blur_ori; //Subtracting the blurred image from the original image // -- Adjust strength of the sharpening and clamp it-- const float4 sharp_strength_luma_clamp = float4(sharp_strength_luma * (0.5 / sharp_clamp),0.5); //Roll part of the clamp into the dot float sharp_luma = saturate(dot(float4(sharp,1.0), sharp_strength_luma_clamp)); //Calculate the luma, adjust the strength, scale up and clamp sharp_luma = (sharp_clamp * 2.0) * sharp_luma - sharp_clamp; //scale down /*-----------------------------------------------------------. / Returning the output / '-----------------------------------------------------------*/ if (debug) return saturate(0.5 + (sharp_luma * 4.0)).rrr; // -- Combining the values to get the final sharpened pixel -- return ori + sharp_luma; // Add the sharpening to the the original. } technique DepthSharpenconstDof { pass { VertexShader = PostProcessVS; PixelShader = DepthSharpenconstDofPass; } }