Advanced HSL (Per-Hue) Shifting
- TreyM
- Topic Author
Less
More
This is a per-hue HSL shifting shader written by my friend, kingeric1992. I'm releasing the shader here with his permission.
This shader gives the ability to shift the color and adjust the saturation of individual hues (Red, Orange, Yellow, Green, Cyan, Blue, Purple, Magenta) on a per-hue basis. This allows for advanced color grading when used in conjunction with the Lift, Gamma, Gain shader.
Shader code:
This shader gives the ability to shift the color and adjust the saturation of individual hues (Red, Orange, Yellow, Green, Cyan, Blue, Purple, Magenta) on a per-hue basis. This allows for advanced color grading when used in conjunction with the Lift, Gamma, Gain shader.
Shader code:
Warning: Spoiler!
////////////////////////////////////////////////////
// Advanced HSL Shifting //
// Author: kingeric1992 //
////////////////////////////////////////////////////
#include "ReShade.fxh"
// UI ELEMENTS /////////////////////////////////////
////////////////////////////////////////////////////
uniform bool EnableHSL <
ui_category = " \n";
ui_label = "Toggle HSL";
> = true;
uniform float3 HUERed <
ui_type = "color";
ui_label="Red";
ui_tooltip =
"Be careful. Do not to push too far!\n"
"You can only shift as far as the next\n"
"or previous hue's current value.\n\n"
"Editing is easiest using the widget\n"
"Click the colored box to open it.\n\n"
"RGB Red Default Value:\n"
"255 : R: 191, G: 64, B: 64\n"
"0.00: R:0.750, G:0.250, B:0.250";
> = float3(0.75, 0.25, 0.25);
uniform float3 HUEOrange <
ui_type = "color";
ui_label="Orange";
ui_tooltip =
"Be careful. Do not to push too far!\n"
"You can only shift as far as the next\n"
"or previous hue's current value.\n\n"
"Editing is easiest using the widget\n"
"Click the colored box to open it.\n\n"
"RGB Orange Default Value:\n"
"255 : R: 191, G: 128, B: 64\n"
"0.00: R:0.750, G:0.500, B:0.250";
> = float3(0.75, 0.50, 0.25);
uniform float3 HUEYellow <
ui_type = "color";
ui_label="Yellow";
ui_tooltip =
"Be careful. Do not to push too far!\n"
"You can only shift as far as the next\n"
"or previous hue's current value.\n\n"
"Editing is easiest using the widget\n"
"Click the colored box to open it.\n\n"
"RGB Yellow Default Value:\n"
"255 : R: 191, G: 191, B: 64\n"
"0.00: R:0.750, G:0.750, B:0.250";
> = float3(0.75, 0.75, 0.25);
uniform float3 HUEGreen <
ui_type = "color";
ui_label="Green";
ui_tooltip =
"Be careful. Do not to push too far!\n"
"You can only shift as far as the next\n"
"or previous hue's current value.\n\n"
"Editing is easiest using the widget\n"
"Click the colored box to open it.\n\n"
"RGB Green Default Value:\n"
"255 : R: 64, G: 191, B: 64\n"
"0.00: R:0.250, G:0.750, B:0.250";
> = float3(0.25, 0.75, 0.25);
uniform float3 HUECyan <
ui_type = "color";
ui_label="Cyan";
ui_tooltip =
"Be careful. Do not to push too far!\n"
"You can only shift as far as the next\n"
"or previous hue's current value.\n\n"
"Editing is easiest using the widget\n"
"Click the colored box to open it.\n\n"
"RGB Cyan Default Value:\n"
"255 : R: 64, G: 191, B: 191\n"
"0.00: R:0.250, G:0.750, B:0.750";
> = float3(0.25, 0.75, 0.75);
uniform float3 HUEBlue <
ui_type = "color";
ui_label="Blue";
ui_tooltip =
"Be careful. Do not to push too far!\n"
"You can only shift as far as the next\n"
"or previous hue's current value.\n\n"
"Editing is easiest using the widget\n"
"Click the colored box to open it.\n\n"
"RGB Blue Default Value:\n"
"255 : R: 64, G: 64, B: 191\n"
"0.00: R:0.250, G:0.250, B:0.750";
> = float3(0.25, 0.25, 0.75);
uniform float3 HUEPurple <
ui_type = "color";
ui_label="Purple";
ui_tooltip =
"Be careful. Do not to push too far!\n"
"You can only shift as far as the next\n"
"or previous hue's current value.\n\n"
"Editing is easiest using the widget\n"
"Click the colored box to open it.\n\n"
"RGB Purple Default Value:\n"
"255 : R: 128, G: 64, B: 191\n"
"0.00: R:0.500, G:0.250, B:0.750";
> = float3(0.50, 0.25, 0.75);
uniform float3 HUEMagenta <
ui_type = "color";
ui_label="Magenta";
ui_tooltip =
"Be careful. Do not to push too far!\n"
"You can only shift as far as the next\n"
"or previous hue's current value.\n\n"
"Editing is easiest using the widget\n"
"Click the colored box to open it.\n\n"
"RGB Magenta Default Value:\n"
"255 : R: 191, G: 64, B: 191\n"
"0.00: R:0.750, G:0.250, B:0.750";
> = float3(0.75, 0.25, 0.75);
////////////////////////////////////////////////////
// SETUP & FUNCTIONS ///////////////////////////////
////////////////////////////////////////////////////
static const float HSL_Threshold_Base = 0.05;
static const float HSL_Threshold_Curve = 1.0;
float3 RGB_to_HSL(float3 color) {
float3 HSL = 0.0f;
float M = max(color.r, max(color.g, color.b));
float C = M - min(color.r, min(color.g, color.b));
HSL.z = M - 0.5 * C;
if (C != 0.0f) {
float3 Delta = (color.brg - color.rgb) / C + float3(2.0f, 4.0f, 6.0f);
Delta *= step(M, color.gbr); //if max = rgb
HSL.x = frac(max(Delta.r, max(Delta.g, Delta.b)) / 6.0);
HSL.y = (HSL.z == 1)? 0.0: C/ (1 - abs( 2 * HSL.z - 1));
}
return HSL;
}
float3 Hue_to_RGB( float h) {
return saturate(float3( abs(h * 6.0f - 3.0f) - 1.0f,
2.0f - abs(h * 6.0f - 2.0f),
2.0f - abs(h * 6.0f - 4.0f)));
}
float3 HSL_to_RGB( float3 HSL ) {
return (Hue_to_RGB(HSL.x) - 0.5) * (1.0 - abs(2.0 * HSL.z - 1)) * HSL.y + HSL.z;
}
float LoC( float L0, float L1, float angle) {
return sqrt(L0*L0+L1*L1-2.0*L0*L1*cos(angle));
}
float3 HSLShift(float3 color) {
float3 hsl = RGB_to_HSL(color);
static const float4 node[9]= {
float4(HUERed, 0.0),//red
float4(HUEOrange, 30.0),
float4(HUEYellow, 60.0),
float4(HUEGreen, 120.0),
float4(HUECyan, 180.0),
float4(HUEBlue, 240.0),
float4(HUEPurple, 270.0),
float4(HUEMagenta, 300.0),
float4(HUERed, 360.0),//red
};
float base;
for(int i=0; i<8; i++) if(node[i].a < hsl.r*360.0 )base = i;
float w = saturate((hsl.r*360.0-node[base].a)/(node[base+1].a-node[base].a));
float3 H0 = RGB_to_HSL(node[base].rgb);
float3 H1 = RGB_to_HSL(node[base+1].rgb);
H1.x += (H1.x < H0.x)? 1.0:0.0;
float3 shift = frac(lerp( H0, H1 , w));
w = max( hsl.g, 0.0)*max( 1.0-hsl.b, 0.0);
shift.b = (shift.b - 0.5)*(pow(w, HSL_Threshold_Curve)*(1.0-HSL_Threshold_Base)+HSL_Threshold_Base)*2.0;
return HSL_to_RGB(saturate(float3(shift.r, hsl.g*(shift.g*2.0), hsl.b*(1.0+shift.b))));
}
////////////////////////////////////////////////////
// PIXEL SHADER ////////////////////////////////////
////////////////////////////////////////////////////
float4 PS_HSLShift(float4 position : SV_Position, float2 txcoord : TexCoord) : SV_Target {
if (EnableHSL == 0) return tex2D(ReShade::BackBuffer, txcoord);
return float4(HSLShift(tex2D(ReShade::BackBuffer, txcoord).rgb), 1.0);
}
////////////////////////////////////////////////////
// TECHNIQUE ///////////////////////////////////////
////////////////////////////////////////////////////
technique HSLShift {
pass HSLPass {
VertexShader = PostProcessVS;
PixelShader = PS_HSLShift;
}
}
////////////////////////////////////////////////////
The following user(s) said Thank You: MakeNX, WalterDasTrevas, Marty, Rudy102, Hooka Tooka
Please Log in or Create an account to join the conversation.
- TreyM
- Topic Author
Less
More
crosire, I'm not sure how to request this to be added to the official repo, but I think this shader is very useful and might make a good addition.
The following user(s) said Thank You: WalterDasTrevas
Please Log in or Create an account to join the conversation.
- Marty McFly
Less
More
5 years 8 months ago #3
by Marty McFly
Replied by Marty McFly on topic Advanced HSL (Per-Hue) Shifting
That's exactly what Lightroom fx from qUINT can do
The following user(s) said Thank You: TreyM
Please Log in or Create an account to join the conversation.
I did not know that you can right-click and choose triangle color wheel. Wow
Please Log in or Create an account to join the conversation.
- crosire
Less
More
The following user(s) said Thank You: TreyM
Please Log in or Create an account to join the conversation.