diff --git a/misc/color-mangler.slang b/misc/color-mangler.slang index a0b7c8c..7fd294f 100644 --- a/misc/color-mangler.slang +++ b/misc/color-mangler.slang @@ -2,8 +2,9 @@ layout(push_constant) uniform Push { - float display_gamma; - float target_gamma; + float gamma_boost_r; + float gamma_boost_g; + float gamma_boost_b; float sat; float lum; float cntrst; @@ -34,8 +35,9 @@ layout(std140, set = 0, binding = 0) uniform UBO Author: hunterk License: Public domain */ -#pragma parameter display_gamma "Display Gamma" 2.2 0.0 10.0 0.1 -#pragma parameter target_gamma "Target Gamma" 2.2 0.0 10.0 0.1 +#pragma parameter gamma_boost_r "Gamma Mod Red Channel" 0.0 -5.0 5.0 0.1 +#pragma parameter gamma_boost_g "Gamma Mod Green Channel" 0.0 -5.0 5.0 0.1 +#pragma parameter gamma_boost_b "Gamma Mod Blue Channel" 0.0 -5.0 5.0 0.1 #pragma parameter sat "Saturation" 1.0 0.0 3.0 0.01 #pragma parameter lum "Luminance" 1.0 0.0 5.0 0.01 #pragma parameter cntrst "Contrast" 1.0 0.0 2.0 0.01 @@ -70,7 +72,7 @@ layout(set = 0, binding = 2) uniform sampler2D Source; void main() { - vec4 screen = pow(texture(Source, vTexCoord), vec4(params.target_gamma)).rgba; + vec4 screen = pow(texture(Source, vTexCoord), vec4(2.2)).rgba; vec4 avglum = vec4(0.5); screen = mix(screen, avglum, (1.0 - params.cntrst)); @@ -80,12 +82,13 @@ mat4 color = mat4(params.r, params.rg, params.rb, 0.0, //red channel params.br, params.bg, params.b, 0.0, //blue channel params.blr, params.blg, params.blb, 0.0); //alpha channel; these numbers do nothing for our purposes. -mat4 adjust = mat4((1.0 - params.sat) * 0.3086 + params.sat, (1.0 - params.sat) * 0.3086, (1.0 - params.sat) * 0.3086, 1.0, -(1.0 - params.sat) * 0.6094, (1.0 - params.sat) * 0.6094 + params.sat, (1.0 - params.sat) * 0.6094, 1.0, -(1.0 - params.sat) * 0.0820, (1.0 - params.sat) * 0.0820, (1.0 - params.sat) * 0.0820 + params.sat, 1.0, +mat4 adjust = mat4((1.0 - params.sat) * 0.2126 + params.sat, (1.0 - params.sat) * 0.2126, (1.0 - params.sat) * 0.2126, 1.0, +(1.0 - params.sat) * 0.7152, (1.0 - params.sat) * 0.7152 + params.sat, (1.0 - params.sat) * 0.7152, 1.0, +(1.0 - params.sat) * 0.0722, (1.0 - params.sat) * 0.0722, (1.0 - params.sat) * 0.0722 + params.sat, 1.0, 0.0, 0.0, 0.0, 1.0); color *= adjust; screen = clamp(screen * params.lum, 0.0, 1.0); screen = color * screen; - FragColor = pow(screen, vec4(1.0 / params.display_gamma)); + vec3 out_gamma = vec3(1.) / (vec3(2.2) - vec3(params.gamma_boost_r, params.gamma_boost_g, params.gamma_boost_b)); + FragColor = pow(screen, vec4(out_gamma, 1.0)); } \ No newline at end of file diff --git a/misc/white_point.slang b/misc/white_point.slang new file mode 100644 index 0000000..c5e0ec1 --- /dev/null +++ b/misc/white_point.slang @@ -0,0 +1,95 @@ +#version 450 + +// white point adjustment +// by hunterk +// based on blog post by Tanner Helland +// http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float temperature; + float luma_preserve; + float wp_red; + float wp_green; + float wp_blue; +} params; + +#pragma parameter temperature "White Point" 6500.0 0.0 12000.0 100.0 +#pragma parameter luma_preserve "Preserve Luminance" 1.0 0.0 1.0 1.0 +#pragma parameter wp_red "Red Shift" 0.0 -1.0 1.0 0.01 +#pragma parameter wp_green "Green Shift" 0.0 -1.0 1.0 0.01 +#pragma parameter wp_blue "Blue Shift" 0.0 -1.0 1.0 0.01 + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +// white point adjustment +// based on blog post by Tanner Helland +// http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ +vec3 wp_adjust(vec3 color){ + const float target_white_point = 9300.0; + const mat3 RGBtoYIQ = mat3( + 0.2989, 0.5870, 0.1140, + 0.5959, -0.2744, -0.3216, + 0.2115, -0.5229, 0.3114); + + const mat3 YIQtoRGB = mat3( + 1.0, 0.956, 0.6210, + 1.0, -0.2720, -0.6474, + 1.0, -1.1060, 1.7046); + + float temp = params.temperature / 100.0; + + // all calculations assume a scale of 255. We'll normalize this at the end + vec3 wp = vec3(255.); + + // calculate RED + wp.r = (temp <= 66.) ? 255. : 329.698727446 * pow((temp - 60.), -0.1332047592); + + // calculate GREEN + wp.g = (temp <= 66.) ? 99.4708025861 * log(temp) - 161.1195681661 : 288.1221695283 * pow((temp - 60.), -0.0755148492); + + // calculate BLUE + wp.b = (temp >= 66.) ? 255. : (temp <= 19.) ? 0. : 138.5177312231 * log(temp - 10.) - 305.0447927307; + + // clamp and normalize + wp.rgb = clamp(wp.rgb, vec3(0.), vec3(255.)) / vec3(255.); + + // this is dumb, but various cores don't always show white as white. Use this to make white white... + wp.rgb += vec3(params.wp_red, params.wp_green, params.wp_blue); + + // apply transformation + vec3 adjusted = (color * wp); + vec3 base_luma = color * RGBtoYIQ; + vec3 adjusted_luma = adjusted * RGBtoYIQ; + adjusted = (params.luma_preserve > 0.5) ? adjusted_luma + (vec3(base_luma.r,0.,0.) - vec3(adjusted_luma.r,0.,0.)) : adjusted_luma; + + return adjusted * YIQtoRGB; +} + +void main() +{ + FragColor = vec4(wp_adjust(texture(Source, vTexCoord).rgb), 1.0); +} \ No newline at end of file