Skip to content

Instantly share code, notes, and snippets.

@hibiyasleep
Last active February 18, 2024 15:05
Show Gist options
  • Save hibiyasleep/88d83af55650a45b8ea6fff22281d6c6 to your computer and use it in GitHub Desktop.
Save hibiyasleep/88d83af55650a45b8ea6fff22281d6c6 to your computer and use it in GitHub Desktop.
Histogram Pixel Shader for ReShade 3/4
/**
* Copyright (C) 2015-2016 Ganossa (mediehawk@gmail.com)
*
* 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