Last active
February 18, 2024 15:05
-
-
Save hibiyasleep/88d83af55650a45b8ea6fff22281d6c6 to your computer and use it in GitHub Desktop.
Histogram Pixel Shader for ReShade 3/4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Copyright (C) 2015-2016 Ganossa ([email protected]) | |
* | |
* 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 with restriction, including without limitation the rights to | |
* use 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 the permission notices (this and below) shall | |
* be included in all copies or substantial portions of the Software. | |
* | |
* Permission needs to be specifically granted by the author of the software 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 copy, modify, merge, publish, distribute, and/or | |
* sublicense the Software, and subject to the following conditions: | |
* | |
* The above copyright notice and the permission notices (this and above) 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. | |
*/ | |
// ????-??-?? / Ported to Reshade 3 / v00d00m4n | |
// 2021-01-19 / code rewrite and feature updates / hibiyasleep | |
// 2021-05-12 / press Ctrl/Alt key to temporally switch mode, split Sample/Palette resolution / hibiyasleep | |
#include "ReShade.fxh" | |
uniform bool Histogram_Mix < | |
ui_tooltip = "Mixes the colors in the histogram."; | |
> = true; | |
uniform bool Histogram_View < | |
ui_tooltip = "Temporal non-mix viewmode switch."; | |
> = true; | |
// not using configuration UI because it's required from texture declaration. | |
#ifndef Histogram_Sample_Resolution | |
#define Histogram_Sample_Resolution 256f | |
#endif | |
#ifndef Histogram_Palette_Resolution | |
#define Histogram_Palette_Resolution 128f | |
#endif | |
//uniform int Histogram_Resolution < | |
// ui_type = "drag"; | |
// ui_min = 32; ui_max = 1024; | |
// ui_tooltip = "Adjust sample resolution (affects performance)"; | |
//> = 256; | |
uniform bool Histogram_Ctrl_Down < | |
source = "key"; | |
keycode = 0x11; | |
mode = ""; | |
>; | |
uniform bool Histogram_Alt_Down < | |
source = "key"; | |
keycode = 0x12; | |
mode = ""; | |
>; | |
uniform int Histogram_ScaleY < | |
ui_type = "drag"; | |
ui_min = 1; ui_max = 100; | |
ui_tooltip = "Y axis scaling of histogram."; | |
> = 25; | |
uniform float2 Histogram_Size < | |
ui_type = "drag"; | |
ui_min = 0f; ui_step = 0.0001f; ui_max = 1f; | |
ui_tooltip = "Size of histogram shown."; | |
> = float2(0.25f, 0.25f); | |
uniform float2 Histogram_Position < | |
ui_type = "drag"; | |
ui_min = 0f; ui_step = 0.0001f; ui_max = 1f; | |
ui_tooltip = "Left-top position of histogram shown."; | |
> = float2(0f, 0f); | |
uniform float Histogram_BackgroundBlend < | |
ui_type = "drag"; | |
ui_min = 0; ui_max = 1; | |
ui_tooltip = "Transparency of histogram background."; | |
> = 0.5f; | |
uniform float Histogram_Antialias < | |
ui_type = "drag"; | |
ui_min = 1f; ui_step = 0.5f; ui_max = 8f; | |
ui_tooltip = "Count of pixels to anti-alias the edge of histogram."; | |
> = 2f; | |
texture2D Histogram_detectIntTex < | |
pooled = true; | |
> { | |
Width = Histogram_Sample_Resolution; | |
Height = Histogram_Sample_Resolution; | |
Format = RGBA32F; | |
MagFilter = LINEAR; | |
MinFilter = LINEAR; | |
MipFilter = LINEAR; | |
}; | |
sampler2D Histogram_detectIntColor { Texture = Histogram_detectIntTex; }; | |
texture2D Histogram_detectLowTex < | |
pooled = true; | |
> { | |
Width = Histogram_Palette_Resolution; | |
Height = 1; | |
Format = RGBA32F; | |
}; | |
sampler2D Histogram_detectLowColor { Texture = Histogram_detectLowTex; }; | |
#define GAMMA_BRIGHTNESS(data) (0.299f * data.r + 0.587f * data.g + 0.114f * data.b) | |
float4 PS_Histogram_DetectInt(float4 vpos: SV_Position, float2 texcoord: TEXCOORD): SV_Target { | |
return tex2D(ReShade::BackBuffer, texcoord); | |
} | |
void PS_Histogram_DetectLow(float4 vpos: SV_Position, float2 texcoord: TEXCOORD, out float4 detectLow: SV_Target) { | |
int bucket = trunc(texcoord.x * Histogram_Palette_Resolution); | |
detectLow = float4(0, 0, 0, 1); | |
float3 level; | |
int3 detect; | |
[fastopt][loop] | |
for(int i = 0; i <= Histogram_Sample_Resolution; i++) { | |
[fastopt][loop] | |
for(int j = 0; j <= Histogram_Sample_Resolution; j++) { | |
level = trunc(tex2D(Histogram_detectIntColor, float2(j, i) / Histogram_Sample_Resolution).rgb * Histogram_Palette_Resolution); | |
detect.rgb += (bucket == level); | |
} | |
} | |
detectLow.rgb = detect / Histogram_Sample_Resolution / Histogram_Sample_Resolution; | |
} | |
float4 PS_Histogram_Display(float4 vpos: SV_Position, float2 texcoord: TEXCOORD): SV_Target { | |
float2 pwd = (texcoord - Histogram_Position) / Histogram_Size; | |
if(pwd.x < 0 || pwd.y < 0 || 1 < pwd.x || 1 < pwd.y) | |
discard; | |
float4 backbuf = tex2D(ReShade::BackBuffer, texcoord) * Histogram_BackgroundBlend; | |
float4 r = float4(0, 0, 0, 1); | |
float4 data; | |
if(Histogram_Ctrl_Down) { | |
data = 1 - tex2D(Histogram_detectLowColor, pwd.x) * Histogram_ScaleY; | |
r = pwd.y - GAMMA_BRIGHTNESS(data); | |
} else if(Histogram_Mix ^ Histogram_Alt_Down) { | |
data = 1 - tex2D(Histogram_detectLowColor, pwd.x) * Histogram_ScaleY; | |
r = pwd.y - data.rgb; | |
} else { | |
float localpwd; | |
int partindex; | |
if(Histogram_View) { | |
data = 1 - tex2D(Histogram_detectLowColor, pwd.x) * Histogram_ScaleY; | |
localpwd = (pwd.y * 4) % 1; | |
partindex = (pwd.y * 4) / 1; | |
} else { | |
data = 1 - tex2D(Histogram_detectLowColor, (pwd.x * 2) % 1) * Histogram_ScaleY; | |
localpwd = (pwd.y * 2) % 1; | |
partindex = (pwd.x > 0.5) + 2 * (pwd.y > 0.5); | |
}; | |
if(partindex == 0) { | |
r = GAMMA_BRIGHTNESS(data); | |
} else { | |
r = float3( | |
partindex == 1? data.r : 1, | |
partindex == 2? data.g : 1, | |
partindex == 3? data.b : 1 | |
); | |
} | |
r = localpwd - r; | |
} | |
// BUFFER_HEIGHT | |
// * Histogram_Size.y <- actual size in pixels | |
// / Histogram_Antialias <- ? | |
return backbuf + clamp(r * BUFFER_HEIGHT * Histogram_Size.y / Histogram_Antialias, 0, 1); | |
} | |
technique Histogram_Source { | |
pass Histogram_DetectInt { | |
VertexShader = PostProcessVS; | |
PixelShader = PS_Histogram_DetectInt; | |
RenderTarget = Histogram_detectIntTex; | |
} | |
pass Histogram_DetectLow { | |
VertexShader = PostProcessVS; | |
PixelShader = PS_Histogram_DetectLow; | |
RenderTarget = Histogram_detectLowTex; | |
//ClearRenderTargets = true; | |
} | |
} | |
technique Histogram_Display { | |
pass Histogram_Display { | |
VertexShader = PostProcessVS; | |
PixelShader = PS_Histogram_Display; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment