Skip to content

Instantly share code, notes, and snippets.

@jeferwang
Last active May 12, 2022 04:02
Show Gist options
  • Save jeferwang/4e14425cbfaed8bc17cfce11e40ecb06 to your computer and use it in GitHub Desktop.
Save jeferwang/4e14425cbfaed8bc17cfce11e40ecb06 to your computer and use it in GitHub Desktop.
HLSL Color Transform: RGB/HSV/HSL, WhiteBalance
Color Transform 颜色转换/调整
HSV/RGB
HSL
WhiteBalance白平衡
//https://blog.csdn.net/haowenlai2008/article/details/99317027
// RGB每个分量转换成阴影中间调高光对应的权重
float3 transfer(float value)
{
float a = 64.0, b = 85.0, scale = 1.785;
float3 result;
float i = value * 255.0;
float shadows = clamp ((i - b) / -a + 0.5, 0.0, 1.0) * scale;
float midtones = clamp ((i - b) / a + 0.5, 0.0, 1.0) * clamp ((i + b - 255.0) / -a + .5, 0.0, 1.0) * scale;
float highlights = clamp (((255.0 - i) - b) / -a + 0.5, 0.0, 1.0) * scale;
result.r = shadows;
result.g = midtones;
result.b = highlights;
return result;
}
void main()
{
float4 base = texture2D(inputImageTexture, textureCoordinate);
float3 hsl = rgb2hsl(base.rgb);
float3 weight_r = transfer(base.r);
float3 weight_g = transfer(base.g);
float3 weight_b = transfer(base.b);
float3 color = float3(base.rgb * 255.0);
color.r += cyan_red_shadow * weight_r.r;
color.r += cyan_red_midtones * weight_r.g;
color.r += cyan_red_highlights * weight_r.b;
color.g += magenta_green_shadow * weight_g.r;
color.g += magenta_green_midtones * weight_g.g;
color.g += magenta_green_highlights * weight_g.b;
color.b += yellow_blue_shadow * weight_b.r;
color.b += yellow_blue_midtones * weight_b.g;
color.b += yellow_blue_highlights * weight_b.b;
color.r = clamp(color.r, 0.0, 255.0);
color.g = clamp(color.g, 0.0, 255.0);
color.b = clamp(color.b, 0.0, 255.0);
float3 hsl2 = rgb2hsl(color / 255.0);
hsl2.z = hsl.z;
gl_FragColor=float4(hsl2rgb(hsl2), base.a);
}
// https://blog.csdn.net/haowenlai2008/article/details/99317027
float3 hsl2rgb(float3 color)
{
float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
float3 p = abs(frac(color.xxx + K.xyz) * 6.0 - K.www);
return color.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), color.y);
}
// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl
float3 hsv2rgb(float3 InHSV)
{
float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
float3 p = abs(frac(InHSV.xxx + K.xyz) * 6.0 - K.www);
return InHSV.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), InHSV.y);
}
// https://blog.csdn.net/haowenlai2008/article/details/99317027
float3 rgb2hsl(float3 color){
float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
float4 p = lerp(float4(color.bg, K.wz), float4(color.gb, K.xy), step(color.b, color.g));
float4 q = lerp(float4(p.xyw, color.r), float4(color.r, p.yzx), step(p.x, color.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
if ( del_Max == 0 ) //This is a gray, no chroma...
{
H = 0;
S = 0;
}
else //Chromatic data...
{
if ( L < 0.5 ) {
S = del_Max / ( var_Max + var_Min );
}
else {
S = del_Max / ( 2 - var_Max - var_Min );
}
float del_R = ( ( ( var_Max - var_R ) / 6 ) + ( del_Max / 2 ) ) / del_Max;
float del_G = ( ( ( var_Max - var_G ) / 6 ) + ( del_Max / 2 ) ) / del_Max;
float del_B = ( ( ( var_Max - var_B ) / 6 ) + ( del_Max / 2 ) ) / del_Max;
if ( var_R == var_Max ) H = del_B - del_G;
else if ( var_G == var_Max ) H = ( 1 / 3 ) + del_R - del_B;
else if ( var_B == var_Max ) H = ( 2 / 3 ) + del_G - del_R;
if ( H < 0 ) H += 1;
if ( H > 1 ) H -= 1;
}
return float3(H, S, L);
// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl
float3 rgb2hsv(vec3 InRGB)
{
float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
float4 p = lerp(float4(InRGB.bg, K.wz), float4(InRGB.gb, K.xy), step(InRGB.b, InRGB.g));
float4 q = lerp(float4(p.xyw, InRGB.r), float4(InRGB.r, p.yzx), step(p.x, InRGB.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
// https://www.jianshu.com/p/7074fa4cb907
float3 WhiteBalance_float(float3 In, float Temperature, float Tint)
{
// Range ~[-1.67;1.67] works best
float t1 = Temperature * 10 / 6;
float t2 = Tint * 10 / 6;
// Get the CIE xy chromaticity of the reference white point.
// Note: 0.31271 = x value on the D65 white point
float x = 0.31271 - t1 * (t1 < 0 ? 0.1 : 0.05);
float standardIlluminantY = 2.87 * x - 3 * x * x - 0.27509507;
float y = standardIlluminantY + t2 * 0.05;
// Calculate the coefficients in the LMS space.
float3 w1 = float3(0.949237, 1.03542, 1.08728); // D65 white point
// CIExyToLMS
float Y = 1;
float X = Y * x / y;
float Z = Y * (1 - x - y) / y;
float L = 0.7328 * X + 0.4296 * Y - 0.1624 * Z;
float M = -0.7036 * X + 1.6975 * Y + 0.0061 * Z;
float S = 0.0030 * X + 0.0136 * Y + 0.9834 * Z;
float3 w2 = float3(L, M, S);
float3 balance = float3(w1.x / w2.x, w1.y / w2.y, w1.z / w2.z);
float3x3 LIN_2_LMS_MAT = {
3.90405e-1, 5.49941e-1, 8.92632e-3,
7.08416e-2, 9.63172e-1, 1.35775e-3,
2.31082e-2, 1.28021e-1, 9.36245e-1
};
float3x3 LMS_2_LIN_MAT = {
2.85847e+0, -1.62879e+0, -2.48910e-2,
-2.10182e-1, 1.15820e+0, 3.24281e-4,
-4.18120e-2, -1.18169e-1, 1.06867e+0
};
float3 lms = mul(LIN_2_LMS_MAT, In);
lms *= balance;
return mul(LMS_2_LIN_MAT, lms);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment