// Color Correction
// ColorCorrect.osl, by Zap Andersson
// Modified: 2021-12-20 by Saul Espinosa for Redshift 3D
// Removed Max UI specific options and added Page grouping Metadata
// Copyright 2020 Autodesk Inc, All rights reserved. This file is licensed under Apache 2.0 license
// https://github.com/ADN-DevTech/3dsMax-OSL-Shaders/blob/master/LICENSE.txt
float remap(color In, int mapping)
{
if (mapping < 3)
return In[mapping];
if (mapping < 6)
return 1.0 - In[mapping-3];
if (mapping == 6) return luminance(In);
if (mapping == 7) return 1.0 - luminance(In);
if (mapping == 8) return 0.0;
return 1.0;
}
shader UberColorCorrect
[[ string label = "Color Correction",
// string category = "Color Correction",
string version = "1.5" ]]
(
color Input = 0.18 [[string page = "Input"]],
int Bypass = 0 [[ string widget = "checkBox", string page = "Input" ]],
float Overall = 1.0 [[ float min = 0.0, float max = 1.0, string page = "Input" ]],
int HueRange = 0 [[ string widget = "checkBox", string page = "Hue Ranges" ]],
color AffectHue = color(1.0, 0.4, 0.3) [[string page = "Hue Ranges"]],
float HueRangeWidth = 10 [[ float min = 0.0, float max = 360, float step = 1.0, string page = "Hue Ranges" ]],
float HueRangeSoftness = 10 [[ float min = 0.0, float max = 360, float step = 1.0, string page = "Hue Ranges" ]],
int ChannelMapping = 0 [[ string widget = "checkBox", string page = "Channels" ]],
int RedMapping = 0
[[
int connectable = 0,
string page = "Channels",
string widget = "mapper",
string options =
"Red:0|Green:1|Blue:2|"
"Red (Inverse):3|Green (Inverse):4|Blue (Inverse):5|"
"Luminance:6|Luminance (Inverse):7|Zero:8|One:9" ]],
int GreenMapping = 1
[[ int connectable = 0,
string page = "Channels",
string widget = "mapper",
string options =
"Red:0|Green:1|Blue:2|"
"Red (Inverse):3|Green (Inverse):4|Blue (Inverse):5|"
"Luminance:6|Luminance (Inverse):7|Zero:8|One:9" ]],
int BlueMapping = 2
[[ int connectable = 0,
string page = "Channels",
string widget = "mapper",
string options =
"Red:0|Green:1|Blue:2|"
"Red (Inverse):3|Green (Inverse):4|Blue (Inverse):5|"
"Luminance:6|Luminance (Inverse):7|Zero:8|One:9" ]],
int BrightnessAdjustment = 1 [[ string widget = "checkBox", string page = "Value Adjustments" ]],
int Invert = 0 [[ string widget = "checkBox", int connectable=0, string page = "Value Adjustments" ]],
float Brightness = 1.0 [[string page = "Value Adjustments"]],
float Contrast = 1.0 [[string page = "Value Adjustments"]],
float Lift = 0.0 [[string page = "Value Adjustments"]],
float Pivot = 0.5 [[string page = "Value Adjustments"]],
int InverseGamma = 0 [[ string widget = "checkBox", int connectable=0, string page = "Value Adjustments" ]],
float Gamma = 1.0 [[string page = "Value Adjustments"]],
int ColorAdjustment = 0 [[ string widget = "checkBox", int connectable=0, string page = "Color Adjustments" ]],
float HueShift = 0.0 [[ float min = -1.0, float max = 1.0, string page = "Color Adjustments" ]],
float Saturation = 1.0 [[ float min = 0.0, float max = 10.0, string page = "Color Adjustments" ]],
color TintColor = 1.0 [[ string page = "Color Adjustments"]],
float TintStrength = 0.0 [[ float min = 0.0, float max = 1.0, string page = "Color Adjustments" ]],
int OutputTint = 0 [[ string widget = "checkBox", int connectable=0, string page = "Output Adjustments" ]],
color Shadows = 0.0 [[ string page = "Output Adjustments"]],
color Midtones = 0.2 [[ string page = "Output Adjustments"]],
color Highlights = 1.0 [[ string page = "Output Adjustments"]],
float MidtoneLum = 0.2 [[ float min = 0.0, float max = 1.0, string page = "Output Adjustments" ]],
int Clamp = 1 [[ string widget = "checkBox", int connectable=0, string page = "Output Clamp" ]],
float ClampLow = 0.0 [[string page = "Output Clamp"]],
float ClampHi = 1.0 [[string page = "Output Clamp"]],
// Outputs
output color Out = 0.0,
output float R = 0.0,
output float G = 0.0,
output float B = 0.0
)
{
float effect = Overall;
Out = Input;
if (!Bypass)
{
// Apply only to hue range
if (HueRange)
{
// Tramsform to HSV space
color hsv = transformc("rgb", "hsv", Input);
// Tramsform to HSV space
color hsv2 = transformc("rgb", "hsv", AffectHue);
float huedifference = fabs(hsv[0] - hsv2[0]);
// If distance in hue is larger than half
// the color wheel, measure the other way around
if (huedifference > 0.5)
huedifference = 1.0 - huedifference;
float HRW = HueRangeWidth / 360.0 / 2.0;
float HRS = HueRangeSoftness / 360.0;
// Are we outside the hue range? Then we need to modulate
// the effect value to apply the effect less (or not at all)
if (huedifference > HRW)
{
// Outside range - apply softness (if any)
if (HRS > 0.0)
effect *= smoothstep(0.0, 1.0, 1.0 - (huedifference - HRW) / HRS);
else
effect = 0.0; // No softness - just hard cut effect to zero
}
}
// Apply the channel mapping
if (ChannelMapping)
{
Out[0] = remap(Input, RedMapping);
Out[1] = remap(Input, GreenMapping);
Out[2] = remap(Input, BlueMapping);
}
// Brightness adjustment section
if (BrightnessAdjustment)
{
// Invert, if requested
if (Invert) Out = 1.0 - Out;
// Multiply by Brightness
Out = Out * Brightness;
// Scale around Pivot by Contrast
Out = ((Out - Pivot) * Contrast) + Pivot;
// Add Lift
Out = Out + Lift;
// Apply Gamma
if (Gamma != 1.0)
Out = pow(max(0.0, Out), InverseGamma?1.0/Gamma:Gamma);
}
// Color adjustment section
if (ColorAdjustment)
{
// Tramsform to HSV space
color hsv = transformc("rgb", "hsv", Out);
hsv[0] += HueShift;
hsv[1] *= Saturation;
// Convert back to RGB
Out = transformc("hsv", "rgb", hsv);
// Mix with tint color scaled by value
Out = mix(Out, TintColor * hsv[2], TintStrength);
}
// Output Tint Section
if (OutputTint)
{
color below = clamp((Out / MidtoneLum), 0.0, 1.0);
color above = clamp((Out - MidtoneLum) / (1.0 - MidtoneLum), 0.0, 1.0);
Out = mix(Shadows, mix(Midtones, Highlights, above), below);
}
if (Clamp)
Out = clamp(Out, ClampLow, ClampHi);
// Do the overall mix in of the effect
Out = mix(Input, Out, effect);
}
// Output individual channels for convenience
R = Out[0];
G = Out[1];
B = Out[2];
}