From 558afdd093ad0a523e145ec4194e43c2cd488c22 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Wed, 13 May 2020 21:13:43 +0200 Subject: [PATCH] Added Contrast Adaptive Sharpening (AMD) by Justin Marshal (IcedTech) --- RELEASE-NOTES.md | 2 + base/renderprogs/global.inc.hlsl | 59 +++++-- base/renderprogs/interactionSM.ps.hlsl | 18 ++- base/renderprogs/postprocess.ps.hlsl | 110 ++++++++++++- base/renderprogs/tonemap.ps.hlsl | 22 ++- neo/renderer/RenderProgs_embedded.h | 209 +++++++++++++++++++++++-- 6 files changed, 390 insertions(+), 30 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 9ecbf13a..98031aec 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -77,6 +77,8 @@ The main goal is that the new content looks the same in RBDOOM-3-BFG as in Blend * Added Blue Noise based Filmic Dithering by Timothy Lottes and Chromatic Aberration +* Added Contrast Adaptive Sharpening (AMD) from Just Marshal (IcedTech) + * Improved Shadow Mapping quality with Vogel Disk Sampling by Panos Karabelas and using dithering the result with Blue Noise magic by Alan Wolfe * Improved Screen Space Ambient Occlusion performance by enhancing the quality with Blue Noise and skipping the expensive extra bilateral filtering pass diff --git a/base/renderprogs/global.inc.hlsl b/base/renderprogs/global.inc.hlsl index a1ad7eb4..21dc060f 100644 --- a/base/renderprogs/global.inc.hlsl +++ b/base/renderprogs/global.inc.hlsl @@ -335,32 +335,39 @@ float3 Hash33( float3 p3 ) return fract( ( p3.xxy + p3.yxx ) * p3.zyx ); } -static float3 ditherRGB( float3 c, float2 uvSeed ) +static float3 ditherRGB( float3 color, float2 uvSeed, float quantSteps ) { // uniform noise - //float3 whiteNoise = Hash33( float3( uvSeed, rpJitterTexOffset.w ) ); + //float3 noise = Hash33( float3( uvSeed, rpJitterTexOffset.w ) ); - //float3 whiteNoise = float3( InterleavedGradientNoise( uvSeed ) ); - float3 whiteNoise = float3( InterleavedGradientNoiseAnim( uvSeed, rpJitterTexOffset.w ) ); + //float3 noise = float3( InterleavedGradientNoise( uvSeed ) ); + float3 noise = float3( InterleavedGradientNoiseAnim( uvSeed, rpJitterTexOffset.w ) ); // triangular noise [-0.5;1.5[ #if 1 - whiteNoise.x = RemapNoiseTriErp( whiteNoise.x ); - whiteNoise = whiteNoise * 2.0 - 0.5; + noise.x = RemapNoiseTriErp( noise.x ); + noise = noise * 2.0 - 0.5; #endif - whiteNoise = float3( whiteNoise.x ); + noise = float3( noise.x ); // quantize/truncate color and dither the result //float scale = exp2( float( TARGET_BITS ) ) - 1.0; // lets assume 2^3 bits = 8 - float scale = 255.0; + //float scale = 7.0; + //const float quantSteps = 8.0; + float scale = quantSteps - 1.0; - float3 color = floor( c * scale + whiteNoise ) / scale; + // apply dither + color += noise / ( quantSteps ); + + color = floor( color * scale ) / scale; + + //float3 color = c + whiteNoise / 255.0; #if defined( USE_LINEAR_RGB ) @@ -368,3 +375,37 @@ static float3 ditherRGB( float3 c, float2 uvSeed ) return color; } + +static float3 ditherChromaticBlueNoise( float3 color, float2 n, sampler2D blueTex ) +{ + // uniform noise + //float3 noise = Hash33( float3( n, rpJitterTexOffset.w ) ); + + //float3 noise = float3( InterleavedGradientNoise( n ) ); + //float3 noise = float3( InterleavedGradientNoiseAnim( n, rpJitterTexOffset.w ) ); + + // uv is screen position / sizeof blue noise image + float2 uv = n.xy * rpJitterTexOffset.xy; + float3 noise = tex2D( blueTex, uv ).rgb; + + // rpJitterTexOffset.w is frameTime % 64 + noise = fract( noise + c_goldenRatioConjugate * rpJitterTexOffset.w ); + + // triangular noise [-0.5;1.5[ + noise.x = RemapNoiseTriErp( noise.x ); + noise = noise * 2.0 - 0.5; + + //noise = float3( noise.x ); + + // quantize/truncate color and dither the result + //float scale = exp2( float( TARGET_BITS ) ) - 1.0; + + // lets assume 2^3 bits = 8 + float quantSteps = 255.0; + + //float3 color = floor( c * scale + noise ) / scale; + + color = floor( 0.5 + color * quantSteps - 0.5 + noise ) * ( 1.0 / ( quantSteps - 1.0 ) ); + + return color; +} diff --git a/base/renderprogs/interactionSM.ps.hlsl b/base/renderprogs/interactionSM.ps.hlsl index 102df2df..ab96bcd4 100644 --- a/base/renderprogs/interactionSM.ps.hlsl +++ b/base/renderprogs/interactionSM.ps.hlsl @@ -424,9 +424,15 @@ void main( PS_IN fragment, out PS_OUT result ) // rpDiffuseModifier contains light color multiplier half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz ); - //lightColor = ditherRGB( lightColor, fragment.position.xy ); - //lightColor *= sRGBToLinearRGB( lightFalloff.xyz );// * rpDiffuseModifier.xyz; + //lightFalloff.xyz = ditherRGB( lightFalloff.xyz, fragment.texcoord2.xy ); + //lightProj.xyz = ditherRGB( lightProj.xyz, fragment.texcoord3.xy ); + + //half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz ); + + //lightColor = ditherChromaticBlueNoise( lightColor, fragment.position.xy, samp6 ); + + //lightColor *= sRGBToLinearRGB( lightFalloff.xyz );// * rpDiffuseModifier.xyz; //lightColor = ditherRGB( lightColor, fragment.position.xy ); @@ -463,6 +469,10 @@ void main( PS_IN fragment, out PS_OUT result ) //half3 diffuseColor = mix( diffuseMap, F0, metal ) * rpDiffuseModifier.xyz; half3 diffuseBRDF = diffuseColor * lambert * ( rpDiffuseModifier.xyz ); - result.color.xyz = ( diffuseBRDF + specularBRDF ) * lightColor * fragment.color.rgb * shadow; - result.color.w = 1.0; + float3 color = ( diffuseBRDF + specularBRDF ) * lightColor * fragment.color.rgb * shadow; + + //color = ditherChromaticBlueNoise( color, fragment.position.xy, samp6 ); + + result.color.rgb = color; + result.color.a = 1.0; } diff --git a/base/renderprogs/postprocess.ps.hlsl b/base/renderprogs/postprocess.ps.hlsl index a84f64e7..8fbb611b 100644 --- a/base/renderprogs/postprocess.ps.hlsl +++ b/base/renderprogs/postprocess.ps.hlsl @@ -5,6 +5,7 @@ Doom 3 BFG Edition GPL Source Code Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 2015-2020 Robert Beckebans Copyright (C) 2014 Timothy Lottes (AMD) +Copyright (C) 2019 Justin Marshal (IcedTech) This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). @@ -61,7 +62,9 @@ struct PS_OUT #define Vibrance 0.5 // [-1.00 to 1.00] #define Vibrance_RGB_Balance float3( 1.0, 1.0, 1.0 ) -#define USE_DITHERING 1 +#define USE_CAS 1 + +#define USE_DITHERING 0 #define Dithering_QuantizationSteps 8.0 // 8.0 = 2 ^ 3 quantization bits #define Dithering_NoiseBoost 1.0 #define Dithering_Wide 1.0 @@ -460,6 +463,107 @@ void DitheringPass( inout float4 fragColor ) } +float Min3( float x, float y, float z ) +{ + return min( x, min( y, z ) ); +} + +float Max3( float x, float y, float z ) +{ + return max( x, max( y, z ) ); +} + + +float rcp( float v ) +{ + return 1.0 / v; +} + +void ContrastAdaptiveSharpeningPass( inout float4 fragColor ) +{ + float2 texcoord = fragment.texcoord0; + float Sharpness = 1; + + // fetch a 3x3 neighborhood around the pixel 'e', + // a b c + // d(e)f + // g h i + int2 bufferSize = textureSize( samp0, 0 ); + float pixelX = ( 1.0 / bufferSize.x ); + float pixelY = ( 1.0 / bufferSize.y ); + + float3 a = tex2D( samp0, texcoord + float2( -pixelX, -pixelY ) ).rgb; + float3 b = tex2D( samp0, texcoord + float2( 0.0, -pixelY ) ).rgb; + float3 c = tex2D( samp0, texcoord + float2( pixelX, -pixelY ) ).rgb; + float3 d = tex2D( samp0, texcoord + float2( -pixelX, 0.0 ) ).rgb; + float3 e = tex2D( samp0, texcoord ).rgb; + float3 f = tex2D( samp0, texcoord + float2( pixelX, 0.0 ) ).rgb; + float3 g = tex2D( samp0, texcoord + float2( -pixelX, pixelY ) ).rgb; + float3 h = tex2D( samp0, texcoord + float2( 0.0, pixelY ) ).rgb; + float3 i = tex2D( samp0, texcoord + float2( pixelX, pixelY ) ).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). + float mnR = Min3( Min3( d.r, e.r, f.r ), b.r, h.r ); + float mnG = Min3( Min3( d.g, e.g, f.g ), b.g, h.g ); + float mnB = Min3( Min3( d.b, e.b, f.b ), b.b, h.b ); + + float mnR2 = Min3( Min3( mnR, a.r, c.r ), g.r, i.r ); + float mnG2 = Min3( Min3( mnG, a.g, c.g ), g.g, i.g ); + float mnB2 = Min3( Min3( mnB, a.b, c.b ), g.b, i.b ); + mnR = mnR + mnR2; + mnG = mnG + mnG2; + mnB = mnB + mnB2; + + float mxR = Max3( Max3( d.r, e.r, f.r ), b.r, h.r ); + float mxG = Max3( Max3( d.g, e.g, f.g ), b.g, h.g ); + float mxB = Max3( Max3( d.b, e.b, f.b ), b.b, h.b ); + + float mxR2 = Max3( Max3( mxR, a.r, c.r ), g.r, i.r ); + float mxG2 = Max3( Max3( mxG, a.g, c.g ), g.g, i.g ); + float mxB2 = Max3( Max3( mxB, a.b, c.b ), g.b, i.b ); + mxR = mxR + mxR2; + mxG = mxG + mxG2; + mxB = mxB + mxB2; + + // Smooth minimum distance to signal limit divided by smooth max. + float rcpMR = rcp( mxR ); + float rcpMG = rcp( mxG ); + float rcpMB = rcp( mxB ); + + float ampR = saturate( min( mnR, 2.0 - mxR ) * rcpMR ); + float ampG = saturate( min( mnG, 2.0 - mxG ) * rcpMG ); + float ampB = saturate( min( mnB, 2.0 - mxB ) * rcpMB ); + + // Shaping amount of sharpening. + ampR = sqrt( ampR ); + ampG = sqrt( ampG ); + ampB = sqrt( ampB ); + + // Filter shape. + // 0 w 0 + // w 1 w + // 0 w 0 + float peak = -rcp( lerp( 8.0, 5.0, saturate( Sharpness ) ) ); + + float wR = ampR * peak; + float wG = ampG * peak; + float wB = ampB * peak; + + float rcpWeightR = rcp( 1.0 + 4.0 * wR ); + float rcpWeightG = rcp( 1.0 + 4.0 * wG ); + float rcpWeightB = rcp( 1.0 + 4.0 * wB ); + + float3 outColor = float3( saturate( ( b.r * wR + d.r * wR + f.r * wR + h.r * wR + e.r ) * rcpWeightR ), + saturate( ( b.g * wG + d.g * wG + f.g * wG + h.g * wG + e.g ) * rcpWeightG ), + saturate( ( b.b * wB + d.b * wB + f.b * wB + h.b * wB + e.b ) * rcpWeightB ) ); + + fragColor.rgb = outColor; +} + void main( PS_IN fragment, out PS_OUT result ) { float2 tCoords = fragment.texcoord0; @@ -479,6 +583,10 @@ void main( PS_IN fragment, out PS_OUT result ) VibrancePass( color ); #endif +#if USE_CAS + ContrastAdaptiveSharpeningPass( color ); +#endif + #if USE_DITHERING DitheringPass( color ); #endif diff --git a/base/renderprogs/tonemap.ps.hlsl b/base/renderprogs/tonemap.ps.hlsl index 94be7b43..1184ff76 100644 --- a/base/renderprogs/tonemap.ps.hlsl +++ b/base/renderprogs/tonemap.ps.hlsl @@ -69,6 +69,8 @@ float3 ACESFilm( float3 x ) return saturate( ( x * ( a * x + b ) ) / ( x * ( c * x + d ) + e ) ); } +#define USE_DITHERING 0 + void main( PS_IN fragment, out PS_OUT result ) { float2 tCoords = fragment.texcoord0; @@ -93,6 +95,14 @@ void main( PS_IN fragment, out PS_OUT result ) color.b = pow( color.b, gamma ); #endif +#if USE_DITHERING + + const float quantSteps = 256.0; + + // dither + color.rgb = ditherRGB( color.rgb, fragment.position.xy, quantSteps ); +#endif + #if defined(BRIGHTPASS) if( Y < 0.1 ) { @@ -197,7 +207,16 @@ void main( PS_IN fragment, out PS_OUT result ) color.rgb *= clamp( B, 0.0, 1.0 ); #endif -#if 1 +#if USE_DITHERING + // The following represents hardware linear->sRGB xform + // which happens on sRGB formatted render targets, + // except using a lot less bits/pixel. + color.rgb = max( float3( 0.0 ), color.rgb ); + color.rgb = Srgb3( color.rgb ); + color.rgb = floor( color.rgb * quantSteps ) * ( 1.0 / ( quantSteps - 1.0 ) ); + +#else + // convert from linear RGB to sRGB //float hdrGamma = 2.2; @@ -205,6 +224,7 @@ void main( PS_IN fragment, out PS_OUT result ) color.r = pow( color.r, gamma ); color.g = pow( color.g, gamma ); color.b = pow( color.b, gamma ); + #endif #if defined(HDR_DEBUG) diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 86cd0d94..41461684 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -349,32 +349,39 @@ static const cgShaderDef_t cg_renderprogs[] = " return fract( ( p3.xxy + p3.yxx ) * p3.zyx );\n" "}\n" "\n" - "static float3 ditherRGB( float3 c, float2 uvSeed )\n" + "static float3 ditherRGB( float3 color, float2 uvSeed, float quantSteps )\n" "{\n" " // uniform noise\n" - " //float3 whiteNoise = Hash33( float3( uvSeed, rpJitterTexOffset.w ) );\n" + " //float3 noise = Hash33( float3( uvSeed, rpJitterTexOffset.w ) );\n" "\n" - " //float3 whiteNoise = float3( InterleavedGradientNoise( uvSeed ) );\n" - " float3 whiteNoise = float3( InterleavedGradientNoiseAnim( uvSeed, rpJitterTexOffset.w ) );\n" + " //float3 noise = float3( InterleavedGradientNoise( uvSeed ) );\n" + " float3 noise = float3( InterleavedGradientNoiseAnim( uvSeed, rpJitterTexOffset.w ) );\n" "\n" "\n" " // triangular noise [-0.5;1.5[\n" "\n" "#if 1\n" - " whiteNoise.x = RemapNoiseTriErp( whiteNoise.x );\n" - " whiteNoise = whiteNoise * 2.0 - 0.5;\n" + " noise.x = RemapNoiseTriErp( noise.x );\n" + " noise = noise * 2.0 - 0.5;\n" "#endif\n" "\n" - " whiteNoise = float3( whiteNoise.x );\n" + " noise = float3( noise.x );\n" "\n" "\n" " // quantize/truncate color and dither the result\n" " //float scale = exp2( float( TARGET_BITS ) ) - 1.0;\n" "\n" " // lets assume 2^3 bits = 8\n" - " float scale = 255.0;\n" + " //float scale = 7.0;\n" + " //const float quantSteps = 8.0;\n" + " float scale = quantSteps - 1.0;\n" "\n" - " float3 color = floor( c * scale + whiteNoise ) / scale;\n" + " // apply dither\n" + " color += noise / ( quantSteps );\n" + "\n" + " color = floor( color * scale ) / scale;\n" + "\n" + " //float3 color = c + whiteNoise / 255.0;\n" "\n" "#if defined( USE_LINEAR_RGB )\n" "\n" @@ -383,6 +390,40 @@ static const cgShaderDef_t cg_renderprogs[] = " return color;\n" "}\n" "\n" + "static float3 ditherChromaticBlueNoise( float3 color, float2 n, sampler2D blueTex )\n" + "{\n" + " // uniform noise\n" + " //float3 noise = Hash33( float3( n, rpJitterTexOffset.w ) );\n" + "\n" + " //float3 noise = float3( InterleavedGradientNoise( n ) );\n" + " //float3 noise = float3( InterleavedGradientNoiseAnim( n, rpJitterTexOffset.w ) );\n" + "\n" + " // uv is screen position / sizeof blue noise image\n" + " float2 uv = n.xy * rpJitterTexOffset.xy;\n" + " float3 noise = tex2D( blueTex, uv ).rgb;\n" + "\n" + " // rpJitterTexOffset.w is frameTime % 64\n" + " noise = fract( noise + c_goldenRatioConjugate * rpJitterTexOffset.w );\n" + "\n" + " // triangular noise [-0.5;1.5[\n" + " noise.x = RemapNoiseTriErp( noise.x );\n" + " noise = noise * 2.0 - 0.5;\n" + "\n" + " //noise = float3( noise.x );\n" + "\n" + " // quantize/truncate color and dither the result\n" + " //float scale = exp2( float( TARGET_BITS ) ) - 1.0;\n" + "\n" + " // lets assume 2^3 bits = 8\n" + " float quantSteps = 255.0;\n" + "\n" + " //float3 color = floor( c * scale + noise ) / scale;\n" + "\n" + " color = floor( 0.5 + color * quantSteps - 0.5 + noise ) * ( 1.0 / ( quantSteps - 1.0 ) );\n" + "\n" + " return color;\n" + "}\n" + "\n" }, @@ -10294,9 +10335,15 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " // rpDiffuseModifier contains light color multiplier\n" " half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );\n" - " //lightColor = ditherRGB( lightColor, fragment.position.xy );\n" - " //lightColor *= sRGBToLinearRGB( lightFalloff.xyz );// * rpDiffuseModifier.xyz;\n" "\n" + " //lightFalloff.xyz = ditherRGB( lightFalloff.xyz, fragment.texcoord2.xy );\n" + " //lightProj.xyz = ditherRGB( lightProj.xyz, fragment.texcoord3.xy );\n" + "\n" + " //half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );\n" + "\n" + " //lightColor = ditherChromaticBlueNoise( lightColor, fragment.position.xy, samp6 );\n" + "\n" + " //lightColor *= sRGBToLinearRGB( lightFalloff.xyz );// * rpDiffuseModifier.xyz;\n" " //lightColor = ditherRGB( lightColor, fragment.position.xy );\n" "\n" "\n" @@ -10333,8 +10380,12 @@ static const cgShaderDef_t cg_renderprogs[] = " //half3 diffuseColor = mix( diffuseMap, F0, metal ) * rpDiffuseModifier.xyz;\n" " half3 diffuseBRDF = diffuseColor * lambert * ( rpDiffuseModifier.xyz );\n" "\n" - " result.color.xyz = ( diffuseBRDF + specularBRDF ) * lightColor * fragment.color.rgb * shadow;\n" - " result.color.w = 1.0;\n" + " float3 color = ( diffuseBRDF + specularBRDF ) * lightColor * fragment.color.rgb * shadow;\n" + "\n" + " //color = ditherChromaticBlueNoise( color, fragment.position.xy, samp6 );\n" + "\n" + " result.color.rgb = color;\n" + " result.color.a = 1.0;\n" "}\n" "\n" @@ -10732,6 +10783,7 @@ static const cgShaderDef_t cg_renderprogs[] = "Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.\n" "Copyright (C) 2015-2020 Robert Beckebans\n" "Copyright (C) 2014 Timothy Lottes (AMD)\n" + "Copyright (C) 2019 Justin Marshal (IcedTech)\n" "\n" "This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\").\n" "\n" @@ -10788,7 +10840,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#define Vibrance 0.5 // [-1.00 to 1.00]\n" "#define Vibrance_RGB_Balance float3( 1.0, 1.0, 1.0 )\n" "\n" - "#define USE_DITHERING 1\n" + "#define USE_CAS 1\n" + "\n" + "#define USE_DITHERING 0\n" "#define Dithering_QuantizationSteps 8.0 // 8.0 = 2 ^ 3 quantization bits\n" "#define Dithering_NoiseBoost 1.0\n" "#define Dithering_Wide 1.0\n" @@ -11187,6 +11241,107 @@ static const cgShaderDef_t cg_renderprogs[] = "}\n" "\n" "\n" + "float Min3( float x, float y, float z )\n" + "{\n" + " return min( x, min( y, z ) );\n" + "}\n" + "\n" + "float Max3( float x, float y, float z )\n" + "{\n" + " return max( x, max( y, z ) );\n" + "}\n" + "\n" + "\n" + "float rcp( float v )\n" + "{\n" + " return 1.0 / v;\n" + "}\n" + "\n" + "void ContrastAdaptiveSharpeningPass( inout float4 fragColor )\n" + "{\n" + " float2 texcoord = fragment.texcoord0;\n" + " float Sharpness = 1;\n" + "\n" + " // fetch a 3x3 neighborhood around the pixel 'e',\n" + " // a b c\n" + " // d(e)f\n" + " // g h i\n" + " int2 bufferSize = textureSize( samp0, 0 );\n" + " float pixelX = ( 1.0 / bufferSize.x );\n" + " float pixelY = ( 1.0 / bufferSize.y );\n" + "\n" + " float3 a = tex2D( samp0, texcoord + float2( -pixelX, -pixelY ) ).rgb;\n" + " float3 b = tex2D( samp0, texcoord + float2( 0.0, -pixelY ) ).rgb;\n" + " float3 c = tex2D( samp0, texcoord + float2( pixelX, -pixelY ) ).rgb;\n" + " float3 d = tex2D( samp0, texcoord + float2( -pixelX, 0.0 ) ).rgb;\n" + " float3 e = tex2D( samp0, texcoord ).rgb;\n" + " float3 f = tex2D( samp0, texcoord + float2( pixelX, 0.0 ) ).rgb;\n" + " float3 g = tex2D( samp0, texcoord + float2( -pixelX, pixelY ) ).rgb;\n" + " float3 h = tex2D( samp0, texcoord + float2( 0.0, pixelY ) ).rgb;\n" + " float3 i = tex2D( samp0, texcoord + float2( pixelX, pixelY ) ).rgb;\n" + "\n" + " // Soft min and max.\n" + " // a b c b\n" + " // d e f * 0.5 + d e f * 0.5\n" + " // g h i h\n" + " // These are 2.0x bigger (factored out the extra multiply).\n" + " float mnR = Min3( Min3( d.r, e.r, f.r ), b.r, h.r );\n" + " float mnG = Min3( Min3( d.g, e.g, f.g ), b.g, h.g );\n" + " float mnB = Min3( Min3( d.b, e.b, f.b ), b.b, h.b );\n" + "\n" + " float mnR2 = Min3( Min3( mnR, a.r, c.r ), g.r, i.r );\n" + " float mnG2 = Min3( Min3( mnG, a.g, c.g ), g.g, i.g );\n" + " float mnB2 = Min3( Min3( mnB, a.b, c.b ), g.b, i.b );\n" + " mnR = mnR + mnR2;\n" + " mnG = mnG + mnG2;\n" + " mnB = mnB + mnB2;\n" + "\n" + " float mxR = Max3( Max3( d.r, e.r, f.r ), b.r, h.r );\n" + " float mxG = Max3( Max3( d.g, e.g, f.g ), b.g, h.g );\n" + " float mxB = Max3( Max3( d.b, e.b, f.b ), b.b, h.b );\n" + "\n" + " float mxR2 = Max3( Max3( mxR, a.r, c.r ), g.r, i.r );\n" + " float mxG2 = Max3( Max3( mxG, a.g, c.g ), g.g, i.g );\n" + " float mxB2 = Max3( Max3( mxB, a.b, c.b ), g.b, i.b );\n" + " mxR = mxR + mxR2;\n" + " mxG = mxG + mxG2;\n" + " mxB = mxB + mxB2;\n" + "\n" + " // Smooth minimum distance to signal limit divided by smooth max.\n" + " float rcpMR = rcp( mxR );\n" + " float rcpMG = rcp( mxG );\n" + " float rcpMB = rcp( mxB );\n" + "\n" + " float ampR = saturate( min( mnR, 2.0 - mxR ) * rcpMR );\n" + " float ampG = saturate( min( mnG, 2.0 - mxG ) * rcpMG );\n" + " float ampB = saturate( min( mnB, 2.0 - mxB ) * rcpMB );\n" + "\n" + " // Shaping amount of sharpening.\n" + " ampR = sqrt( ampR );\n" + " ampG = sqrt( ampG );\n" + " ampB = sqrt( ampB );\n" + "\n" + " // Filter shape.\n" + " // 0 w 0\n" + " // w 1 w\n" + " // 0 w 0\n" + " float peak = -rcp( lerp( 8.0, 5.0, saturate( Sharpness ) ) );\n" + "\n" + " float wR = ampR * peak;\n" + " float wG = ampG * peak;\n" + " float wB = ampB * peak;\n" + "\n" + " float rcpWeightR = rcp( 1.0 + 4.0 * wR );\n" + " float rcpWeightG = rcp( 1.0 + 4.0 * wG );\n" + " float rcpWeightB = rcp( 1.0 + 4.0 * wB );\n" + "\n" + " float3 outColor = float3( saturate( ( b.r * wR + d.r * wR + f.r * wR + h.r * wR + e.r ) * rcpWeightR ),\n" + " saturate( ( b.g * wG + d.g * wG + f.g * wG + h.g * wG + e.g ) * rcpWeightG ),\n" + " saturate( ( b.b * wB + d.b * wB + f.b * wB + h.b * wB + e.b ) * rcpWeightB ) );\n" + "\n" + " fragColor.rgb = outColor;\n" + "}\n" + "\n" "void main( PS_IN fragment, out PS_OUT result )\n" "{\n" " float2 tCoords = fragment.texcoord0;\n" @@ -11206,6 +11361,10 @@ static const cgShaderDef_t cg_renderprogs[] = " VibrancePass( color );\n" "#endif\n" "\n" + "#if USE_CAS\n" + " ContrastAdaptiveSharpeningPass( color );\n" + "#endif\n" + "\n" "#if USE_DITHERING\n" " DitheringPass( color );\n" "#endif\n" @@ -13599,6 +13758,8 @@ static const cgShaderDef_t cg_renderprogs[] = " return saturate( ( x * ( a * x + b ) ) / ( x * ( c * x + d ) + e ) );\n" "}\n" "\n" + "#define USE_DITHERING 0\n" + "\n" "void main( PS_IN fragment, out PS_OUT result )\n" "{\n" " float2 tCoords = fragment.texcoord0;\n" @@ -13623,6 +13784,14 @@ static const cgShaderDef_t cg_renderprogs[] = " color.b = pow( color.b, gamma );\n" "#endif\n" "\n" + "#if USE_DITHERING\n" + "\n" + " const float quantSteps = 256.0;\n" + "\n" + " // dither\n" + " color.rgb = ditherRGB( color.rgb, fragment.position.xy, quantSteps );\n" + "#endif\n" + "\n" "#if defined(BRIGHTPASS)\n" " if( Y < 0.1 )\n" " {\n" @@ -13727,7 +13896,16 @@ static const cgShaderDef_t cg_renderprogs[] = " color.rgb *= clamp( B, 0.0, 1.0 );\n" "#endif\n" "\n" - "#if 1\n" + "#if USE_DITHERING\n" + " // The following represents hardware linear->sRGB xform\n" + " // which happens on sRGB formatted render targets,\n" + " // except using a lot less bits/pixel.\n" + " color.rgb = max( float3( 0.0 ), color.rgb );\n" + " color.rgb = Srgb3( color.rgb );\n" + " color.rgb = floor( color.rgb * quantSteps ) * ( 1.0 / ( quantSteps - 1.0 ) );\n" + "\n" + "#else\n" + "\n" " // convert from linear RGB to sRGB\n" "\n" " //float hdrGamma = 2.2;\n" @@ -13735,6 +13913,7 @@ static const cgShaderDef_t cg_renderprogs[] = " color.r = pow( color.r, gamma );\n" " color.g = pow( color.g, gamma );\n" " color.b = pow( color.b, gamma );\n" + "\n" "#endif\n" "\n" "#if defined(HDR_DEBUG)\n"