Created
June 1, 2023 08:17
-
-
Save Quackdoc/cc37d015a4343c5caec26f459d9f2334 to your computer and use it in GitHub Desktop.
olive tonemap ported from hdr-toys
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0"?> | |
<olive version="230220"> | |
<nodes version="1"> | |
<node version="1" id="org.olivevideoeditor.Olive.displaytransform" ptr="1991839047088"> | |
<input id="enabled_in"> | |
<primary> | |
<keyframing>0</keyframing> | |
<standard> | |
<track>true</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="tex_in"> | |
<primary> | |
<standard> | |
<track></track> | |
</standard> | |
</primary> | |
</input> | |
<input id="display_in"> | |
<primary> | |
<standard> | |
<track>0</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="view_in"> | |
<primary> | |
<standard> | |
<track>0</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="dir_in"> | |
<primary> | |
<standard> | |
<track>0</track> | |
</standard> | |
</primary> | |
</input> | |
<connections> | |
<connection input="tex_in" element="-1"> | |
<output>1991285140944</output> | |
</connection> | |
</connections> | |
<caches> | |
<audio>{ba1879fc-773e-4cd0-9ed4-cb7715ffa1ca}</audio> | |
<video>{b7aac616-432b-4ae7-b31d-be625f65cec0}</video> | |
<thumb>{c42a5196-a70e-4ea7-8013-d1bdf3ded39e}</thumb> | |
<waveform>{5d6ac312-66ac-4db6-8a9e-09146de35401}</waveform> | |
</caches> | |
<custom/> | |
</node> | |
<node version="1" id="org.olivevideoeditor.Olive.shader" ptr="1991285140944"> | |
<label>Compress</label> | |
<input id="enabled_in"> | |
<primary> | |
<keyframing>0</keyframing> | |
<standard> | |
<track>true</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="source"> | |
<primary> | |
<standard> | |
<track>#version 150 | |
//OVE shader_name: Compress | |
//OVE shader_description: | |
//OVE main_input_name: Input | |
uniform sampler2D tex_in; | |
//OVE end | |
// pixel coordinates in range [0..1]x[0..1] | |
in vec2 ove_texcoord; | |
// output color | |
out vec4 frag_color; | |
const float cyan_limit = 1.6515689028157825; | |
const float magenta_limit = 1.7355376392652817; | |
const float yellow_limit = 1.671460554049985; | |
const float cyan_threshold = 0.4770771960073855; | |
const float magenta_threshold = 0.43305325213057494; | |
const float yellow_threshold = 0.8430686842640781; | |
const float select = 0.1; | |
mat3 M = mat3( | |
1.6605, -0.5876, -0.0728, | |
-0.1246, 1.1329, -0.0083, | |
-0.0182, -0.1006, 1.1187); | |
void main(void) { | |
vec4 color = texture(tex_in, ove_texcoord); | |
vec3 color_src = color.rgb; | |
vec3 color_src_cliped = clamp(color_src, 0.0, 1.0); | |
vec3 color_dst = color_src_cliped * M; | |
vec3 rgb = color_dst; | |
// Distance limit: How far beyond the gamut boundary to compress | |
vec3 dl = vec3(cyan_limit, magenta_limit, yellow_limit); | |
// Amount of outer gamut to affect | |
vec3 th = vec3(cyan_threshold, magenta_threshold, yellow_threshold); | |
// Achromatic axis | |
float ac = max(rgb.x, max(rgb.y, rgb.z)); | |
// Inverse RGB Ratios: distance from achromatic axis | |
vec3 d = ac == 0.0 ? vec3(0.0) : (ac - rgb) / abs(ac); | |
// Calculate scale so compression function passes through distance limit: (x=dl, y=1) | |
vec3 s; | |
s.x = (1.0 - th.x) / sqrt(dl.x - 1.0); | |
s.y = (1.0 - th.y) / sqrt(dl.y - 1.0); | |
s.z = (1.0 - th.z) / sqrt(dl.z - 1.0); | |
vec3 cd; // Compressed distance | |
// Parabolic compression function: https://www.desmos.com/calculator/nvhp63hmtj | |
cd.x = d.x < th.x ? d.x : s.x * sqrt(d.x - th.x + s.x * s.x / 4.0) - s.x * sqrt(s.x * s.x / 4.0) + th.x; | |
cd.y = d.y < th.y ? d.y : s.y * sqrt(d.y - th.y + s.y * s.y / 4.0) - s.y * sqrt(s.y * s.y / 4.0) + th.y; | |
cd.z = d.z < th.z ? d.z : s.z * sqrt(d.z - th.z + s.z * s.z / 4.0) - s.z * sqrt(s.z * s.z / 4.0) + th.z; | |
// Inverse RGB Ratios to RGB | |
vec3 crgb = ac - cd * abs(ac); | |
color.rgb = mix(rgb, crgb, select); | |
frag_color= color.rgba; | |
} | |
</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="issues"> | |
<primary> | |
<standard> | |
<track>None</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="tex_in"> | |
<primary> | |
<standard> | |
<track></track> | |
</standard> | |
</primary> | |
</input> | |
<connections> | |
<connection input="tex_in" element="-1"> | |
<output>1991285142096</output> | |
</connection> | |
</connections> | |
<hints> | |
<hint input="enabled_in" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
<hint input="issues" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
<hint input="source" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
<hint input="tex_in" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
</hints> | |
<caches> | |
<audio>{d0f2d853-dfc5-46f9-bce2-25c7f4a498dc}</audio> | |
<video>{a72a54d3-2d1e-4719-b9a5-d370f64a3751}</video> | |
<thumb>{affcfa21-94d6-43bf-85d4-993aada2a416}</thumb> | |
<waveform>{d266519a-e979-456f-9386-d463b97a28ac}</waveform> | |
</caches> | |
<custom/> | |
</node> | |
<node version="1" id="org.olivevideoeditor.Olive.shader" ptr="1991285142096"> | |
<label>bt.2446a</label> | |
<input id="enabled_in"> | |
<primary> | |
<keyframing>0</keyframing> | |
<standard> | |
<track>true</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="source"> | |
<primary> | |
<standard> | |
<track>#version 150 | |
//OVE shader_name: bt.2446a | |
//OVE shader_description: Tonemap linear to bt.2446a | |
//OVE main_input_name: Input | |
uniform sampler2D tex_in; | |
//OVE end | |
// pixel coordinates in range [0..1]x[0..1] | |
in vec2 ove_texcoord; | |
// output color | |
out vec4 frag_color; | |
const float L_hdr = 2500.0; | |
const float L_sdr = 203.0; | |
const float a = 0.2627; | |
const float b = 0.6780; | |
const float c = 0.0593; // a + b + c = 1 | |
const float d = 1.8814; // 2 * (a + b) | |
const float e = 1.4747; // 2 * (1 - a) | |
vec3 RGB_to_YCbCr(float R, float G, float B) { | |
const float Y = a * R + b * G + c * B; | |
const float Cb = (B - Y) / d; | |
const float Cr = (R - Y) / e; | |
return vec3(Y, Cb, Cr); | |
} | |
vec3 YCbCr_to_RGB(float Y, float Cb, float Cr) { | |
const float R = Y + e * Cr; | |
const float G = Y - (a * e / b) * Cr - (c * d / b) * Cb; | |
const float B = Y + d * Cb; | |
return vec3(R, G, B); | |
} | |
float f(float Y) { | |
Y = pow(Y, 1.0 / 2.4); | |
const float pHDR = 1.0 + 32.0 * pow(L_hdr / 10000.0, 1.0 / 2.4); | |
const float pSDR = 1.0 + 32.0 * pow(L_sdr / 10000.0, 1.0 / 2.4); | |
const float Yp = log(1.0 + (pHDR - 1.0) * Y) / log(pHDR); | |
float Yc; | |
if (Yp <= 0.7399) Yc = Yp * 1.0770; | |
else if (Yp < 0.9909) Yc = Yp * (-1.1510 * Yp + 2.7811) - 0.6302; | |
else Yc = Yp * 0.5000 + 0.5000; | |
const float Ysdr = (pow(pSDR, Yc) - 1.0) / (pSDR - 1.0); | |
Y = pow(Ysdr, 2.4); | |
return Y; | |
} | |
vec3 tone_mapping(vec3 YCbCr) { | |
const float W = L_hdr / L_sdr; | |
YCbCr /= W; | |
float Y = YCbCr.r; | |
float Cb = YCbCr.g; | |
float Cr = YCbCr.b; | |
const float Ysdr = f(Y); | |
const float Yr = Ysdr / (1.1 * Y); | |
Cb *= Yr; | |
Cr *= Yr; | |
Y = Ysdr - max(0.1 * Cr, 0.0); | |
return vec3(Y, Cb, Cr); | |
} | |
void main(void) { | |
//vec4 textureColor = texture(tex_in, ove_texcoord); | |
//frag_color= textureColor.brga; | |
vec4 color = texture(tex_in, ove_texcoord); | |
color.rgb = RGB_to_YCbCr(color.r, color.g, color.b); | |
color.rgb = tone_mapping(color.rgb); | |
color.rgb = YCbCr_to_RGB(color.r, color.g, color.b); | |
frag_color= color.rgba; | |
}</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="issues"> | |
<primary> | |
<standard> | |
<track>None</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="tex_in"> | |
<primary> | |
<standard> | |
<track></track> | |
</standard> | |
</primary> | |
</input> | |
<connections> | |
<connection input="tex_in" element="-1"> | |
<output>1991486862384</output> | |
</connection> | |
</connections> | |
<hints> | |
<hint input="enabled_in" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
<hint input="issues" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
<hint input="source" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
<hint input="tex_in" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
</hints> | |
<caches> | |
<audio>{599174c3-e141-4e2a-be0d-6a7236d14eab}</audio> | |
<video>{7c2957b5-f0bb-47f4-a69e-316c42b1009a}</video> | |
<thumb>{e00b2c50-37ed-4d7c-af82-6a5292fa35fa}</thumb> | |
<waveform>{dd54e144-e707-4bfd-8e51-292f7d8ecfd5}</waveform> | |
</caches> | |
<custom/> | |
</node> | |
<node version="1" id="org.olivevideoeditor.Olive.shader" ptr="1991486862384"> | |
<label>HLG to linear</label> | |
<input id="enabled_in"> | |
<primary> | |
<keyframing>0</keyframing> | |
<standard> | |
<track>true</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="source"> | |
<primary> | |
<standard> | |
<track>#version 150 | |
//OVE shader_name: HLG to linear | |
//OVE shader_description: | |
//OVE main_input_name: Input | |
uniform sampler2D tex_in; | |
//OVE end | |
// pixel coordinates in range [0..1]x[0..1] | |
in vec2 ove_texcoord; | |
// output color | |
out vec4 frag_color; | |
const float L_sdr = 203.0; | |
const float Lb_sdr = 0; | |
const float L_w = 1000.0; | |
const float L_b = 0.0; | |
const float alpha = L_w - L_b; | |
const float beta = L_b; | |
const float gamma = 1.2 * pow(1.111, log2(L_w / 1000.0)); | |
const float a = 0.17883277; | |
const float b = 1.0 - 4.0 * a; | |
const float c = 0.5 - a * log(4.0 * a); | |
// HLG EOTF (i.e. HLG inverse OETF followed by the HLG OOTF) | |
vec3 HLG_to_Y(vec3 HLG) { | |
// HLG Inverse OETF scene-linear (non-linear signal value to scene linear) | |
const vec3 sceneLinear = vec3( | |
HLG.r >= 0.0 && HLG.r <= 0.5 ? pow(HLG.r, 2.0) / 3.0 : (exp((HLG.r - c) / a) + b) / 12.0, | |
HLG.g >= 0.0 && HLG.g <= 0.5 ? pow(HLG.g, 2.0) / 3.0 : (exp((HLG.g - c) / a) + b) / 12.0, | |
HLG.b >= 0.0 && HLG.b <= 0.5 ? pow(HLG.b, 2.0) / 3.0 : (exp((HLG.b - c) / a) + b) / 12.0 | |
); | |
// HLG OOTF (scene linear to display linear) | |
const float Y_s = dot(sceneLinear, vec3(0.2627, 0.6780, 0.0593)); | |
const vec3 displayLinear = alpha * pow(Y_s, gamma - 1) * sceneLinear + beta; | |
return displayLinear; | |
} | |
vec3 Y_to_linCV(vec3 Y, float Ymax, float Ymin) { | |
return (Y - Ymin) / (Ymax - Ymin); | |
} | |
void main(void) { | |
vec4 textureColor = texture(tex_in, ove_texcoord); | |
textureColor.rgb = clamp(textureColor.rgb, 0.0, 1.0); //clip | |
textureColor.rgb = HLG_to_Y(textureColor.rgb); | |
textureColor.rgb = Y_to_linCV(textureColor.rgb, L_sdr, Lb_sdr); | |
frag_color= textureColor.rgba; | |
} | |
</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="issues"> | |
<primary> | |
<standard> | |
<track>None</track> | |
</standard> | |
</primary> | |
</input> | |
<input id="tex_in"> | |
<primary> | |
<standard> | |
<track></track> | |
</standard> | |
</primary> | |
</input> | |
<connections> | |
<connection input="tex_in" element="-1"> | |
<output>1991422096304</output> | |
</connection> | |
</connections> | |
<hints> | |
<hint input="enabled_in" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
<hint input="issues" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
<hint input="source" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
<hint input="tex_in" element="-1" version="1"> | |
<types/> | |
<index>-1</index> | |
<tag></tag> | |
</hint> | |
</hints> | |
<caches> | |
<audio>{bae4ad56-b731-4e97-a858-f89938a47bc9}</audio> | |
<video>{1e0de5ab-8367-4d85-8c2a-776a4e5369c2}</video> | |
<thumb>{6695b66d-123a-4d74-997d-0dfcc8d6e38d}</thumb> | |
<waveform>{9d6ec18f-700d-4ab1-81fc-4c7d500c330c}</waveform> | |
</caches> | |
<custom/> | |
</node> | |
<properties> | |
<node ptr="1991839047088"> | |
<expanded>0</expanded> | |
<x>-0.833334</x> | |
<y>1.18519</y> | |
</node> | |
<node ptr="1991285142096"> | |
<expanded>0</expanded> | |
<x>-1.62878</x> | |
<y>1.23457</y> | |
</node> | |
<node ptr="1991285140944"> | |
<expanded>0</expanded> | |
<x>-1.20455</x> | |
<y>-0.0493827</y> | |
</node> | |
<node ptr="1991486862384"> | |
<expanded>0</expanded> | |
<x>-1.99621</x> | |
<y>-0.0493827</y> | |
</node> | |
</properties> | |
</nodes> | |
</olive> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment