/** Local Contrast PS, version 0.2.1 All rights (c) 2020 Jakub Maksymilian Fober (the Author). The Author provides this shader (the Work) under the Creative Commons CC BY-SA 3.0 license available online at http://creativecommons.org/licenses/by-sa/3.0/ For inquiries please contact jakub.m.fober@pm.me */ #include "ReShade.fxh" //////////// /// MENU /// //////////// #if !defined(LC_BLOCK) #define LC_BLOCK 8 #endif uniform bool CorrectGamma < ui_label = "Perform gamma correction"; ui_tootlip = "Applies S-curve to the corrected luma channel"; > = true; uniform int ContrastLimit < ui_type = "slider"; ui_label = "Contrast limit"; ui_min = 0; ui_max = 63; > = 40; /////////////// /// TEXTURE /// /////////////// // Local histogram values map texture LocalContrastMapBuffer { Width = BUFFER_WIDTH/LC_BLOCK; Height = BUFFER_HEIGHT/LC_BLOCK; Format = RG8; // R = histogram luma min // G = histogram luma max }; sampler LocalContrastMap { Texture = LocalContrastMapBuffer; }; // Point mapping back-buffer sampler sampler BackBuffer { Texture = ReShade::BackBufferTex; }; ///////////////// /// FUNCTIONS /// ///////////////// // RGB to YUV709 static const float3x3 ToYUV709 = float3x3( float3(0.2126, 0.7152, 0.0722), float3(-0.09991, -0.33609, 0.436), float3(0.615, -0.55861, -0.05639) ); // RGB to YUV601 static const float3x3 ToYUV601 = float3x3( float3(0.299, 0.587, 0.114), float3(-0.14713, -0.28886, 0.436), float3(0.615, -0.51499, -0.10001) ); // YUV709 to RGB static const float3x3 ToRGB709 = float3x3( float3(1, 0, 1.28033), float3(1, -0.21482, -0.38059), float3(1, 2.12798, 0) ); // YUV601 to RGB static const float3x3 ToRGB601 = float3x3( float3(1, 0, 1.13983), float3(1, -0.39465, -0.58060), float3(1, 2.03211, 0) ); // Overlay filter by Fubax // Generates smooth s-curve // input is between 0-1 float weight(float gradient) { float bottom = min(gradient, 0.5); float top = max(gradient, 0.5); return 2.0 *(bottom*bottom +top +top -top*top) -1.5; } // Convert map slider range float getContrastLimit() { return 1.0-ContrastLimit/127.0; } ////////////// /// SHADER /// ////////////// // Analyze histogram per image block void GetLocalHistogramPS( float4 pos : SV_Position, float2 texcoord : TEXCOORD, out float2 histogramStats : SV_Target // Contrast-limited adaptive histogram ){ // Initial values of the histogram histogramStats.s = 1.0; // Min histogramStats.t = 0.0; // Max float histogramMean = 0.0; // Average // Loop through image block and get histogram min, max and average const int halfBlock = LC_BLOCK/2; for (int y=-halfBlock; y { pass Local_Histogram { VertexShader = PostProcessVS; PixelShader = GetLocalHistogramPS; RenderTarget = LocalContrastMapBuffer; } pass Historgram_Normalization { VertexShader = PostProcessVS; PixelShader = LocalConstrastPS; } }