#version 450 // White Point Mapping // ported by Dogway // // From the first comment post (sRGB primaries and linear light compensated) // http://www.zombieprototypes.com/?p=210#comment-4695029660 // Based on the Neil Bartlett's blog update // http://www.zombieprototypes.com/?p=210 // Inspired itself by Tanner Helland's work // 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" 9311.0 1031.0 12047.0 72.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; vec3 wp_adjust(vec3 color){ float temp = params.temperature / 100.; float k = params.temperature / 10000.; float lk = log(k); vec3 wp = vec3(1.); // calculate RED wp.r = (temp <= 65.) ? 1. : 0.32068362618584273 + (0.19668730877673762 * pow(k - 0.21298613432655075, - 1.5139012907556737)) + (- 0.013883432789258415 * lk); // calculate GREEN float mg = 1.226916242502167 + (- 1.3109482654223614 * pow(k - 0.44267061967913873, 3.) * exp(- 5.089297600846147 * (k - 0.44267061967913873))) + (0.6453936305542096 * lk); float pg = 0.4860175851734596 + (0.1802139719519286 * pow(k - 0.14573069517701578, - 1.397716496795082)) + (- 0.00803698899233844 * lk); wp.g = (temp <= 65.5) ? ((temp <= 8.) ? 0. : mg) : pg; // calculate BLUE wp.b = (temp <= 19.) ? 0. : (temp >= 66.) ? 1. : 1.677499032830161 + (- 0.02313594016938082 * pow(k - 1.1367244820333684, 3.) * exp(- 4.221279555918655 * (k - 1.1367244820333684))) + (1.6550275798913296 * lk); // clamp wp.rgb = clamp(wp.rgb, vec3(0.), vec3(1.)); // R/G/B independent manual White Point adjustment wp.rgb += vec3(params.wp_red, params.wp_green, params.wp_blue); // Linear color input return color * wp; } vec3 sRGB_to_XYZ(vec3 RGB){ const mat3x3 m = mat3x3( 0.4124564, 0.3575761, 0.1804375, 0.2126729, 0.7151522, 0.0721750, 0.0193339, 0.1191920, 0.9503041); return RGB * m; } vec3 XYZtoYxy(vec3 XYZ){ float XYZrgb = XYZ.r+XYZ.g+XYZ.b; float Yxyr = XYZ.g; float Yxyg = (XYZrgb <= 0.0) ? 0.3805 : XYZ.r / XYZrgb; float Yxyb = (XYZrgb <= 0.0) ? 0.3769 : XYZ.g / XYZrgb; return vec3(Yxyr,Yxyg,Yxyb); } vec3 XYZ_to_sRGB(vec3 XYZ){ const mat3x3 m = mat3x3( 3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252); return XYZ * m; } vec3 YxytoXYZ(vec3 Yxy){ float Xs = Yxy.r * (Yxy.g/Yxy.b); float Xsz = (Yxy.r <= 0.0) ? 0 : 1; vec3 XYZ = vec3(Xsz,Xsz,Xsz) * vec3(Xs, Yxy.r, (Xs/Yxy.g)-Xs-Yxy.r); return XYZ; } vec3 linear_to_sRGB(vec3 color, float gamma){ color = clamp(color, 0.0, 1.0); color.r = (color.r <= 0.00313066844250063) ? color.r * 12.92 : 1.055 * pow(color.r, 1.0 / gamma) - 0.055; color.g = (color.g <= 0.00313066844250063) ? color.g * 12.92 : 1.055 * pow(color.g, 1.0 / gamma) - 0.055; color.b = (color.b <= 0.00313066844250063) ? color.b * 12.92 : 1.055 * pow(color.b, 1.0 / gamma) - 0.055; return color.rgb; } vec3 sRGB_to_linear(vec3 color, float gamma){ color = clamp(color, 0.0, 1.0); color.r = (color.r <= 0.04045) ? color.r / 12.92 : pow((color.r + 0.055) / (1.055), gamma); color.g = (color.g <= 0.04045) ? color.g / 12.92 : pow((color.g + 0.055) / (1.055), gamma); color.b = (color.b <= 0.04045) ? color.b / 12.92 : pow((color.b + 0.055) / (1.055), gamma); return color.rgb; } void main() { vec3 original = sRGB_to_linear(texture(Source, vTexCoord).rgb, 2.40); vec3 adjusted = wp_adjust(original); vec3 base_luma = XYZtoYxy(sRGB_to_XYZ(original)); vec3 adjusted_luma = XYZtoYxy(sRGB_to_XYZ(adjusted)); adjusted = (params.luma_preserve == 1.0) ? adjusted_luma + (vec3(base_luma.r,0.,0.) - vec3(adjusted_luma.r,0.,0.)) : adjusted_luma; FragColor = vec4(linear_to_sRGB(XYZ_to_sRGB(YxytoXYZ(adjusted)), 2.40), 1.0); }