/* Tonemap "Toe Last" by Jed Smith - v0.0.1 Desmos plot https://www.desmos.com/calculator/7qvuixbzht Presets ----------- SDR - Dark Surround Lp 100 Lw 100 Lg 11.5 c 1.4 ps 1 t0 0.01 SDR - Dim Surround Lp 100 Lw 100 Lg 11.5 c 1.4 ps .95 t0 0.01 SDR - Average Surround Lp 100 Lw 100 Lg 11.5 c 1.4 ps .9 t0 0.01 Rec.2100 PQ ST-2084 600 nit Lp 10000 Lw 600 Lg 14 c 1.2 ps 1 t0 0.002 Rec.2100 PQ ST-2084 1000 nit Lp 10000 Lw 1000 Lg 14 c 1.2 ps 1 t0 0.001 Rec.2100 PQ ST-2084 2000 nit Lp 10000 Lw 2000 Lg 14 c 1.2 ps 1 t0 0.0005 Rec.2100 PQ ST-2084 4000 nit Lp 10000 Lw 4000 Lg 14 c 1.2 ps 1 t0 0.00025 */ DEFINE_UI_PARAMS(preset, preset, DCTLUI_COMBO_BOX, 0, {A, B, C, D, E, F, G, H}, {Custom, SDR - Dark, SDR - Dim, SDR - Average, Rec.2100 PQ ST-2084 600 nit, Rec.2100 PQ ST-2084 1000 nit, Rec.2100 PQ ST-2084 2000 nit, Rec.2100 PQ ST-2084 4000 nit}); DEFINE_UI_PARAMS(_Lp, Lp, DCTLUI_SLIDER_FLOAT, 100.0, 100.0, 10000.0, 100.0); DEFINE_UI_PARAMS(_Lw, Lw, DCTLUI_SLIDER_FLOAT, 100.0, 100.0, 4000.0, 10.0); DEFINE_UI_PARAMS(_Lg, Lg, DCTLUI_SLIDER_FLOAT, 10.0, 1.0, 50.0, 1.0); DEFINE_UI_PARAMS(_c, contrast, DCTLUI_SLIDER_FLOAT, 1.4, 0.5, 2.0, 0.0); DEFINE_UI_PARAMS(_ps, surround, DCTLUI_SLIDER_FLOAT, 1.0, 0.8, 1.2, 0.0); DEFINE_UI_PARAMS(_t0, toe, DCTLUI_SLIDER_FLOAT, 0.004, 0.0, 0.01, 0.0); DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0); __DEVICE__ float3 powv(float3 a, float b) { return make_float3(_powf(a.x, b), _powf(a.y, b), _powf(a.z, b)); } __DEVICE__ float3 sqrtv(float3 a) { return make_float3(_sqrtf(a.x), _sqrtf(a.y), _sqrtf(a.z)); } __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) { float3 rgb = make_float3(p_R, p_G, p_B); float Lp, Lw, Lg, c, ps, t0; // setup presets if (preset == A) { // user-driven custom parameters Lp = _Lp; Lw = _Lw; Lg = _Lg; c = _c; ps = _ps; t0 = _t0; } else if (preset == B) { // SDR - Dark Surround Lp = 100.0f; Lw = 100.0f; Lg = 11.5f; c = 1.4f; ps = 1.0f; t0 = 0.01f; } else if (preset == C) { // SDR - Dim Surround Lp = 100.0f; Lw = 100.0f; Lg = 11.5f; c = 1.4f; ps = 0.95f; t0 = 0.01f; } else if (preset == D) { // SDR - Average Surround Lp = 100.0f; Lw = 100.0f; Lg = 11.5f; c = 1.4f; ps = 0.9f; t0 = 0.01f; } else if (preset == E) { // Rec.2100 PQ ST-2084 600 nit Lp = 10000.0f; Lw = 600.0f; Lg = 14.0f; c = 1.2f; ps = 1.0f; t0 = 0.002f; } else if (preset == F) { // Rec.2100 PQ ST-2084 1000 nit Lp = 10000.0f; Lw = 1000.0f; Lg = 14.0f; c = 1.2f; ps = 1.0f; t0 = 0.001f; } else if (preset == G) { // Rec.2100 PQ ST-2084 2000 nit Lp = 10000.0f; Lw = 2000.0f; Lg = 14.0f; c = 1.2f; ps = 1.0f; t0 = 0.0005f; } else if (preset == H) { // Rec.2100 PQ ST-2084 4000 nit Lp = 10000.0f; Lw = 4000.0f; Lg = 14.0f; c = 1.2f; ps = 1.0f; t0 = 0.00025f; } // set up constants const float th = Lg / Lw; const float p = c * ps; const float2 g = make_float2(0.18f, Lg / Lp); const float h = 0.048 * Lw / 1000 + 1.033; const float sy = Lw / Lp * h; const float gi = _powf(g.y / sy, 1.0f / c); const float w = th > gi ? gi / g.x : (2.0f * th * gi - gi - th * th) / (g.x * (gi - 1.0f)); const float sx = w * _fmaxf(1.0f, _powf(Lw / 1000.0f, 0.1f)); if (invert == 0) { // input scale -> shoulder -> contrast -> toe -> output scale rgb = rgb * sx; rgb = rgb / (rgb + 1.0f); rgb = powv(rgb, p); rgb = (rgb * rgb) / (rgb + t0); rgb = rgb * sy; } else { // inverse output scale -> inverse toe -> inverse contrast -> // inverse shoulder -> inverse input scale rgb = rgb / sy; rgb = (rgb + sqrtv(rgb * (4.0f * t0 + rgb)))/2.0f; rgb = powv(rgb, 1.0f / p); rgb = rgb / (1.0f - rgb); rgb = rgb / sx; } return rgb; }