diff --git a/src/games/avatarfop-swoutlaws/addon.cpp b/src/games/avatarfop-swoutlaws/addon.cpp index 8458e45fa..cea227c32 100644 --- a/src/games/avatarfop-swoutlaws/addon.cpp +++ b/src/games/avatarfop-swoutlaws/addon.cpp @@ -38,7 +38,7 @@ renodx::utils::settings::Settings settings = { .label = "Tone Mapper", .section = "Tone Mapping & Color Grading", .tooltip = "Sets the tone mapper type", - .labels = {"Vanilla", "None", "Neutwo"}, + .labels = {"Vanilla", "None", "RenoDX"}, }, new renodx::utils::settings::Setting{ .key = "ToneMapPeakNits", @@ -61,7 +61,7 @@ renodx::utils::settings::Settings settings = { .tooltip = "Sets the value of 100% white in nits", .min = 48.f, .max = 500.f, - .is_enabled = []() { return shader_injection.tone_map_type != 0; }, + .is_enabled = []() { return shader_injection.tone_map_type != 0.f; }, }, new renodx::utils::settings::Setting{ .key = "SDREOTFEmulation", @@ -71,8 +71,19 @@ renodx::utils::settings::Settings settings = { .label = "SDR EOTF Emulation", .section = "Tone Mapping & Color Grading", .tooltip = "Emulates a 2.2 EOTF", - .labels = {"Off", "2.2 (Per Channel)", "2.2 (By Luminosity)"}, - .is_enabled = []() { return shader_injection.tone_map_type != 0; }, + .labels = {"Off", "2.2 (Per Channel)", "2.2 (By Luminance)"}, + .is_enabled = []() { return shader_injection.tone_map_type != 0.f; }, + }, + new renodx::utils::settings::Setting{ + .key = "ToneMapHueEmulation", + .binding = &shader_injection.tone_map_hue_emulation, + .default_value = 0.f, + .label = "BT.2020 Hue Emulation", + .section = "Tone Mapping & Color Grading", + .tooltip = "Emulates hue shifts from BT.2020 per-channel tonemapping.", + .max = 100.f, + .is_enabled = []() { return shader_injection.tone_map_type != 0.f; }, + .parse = [](float value) { return value * 0.01f; }, }, new renodx::utils::settings::Setting{ .key = "ToneMapWhiteClip", @@ -94,6 +105,17 @@ renodx::utils::settings::Settings settings = { .format = "%.2f", .is_enabled = []() { return shader_injection.tone_map_type != 0 && shader_injection.tone_map_type != 3; }, }, + new renodx::utils::settings::Setting{ + .key = "ColorGradeGamma", + .binding = &shader_injection.tone_map_gamma, + .default_value = 1.f, + .label = "Gamma", + .section = "Tone Mapping & Color Grading", + .min = 0.75f, + .max = 1.25f, + .format = "%.2f", + .is_enabled = []() { return shader_injection.tone_map_type != 0 && shader_injection.tone_map_type != 3; }, + }, new renodx::utils::settings::Setting{ .key = "ColorGradeHighlights", .binding = &shader_injection.tone_map_highlights, @@ -104,6 +126,16 @@ renodx::utils::settings::Settings settings = { .is_enabled = []() { return shader_injection.tone_map_type != 0 && shader_injection.tone_map_type != 3; }, .parse = [](float value) { return value * 0.02f; }, }, + new renodx::utils::settings::Setting{ + .key = "ColorGradeHighlightContrast", + .binding = &shader_injection.tone_map_contrast_highlights, + .default_value = 45.f, + .label = "Highlight Contrast", + .section = "Tone Mapping & Color Grading", + .max = 100.f, + .is_enabled = []() { return shader_injection.tone_map_type != 0 && shader_injection.tone_map_type != 3; }, + .parse = [](float value) { return value * 0.02f; }, + }, new renodx::utils::settings::Setting{ .key = "ColorGradeShadows", .binding = &shader_injection.tone_map_shadows, @@ -114,6 +146,16 @@ renodx::utils::settings::Settings settings = { .is_enabled = []() { return shader_injection.tone_map_type != 0 && shader_injection.tone_map_type != 3; }, .parse = [](float value) { return value * 0.02f; }, }, + new renodx::utils::settings::Setting{ + .key = "ColorGradeShadowContrast", + .binding = &shader_injection.tone_map_contrast_shadows, + .default_value = 50.f, + .label = "Shadow Contrast", + .section = "Tone Mapping & Color Grading", + .max = 100.f, + .is_enabled = []() { return shader_injection.tone_map_type != 0 && shader_injection.tone_map_type != 3; }, + .parse = [](float value) { return value * 0.02f; }, + }, new renodx::utils::settings::Setting{ .key = "ColorGradeContrast", .binding = &shader_injection.tone_map_contrast, @@ -124,6 +166,16 @@ renodx::utils::settings::Settings settings = { .is_enabled = []() { return shader_injection.tone_map_type != 0 && shader_injection.tone_map_type != 3; }, .parse = [](float value) { return value * 0.02f; }, }, + new renodx::utils::settings::Setting{ + .key = "ColorGradeAdaptationContrast", + .binding = &shader_injection.tone_map_adaptation_contrast, + .default_value = 50.f, + .label = "Adaptation Contrast", + .section = "Tone Mapping & Color Grading", + .max = 100.f, + .is_enabled = []() { return shader_injection.tone_map_type != 0 && shader_injection.tone_map_type != 3; }, + .parse = [](float value) { return value * 0.02f; }, + }, new renodx::utils::settings::Setting{ .key = "ColorGradeSaturation", .binding = &shader_injection.tone_map_saturation, @@ -165,7 +217,7 @@ renodx::utils::settings::Settings settings = { .tooltip = "Flare/Glare Compensation", .max = 100.f, .is_enabled = []() { return shader_injection.tone_map_type != 0 && shader_injection.tone_map_type != 3; }, - .parse = [](float value) { return value * 0.02f; }, + .parse = [](float value) { return value * 0.01f; }, }, // new renodx::utils::settings::Setting{ // .key = "ColorGradeLUTStrength", @@ -231,12 +283,9 @@ renodx::utils::settings::Settings settings = { .on_change = []() { renodx::utils::settings::ResetSettings(); renodx::utils::settings::UpdateSettings({ - {"SDREOTFEmulation", 0.f}, - {"ToneMapWhiteClip", 41.f}, - {"ColorGradeHighlights", 42.f}, - {"ColorGradeShadows", 80.f}, - {"ColorGradeSaturation", 52.f}, - {"ColorGradeFlare", 36.f}, + {"ColorGradeHighlightContrast", 50.f}, + {"ColorGradeContrast", 42.f}, + {"ColorGradeSaturation", 48.f}, }); }, }, @@ -317,10 +366,16 @@ void OnPresetOff() { {"ToneMapUINits", 203.f}, {"SDREOTFEmulation", 0.f}, {"UISDREOTFEmulation", 0.f}, + {"ToneMapHueEmulation", 0.f}, + {"ToneMapWhiteClip", 100.f}, {"ColorGradeExposure", 1.f}, + {"ColorGradeGamma", 1.f}, {"ColorGradeHighlights", 50.f}, + {"ColorGradeHighlightContrast", 50.f}, {"ColorGradeShadows", 50.f}, + {"ColorGradeShadowContrast", 50.f}, {"ColorGradeContrast", 50.f}, + {"ColorGradeAdaptationContrast", 50.f}, {"ColorGradeSaturation", 50.f}, {"ColorGradeHighlightSaturation", 50.f}, {"ColorGradeDechroma", 0.f}, @@ -374,4 +429,4 @@ BOOL APIENTRY DllMain(HMODULE h_module, DWORD fdw_reason, LPVOID lpv_reserved) { renodx::mods::shader::Use(fdw_reason, custom_shaders, &shader_injection); return TRUE; -} \ No newline at end of file +} diff --git a/src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_0x9642EE3A.cs_6_0.hlsl b/src/games/avatarfop-swoutlaws/avatarfop/deprecated/old_lutbuilder_hdr_0x9642EE3A.cs_6_0.hlsl similarity index 99% rename from src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_0x9642EE3A.cs_6_0.hlsl rename to src/games/avatarfop-swoutlaws/avatarfop/deprecated/old_lutbuilder_hdr_0x9642EE3A.cs_6_0.hlsl index 1d764d85d..e2e8ba591 100644 --- a/src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_0x9642EE3A.cs_6_0.hlsl +++ b/src/games/avatarfop-swoutlaws/avatarfop/deprecated/old_lutbuilder_hdr_0x9642EE3A.cs_6_0.hlsl @@ -1,4 +1,4 @@ -#include "..\lutbuilder.hlsli" +#include "..\..\lutbuilder.hlsli" cbuffer CB0_buf : register(b2200, space0) { float3 CB0_m0 : packoffset(c0); diff --git a/src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_no_gamma_correction_0xB59B69BC.cs_6_0.hlsl b/src/games/avatarfop-swoutlaws/avatarfop/deprecated/old_lutbuilder_hdr_no_gamma_correction_0xB59B69BC.cs_6_0.hlsl similarity index 99% rename from src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_no_gamma_correction_0xB59B69BC.cs_6_0.hlsl rename to src/games/avatarfop-swoutlaws/avatarfop/deprecated/old_lutbuilder_hdr_no_gamma_correction_0xB59B69BC.cs_6_0.hlsl index eb4cdbc67..9d78fd616 100644 --- a/src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_no_gamma_correction_0xB59B69BC.cs_6_0.hlsl +++ b/src/games/avatarfop-swoutlaws/avatarfop/deprecated/old_lutbuilder_hdr_no_gamma_correction_0xB59B69BC.cs_6_0.hlsl @@ -1,4 +1,4 @@ -#include "..\lutbuilder.hlsli" +#include "..\..\lutbuilder.hlsli" cbuffer CB0_buf : register(b2200, space0) { float3 CB0_m0 : packoffset(c0); diff --git a/src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_0xCD4504F9.cs_6_0.hlsl b/src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_0xCD4504F9.cs_6_0.hlsl new file mode 100644 index 000000000..6725ce305 --- /dev/null +++ b/src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_0xCD4504F9.cs_6_0.hlsl @@ -0,0 +1,397 @@ +#include "..\lutbuilder.hlsli" + +cbuffer CB0_buf : register(b2200, space0) { + float3 CB0_m0 : packoffset(c0); + uint CB0_m1 : packoffset(c0.w); +}; + +cbuffer CB1_buf : register(b2201, space0) { + uint4 CB1_m[4096] : packoffset(c0); +}; + +cbuffer CB2_buf : register(b0, space2) { + uint4 CB2_m0 : packoffset(c0); + uint4 CB2_m1 : packoffset(c1); + uint4 CB2_m2 : packoffset(c2); + uint4 CB2_m3 : packoffset(c3); + uint4 CB2_m4 : packoffset(c4); + uint4 CB2_m5 : packoffset(c5); + uint4 CB2_m6 : packoffset(c6); + uint4 CB2_m7 : packoffset(c7); + uint4 CB2_m8 : packoffset(c8); + uint4 CB2_m9 : packoffset(c9); + uint4 CB2_m10 : packoffset(c10); + uint4 CB2_m11 : packoffset(c11); +}; + +RWTexture3D U0[] : register(u0, space2820); + +static uint3 gl_GlobalInvocationID; +struct SPIRV_Cross_Input { + uint3 gl_GlobalInvocationID : SV_DispatchThreadID; +}; + +float dp3_f32(float3 a, float3 b) { + precise float _261 = a.x * b.x; + return mad(a.z, b.z, mad(a.y, b.y, _261)); +} + +float dp2_f32(float2 a, float2 b) { + precise float _249 = a.x * b.x; + return mad(a.y, b.y, _249); +} + +void comp_main() { + float _278 = float(gl_GlobalInvocationID.x); + float _279 = float(gl_GlobalInvocationID.y); + float _280 = float(gl_GlobalInvocationID.z); + float _288 = _278 * CB0_m0.x; + float _289 = _279 * CB0_m0.y; + float _290 = _280 * CB0_m0.z; + float _1368; + float _1369; + float _1370; + if (CB1_m[0u].x != 0u) { + float _961; + float _962; + float _963; + if (CB1_m[0u].y != 0u) { + bool _304 = _290 < _289; + float _305 = _304 ? _289 : _290; + float _306 = _304 ? _290 : _289; + bool _309 = _288 > _305; + float _310 = _309 ? _288 : _305; + float _312 = _309 ? _305 : _288; + float _314 = _310 - min(_306, _312); + float _318 = ((_312 - _306) / mad(_314, 6.0f, 1.0000000133514319600180897396058e-10f)) + (_309 ? (_304 ? 0.0f : (-1.0f)) : (_304 ? (-0.3333333432674407958984375f) : 0.666666686534881591796875f)); + float _320 = _314 / (_310 + 1.0000000133514319600180897396058e-10f); + uint _426; + uint _427; + uint _428; + uint _429; + if (!((asfloat(CB1_m[20u].y) == 0.0f) && ((asfloat(CB1_m[20u].x) == 0.0f) && (asfloat(CB1_m[20u].z) == 0.0f)))) { + float _339 = abs(_318); + float _341 = abs(_339 - 1.0f); + float _359 = min(clamp((asfloat(CB1_m[8u].y) - min(_341, 1.0f - _341)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_320 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _360 = _359 != 0.0f; + float _364 = _339 + asfloat(CB1_m[20u].x); + float _369 = clamp(_320 + asfloat(CB1_m[20u].y), 0.0f, 1.0f); + float _396 = asfloat(CB1_m[20u].z); + _426 = _360 ? asuint(_359) : 0u; + _427 = _360 ? asuint(_359 * (_290 + (_359 * mad(-_280, CB0_m0.z, clamp(mad(mad(_369, clamp(abs(mad(frac(_364 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _396), 0.0f, 1.0f))))) : 0u; + _428 = _360 ? asuint(_359 * (_289 + (_359 * mad(-_279, CB0_m0.y, clamp(mad(mad(_369, clamp(abs(mad(frac(_364 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _396), 0.0f, 1.0f))))) : 0u; + _429 = _360 ? asuint(_359 * (_288 + (_359 * mad(-_278, CB0_m0.x, clamp(mad(mad(_369, clamp(abs(mad(frac(_364 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _396), 0.0f, 1.0f))))) : 0u; + } else { + _426 = 0u; + _427 = 0u; + _428 = 0u; + _429 = 0u; + } + float _430 = asfloat(_429); + float _431 = asfloat(_428); + float _432 = asfloat(_427); + float _433 = asfloat(_426); + float _534; + float _535; + float _536; + float _537; + if (!(((asfloat(CB1_m[21u].x) == 0.0f) && (asfloat(CB1_m[21u].z) == 0.0f)) && (asfloat(CB1_m[21u].y) == 0.0f))) { + float _450 = abs(_318); + float _452 = abs(_450 - 0.3333333432674407958984375f); + float _470 = min(clamp((asfloat(CB1_m[8u].y) - min(_452, 1.0f - _452)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_320 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _471 = _470 != 0.0f; + float _475 = _450 + asfloat(CB1_m[21u].x); + float _480 = clamp(_320 + asfloat(CB1_m[21u].y), 0.0f, 1.0f); + float _507 = asfloat(CB1_m[21u].z); + _534 = _471 ? (_470 + _433) : _433; + _535 = _471 ? mad(_470, _290 + (_470 * mad(-_280, CB0_m0.z, clamp(mad(_310, mad(_480, clamp(abs(mad(frac(_475 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _507), 0.0f, 1.0f))), _432) : _432; + _536 = _471 ? mad(_470, _289 + (_470 * mad(-_279, CB0_m0.y, clamp(mad(_310, mad(_480, clamp(abs(mad(frac(_475 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _507), 0.0f, 1.0f))), _431) : _431; + _537 = _471 ? mad(_470, _288 + (_470 * mad(-_278, CB0_m0.x, clamp(mad(mad(_480, clamp(abs(mad(frac(_475 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _507), 0.0f, 1.0f))), _430) : _430; + } else { + _534 = _433; + _535 = _432; + _536 = _431; + _537 = _430; + } + float _638; + float _639; + float _640; + float _641; + if (!((asfloat(CB1_m[22u].y) == 0.0f) && ((asfloat(CB1_m[22u].x) == 0.0f) && (asfloat(CB1_m[22u].z) == 0.0f)))) { + float _554 = abs(_318); + float _556 = abs(_554 - 0.666666686534881591796875f); + float _574 = min(clamp((asfloat(CB1_m[8u].y) - min(_556, 1.0f - _556)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_320 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _575 = _574 != 0.0f; + float _579 = _554 + asfloat(CB1_m[22u].x); + float _584 = clamp(_320 + asfloat(CB1_m[22u].y), 0.0f, 1.0f); + float _611 = asfloat(CB1_m[22u].z); + _638 = _575 ? (_574 + _534) : _534; + _639 = _575 ? mad(_574, _290 + (_574 * mad(-_280, CB0_m0.z, clamp(mad(_310, mad(_584, clamp(abs(mad(frac(_579 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _611), 0.0f, 1.0f))), _535) : _535; + _640 = _575 ? mad(_574, _289 + (_574 * mad(-_279, CB0_m0.y, clamp(mad(_310, mad(_584, clamp(abs(mad(frac(_579 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _611), 0.0f, 1.0f))), _536) : _536; + _641 = _575 ? mad(_574, _288 + (_574 * mad(-_278, CB0_m0.x, clamp(mad(mad(_584, clamp(abs(mad(frac(_579 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _611), 0.0f, 1.0f))), _537) : _537; + } else { + _638 = _534; + _639 = _535; + _640 = _536; + _641 = _537; + } + float _742; + float _743; + float _744; + float _745; + if (!((asfloat(CB1_m[23u].y) == 0.0f) && ((asfloat(CB1_m[23u].x) == 0.0f) && (asfloat(CB1_m[23u].z) == 0.0f)))) { + float _658 = abs(_318); + float _660 = abs(_658 - 0.5f); + float _678 = min(clamp((asfloat(CB1_m[8u].y) - min(_660, 1.0f - _660)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_320 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _679 = _678 != 0.0f; + float _683 = _658 + asfloat(CB1_m[23u].x); + float _688 = clamp(_320 + asfloat(CB1_m[23u].y), 0.0f, 1.0f); + float _715 = asfloat(CB1_m[23u].z); + _742 = _679 ? (_678 + _638) : _638; + _743 = _679 ? mad(_678, _290 + (_678 * mad(-_280, CB0_m0.z, clamp(mad(_310, mad(_688, clamp(abs(mad(frac(_683 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _715), 0.0f, 1.0f))), _639) : _639; + _744 = _679 ? mad(_678, _289 + (_678 * mad(-_279, CB0_m0.y, clamp(mad(_310, mad(_688, clamp(abs(mad(frac(_683 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _715), 0.0f, 1.0f))), _640) : _640; + _745 = _679 ? mad(_678, _288 + (_678 * mad(-_278, CB0_m0.x, clamp(mad(mad(_688, clamp(abs(mad(frac(_683 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _715), 0.0f, 1.0f))), _641) : _641; + } else { + _742 = _638; + _743 = _639; + _744 = _640; + _745 = _641; + } + float _846; + float _847; + float _848; + float _849; + if (!((asfloat(CB1_m[24u].y) == 0.0f) && ((asfloat(CB1_m[24u].x) == 0.0f) && (asfloat(CB1_m[24u].z) == 0.0f)))) { + float _762 = abs(_318); + float _764 = abs(_762 - 0.83333337306976318359375f); + float _782 = min(clamp((asfloat(CB1_m[8u].y) - min(_764, 1.0f - _764)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_320 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _783 = _782 != 0.0f; + float _787 = _762 + asfloat(CB1_m[24u].x); + float _792 = clamp(_320 + asfloat(CB1_m[24u].y), 0.0f, 1.0f); + float _819 = asfloat(CB1_m[24u].z); + _846 = _783 ? (_782 + _742) : _742; + _847 = _783 ? mad(_782, _290 + (_782 * mad(-_280, CB0_m0.z, clamp(mad(mad(_792, clamp(abs(mad(frac(_787 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _819), 0.0f, 1.0f))), _743) : _743; + _848 = _783 ? mad(_782, _289 + (_782 * mad(-_279, CB0_m0.y, clamp(mad(mad(_792, clamp(abs(mad(frac(_787 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _819), 0.0f, 1.0f))), _744) : _744; + _849 = _783 ? mad(_782, _288 + (_782 * mad(-_278, CB0_m0.x, clamp(mad(mad(_792, clamp(abs(mad(frac(_787 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _819), 0.0f, 1.0f))), _745) : _745; + } else { + _846 = _742; + _847 = _743; + _848 = _744; + _849 = _745; + } + float _950; + float _951; + float _952; + float _953; + if (!((asfloat(CB1_m[25u].y) == 0.0f) && ((asfloat(CB1_m[25u].x) == 0.0f) && (asfloat(CB1_m[25u].z) == 0.0f)))) { + float _866 = abs(_318); + float _868 = abs(_866 - 0.16666667163372039794921875f); + float _886 = min(clamp((asfloat(CB1_m[8u].y) - min(_868, 1.0f - _868)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_320 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _887 = _886 != 0.0f; + float _891 = _866 + asfloat(CB1_m[25u].x); + float _896 = clamp(_320 + asfloat(CB1_m[25u].y), 0.0f, 1.0f); + float _923 = asfloat(CB1_m[25u].z); + _950 = _887 ? mad(_886, _290 + (_886 * mad(-_280, CB0_m0.z, clamp(mad(mad(_896, clamp(abs(mad(frac(_891 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _923), 0.0f, 1.0f))), _847) : _847; + _951 = _887 ? mad(_886, _289 + (_886 * mad(-_279, CB0_m0.y, clamp(mad(mad(_896, clamp(abs(mad(frac(_891 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _923), 0.0f, 1.0f))), _848) : _848; + _952 = _887 ? mad(_886, _288 + (_886 * mad(-_278, CB0_m0.x, clamp(mad(mad(_896, clamp(abs(mad(frac(_891 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _310, _923), 0.0f, 1.0f))), _849) : _849; + _953 = _887 ? (_886 + _846) : _846; + } else { + _950 = _847; + _951 = _848; + _952 = _849; + _953 = _846; + } + bool _954 = _953 >= 9.9999997473787516355514526367188e-05f; + _961 = _954 ? (_950 / _953) : _290; + _962 = _954 ? (_951 / _953) : _289; + _963 = _954 ? (_952 / _953) : _288; + } else { + _961 = _290; + _962 = _289; + _963 = _288; + } + float3 _972 = float3(asfloat(CB1_m[9u].x), asfloat(CB1_m[9u].y), asfloat(CB1_m[9u].z)); + float _982 = mad(log2(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _972)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _983 = mad(log2(dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _972)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _984 = mad(log2(dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _972)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float3 _985 = float3(_982, _983, _984); + float _987 = rsqrt(dp3_f32(_985, _985)); + float _994 = asfloat(CB1_m[9u].w) * 0.0555555559694766998291015625f; + float _998 = _994 + ((_987 * _982) * 1.73205089569091796875f); + float _999 = _994 + ((_987 * _983) * 1.73205089569091796875f); + float _1000 = _994 + ((_987 * _984) * 1.73205089569091796875f); + float3 _1009 = float3(asfloat(CB1_m[10u].x), asfloat(CB1_m[10u].y), asfloat(CB1_m[10u].z)); + float _1019 = mad(log2(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _1009)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1020 = mad(log2(dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _1009)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1021 = mad(log2(dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _1009)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float3 _1022 = float3(_1019, _1020, _1021); + float _1024 = rsqrt(dp3_f32(_1022, _1022)); + float _1031 = asfloat(CB1_m[10u].w) * 0.0555555559694766998291015625f; + float _1035 = ((_1019 * _1024) * 1.73205089569091796875f) + _1031; + float _1036 = _1031 + ((_1024 * _1020) * 1.73205089569091796875f); + float _1037 = _1031 + ((_1024 * _1021) * 1.73205089569091796875f); + float3 _1046 = float3(asfloat(CB1_m[11u].x), asfloat(CB1_m[11u].y), asfloat(CB1_m[11u].z)); + float _1056 = mad(log2(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _1046)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1057 = mad(log2(dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _1046)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1058 = mad(log2(dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _1046)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float3 _1059 = float3(_1056, _1057, _1058); + float _1061 = rsqrt(dp3_f32(_1059, _1059)); + float _1068 = asfloat(CB1_m[11u].w) * 0.0555555559694766998291015625f; + float _1081 = clamp((_963 - 0.273893058300018310546875f) * 6.96335124969482421875f, 0.0f, 1.0f); + float _1082 = clamp((_962 - 0.273893058300018310546875f) * 6.96335124969482421875f, 0.0f, 1.0f); + float _1083 = clamp((_961 - 0.273893058300018310546875f) * 6.96335124969482421875f, 0.0f, 1.0f); + float _1099 = clamp((_963 - 0.4584445953369140625f) * 11.35673618316650390625f, 0.0f, 1.0f); + float _1100 = clamp((_962 - 0.4584445953369140625f) * 11.35673618316650390625f, 0.0f, 1.0f); + float _1101 = clamp((_961 - 0.4584445953369140625f) * 11.35673618316650390625f, 0.0f, 1.0f); + float _1131 = asfloat(CB1_m[12u].w); + float _1135 = clamp(mad(_1131, 0.0555555559694766998291015625f, clamp(mad(mad(_1081, -2.0f, 3.0f) * (_1081 * _1081), mad(mad(_1099, -2.0f, 3.0f) * (_1099 * _1099), (((_1056 * _1061) * 1.73205089569091796875f) + _1068) - _1035, _1035) - _998, _998) * _963, 0.0f, 1.0f)), 0.0f, 1.0f); + float _1136 = clamp(mad(_1131, 0.0555555559694766998291015625f, clamp(mad(mad((_1068 + ((_1061 * _1057) * 1.73205089569091796875f)) - _1036, (_1100 * _1100) * mad(_1100, -2.0f, 3.0f), _1036) - _999, (_1082 * _1082) * mad(_1082, -2.0f, 3.0f), _999) * _962, 0.0f, 1.0f)), 0.0f, 1.0f); + float _1137 = clamp(mad(_1131, 0.0555555559694766998291015625f, clamp(mad(mad((_1068 + ((_1061 * _1058) * 1.73205089569091796875f)) - _1037, (_1101 * _1101) * mad(_1101, -2.0f, 3.0f), _1037) - _1000, (_1083 * _1083) * mad(_1083, -2.0f, 3.0f), _1000) * _961, 0.0f, 1.0f)), 0.0f, 1.0f); + float _1140 = asfloat(CB1_m[13u].y); + bool _1141 = _1140 != 1.0f; + float _1148 = exp2((_1135 - 0.449999988079071044921875f) * 18.0f); + float _1149 = exp2((_1136 - 0.449999988079071044921875f) * 18.0f); + float _1150 = exp2((_1137 - 0.449999988079071044921875f) * 18.0f); + float _1155 = dp3_f32(float3(0.25f, 0.5f, 0.25f), float3(_1148 * 0.180000007152557373046875f, _1149 * 0.180000007152557373046875f, _1150 * 0.180000007152557373046875f)); + float _1185 = asfloat(CB1_m[13u].x); + float3 _1200 = float3(asfloat(CB1_m[12u].x), asfloat(CB1_m[12u].y), asfloat(CB1_m[12u].z)); + float _1210 = mad(log2(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _1200)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1211 = mad(log2(dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _1200)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1212 = mad(log2(dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _1200)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float3 _1213 = float3(_1210, _1211, _1212); + float _1215 = rsqrt(dp3_f32(_1213, _1213)); + float _1225 = clamp((clamp(mad((_1141 ? clamp(mad(log2(mad(_1140, mad(_1148, 0.180000007152557373046875f, -_1155), _1155)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1135) - 0.449999988079071044921875f, _1185, 0.449999988079071044921875f), 0.0f, 1.0f) * (_1210 * _1215)) * 1.73205089569091796875f, 0.0f, 1.0f); + float _1226 = clamp(((_1215 * _1211) * clamp(mad(_1185, (_1141 ? clamp(mad(log2(mad(_1140, mad(_1149, 0.180000007152557373046875f, -_1155), _1155)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1136) - 0.449999988079071044921875f, 0.449999988079071044921875f), 0.0f, 1.0f)) * 1.73205089569091796875f, 0.0f, 1.0f); + float _1227 = clamp(((_1215 * _1212) * clamp(mad(_1185, (_1141 ? clamp(mad(log2(mad(_1140, mad(_1150, 0.180000007152557373046875f, -_1155), _1155)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1137) - 0.449999988079071044921875f, 0.449999988079071044921875f), 0.0f, 1.0f)) * 1.73205089569091796875f, 0.0f, 1.0f); + float _1229 = dp3_f32(float3(_1225, _1227, _1226), float3(0.25f, 0.25f, 0.5f)); + bool _1230 = _1229 < 0.4584445953369140625f; + float _1232 = _1230 ? (-0.273893058300018310546875f) : (-0.5464980602264404296875f); + float _1236 = clamp((_1229 + _1232) / ((_1230 ? 0.4175020754337310791015625f : 0.4584445953369140625f) + _1232), 0.0f, 1.0f); + float _1239 = mad(_1236, -2.0f, 3.0f) * (_1236 * _1236); + uint _1240 = _1230 ? 14u : 18u; + float _1247 = asfloat(CB1_m[_1240].x); + float _1248 = asfloat(CB1_m[_1240].y); + float _1249 = asfloat(CB1_m[_1240].z); + float _1250 = asfloat(CB1_m[_1240].w); + float _1268 = mad(_1239, asfloat(CB1_m[16u].w) - _1250, _1250); + uint _1269 = _1230 ? 15u : 19u; + float _1274 = asfloat(CB1_m[_1269].x); + float _1275 = asfloat(CB1_m[_1269].y); + float _1284 = mad(_1239, asfloat(CB1_m[17u].x) - _1274, _1274); + float _1285 = mad(_1239, asfloat(CB1_m[17u].y) - _1275, _1275); + float _1289 = clamp(mad(_1268, 0.0555555559694766998291015625f, _1225), 0.0f, 1.0f); + float _1290 = clamp(mad(_1268, 0.0555555559694766998291015625f, _1226), 0.0f, 1.0f); + float _1291 = clamp(mad(_1268, 0.0555555559694766998291015625f, _1227), 0.0f, 1.0f); + bool _1292 = _1285 != 1.0f; + float _1299 = exp2((_1289 - 0.449999988079071044921875f) * 18.0f); + float _1300 = exp2((_1290 - 0.449999988079071044921875f) * 18.0f); + float _1301 = exp2((_1291 - 0.449999988079071044921875f) * 18.0f); + float _1306 = dp3_f32(float3(0.25f, 0.5f, 0.25f), float3(_1299 * 0.180000007152557373046875f, _1300 * 0.180000007152557373046875f, _1301 * 0.180000007152557373046875f)); + float3 _1340 = float3(mad(_1239, asfloat(CB1_m[16u].x) - _1247, _1247), mad(_1239, asfloat(CB1_m[16u].y) - _1248, _1248), mad(_1239, asfloat(CB1_m[16u].z) - _1249, _1249)); + float _1350 = mad(log2(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _1340)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1351 = mad(log2(dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _1340)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1352 = mad(log2(dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _1340)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float3 _1353 = float3(_1350, _1351, _1352); + float _1355 = rsqrt(dp3_f32(_1353, _1353)); + _1368 = clamp(((_1355 * _1352) * clamp(mad(_1284, (_1292 ? clamp(mad(log2(mad(mad(_1301, 0.180000007152557373046875f, -_1306), _1285, _1306)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1291) - 0.449999988079071044921875f, 0.449999988079071044921875f), 0.0f, 1.0f)) * 1.73205089569091796875f, 0.0f, 1.0f); + _1369 = clamp(((_1355 * _1351) * clamp(mad(_1284, (_1292 ? clamp(mad(log2(mad(mad(_1300, 0.180000007152557373046875f, -_1306), _1285, _1306)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1290) - 0.449999988079071044921875f, 0.449999988079071044921875f), 0.0f, 1.0f)) * 1.73205089569091796875f, 0.0f, 1.0f); + _1370 = clamp((clamp(mad(_1284, (_1292 ? clamp(mad(log2(mad(mad(_1299, 0.180000007152557373046875f, -_1306), _1285, _1306)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1289) - 0.449999988079071044921875f, 0.449999988079071044921875f), 0.0f, 1.0f) * (_1350 * _1355)) * 1.73205089569091796875f, 0.0f, 1.0f); + } else { + _1368 = _290; + _1369 = _289; + _1370 = _288; + } + float _1380 = exp2((clamp(_1370, 0.0f, 1.0f) - 0.449999988079071044921875f) * 18.0f); + float _1381 = exp2((clamp(_1369, 0.0f, 1.0f) - 0.449999988079071044921875f) * 18.0f); + float _1382 = exp2((clamp(_1368, 0.0f, 1.0f) - 0.449999988079071044921875f) * 18.0f); + float _1391 = dp3_f32(float3(_1380 * 0.180000007152557373046875f, _1381 * 0.180000007152557373046875f, _1382 * 0.180000007152557373046875f), asfloat(CB1_m[0u].w).xxx); + float3 _1395 = float3(mad(_1380, 0.180000007152557373046875f, _1391), mad(_1381, 0.180000007152557373046875f, _1391), mad(_1382, 0.180000007152557373046875f, _1391)); + +#if 1 // custom tonemapper + float3 ungraded_bt709 = _1395; + if (RENODX_TONE_MAP_TYPE != 0 && RENODX_TONE_MAP_TYPE != 3.f) { + float contrast = asfloat(CB1_m[4u].y); + U0[CB2_m11.y][gl_GlobalInvocationID] = float4(GenerateOutputAvatar(ungraded_bt709, contrast), 1.f); + return; + } +#endif + + // BT.709 -> AP1 + float3 _1399 = float3(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _1395), dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _1395), dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _1395)); + float _1403 = max(dp3_f32(float3(0.450864851474761962890625f, 0.528371751308441162109375f, 0.02073897421360015869140625f), _1399), 0.0f); + float _1404 = max(dp3_f32(float3(0.1640706360340118408203125f, 0.756849944591522216796875f, 0.079059422016143798828125f), _1399), 0.0f); + float _1405 = max(dp3_f32(float3(-0.004941581748425960540771484375f, 0.001257075113244354724884033203125f, 1.00365674495697021484375f), _1399), 0.0f); + float _1408 = asfloat(CB1_m[1u].y); + float _1421 = exp2(log2(max(_1403 * _1408, 0.0f)) * 0.1593017578125f); + float _1422 = exp2(log2(max(_1404 * _1408, 0.0f)) * 0.1593017578125f); + float _1423 = exp2(log2(max(_1405 * _1408, 0.0f)) * 0.1593017578125f); + float _1439 = exp2(log2(mad(_1421, 18.8515625f, 0.8359375f) / mad(_1421, 18.6875f, 1.0f)) * 78.84375f); + float _1440 = exp2(log2(mad(_1422, 18.8515625f, 0.8359375f) / mad(_1422, 18.6875f, 1.0f)) * 78.84375f); + float3 _1444 = float3(_1439, _1440, exp2(log2(mad(_1423, 18.8515625f, 0.8359375f) / mad(_1423, 18.6875f, 1.0f)) * 78.84375f)); + float _1447 = max(_1405, _1404); + float _1448 = max(_1403, _1447); + float _1451 = asfloat(CB1_m[4u].x); + float _1456 = asfloat(CB1_m[4u].y); + float _1457 = log2(clamp(_1403, _1447, _1451)) * _1456; + float _1461 = asfloat(CB1_m[4u].z); + float _1466 = asfloat(CB1_m[4u].w); + float _1469 = asfloat(CB1_m[5u].x); + float _1471 = exp2(_1457) / mad(exp2(_1457 * _1461), _1466, _1469); + float _1472 = _1403 / _1448; + float _1473 = _1404 / _1448; + float _1474 = _1405 / _1448; + float _1477 = clamp(dp3_f32(float3(_1472, _1473, _1474), float3(0.60000002384185791015625f, 1.5f, -0.300000011920928955078125f)), 0.0f, 1.0f); + float _1491 = exp2(log2(clamp(mad(dp2_f32(0.5f.xx, float2(_1439, _1440)), asfloat(CB1_m[7u].z), asfloat(CB1_m[7u].w)), 0.0f, 1.0f)) * asfloat(CB1_m[8u].x)); + float _1492 = 1.0f - _1491; + float _1502 = mad(_1477, (1.0f - exp2(log2(_1471) * asfloat(CB1_m[5u].y))) + (_1491 - 1.0f), _1492); + float _1506 = mad(_1472 - 1.0f, _1502, 1.0f); + float _1507 = mad(_1473 - 1.0f, _1502, 1.0f); + float _1508 = mad(_1474 - 1.0f, _1502, 1.0f); + float _1517 = asfloat(CB1_m[6u].y); + float _1530 = _1456 * log2(min(_1451, _1448 * mad(1.0f - _1472, _1517, _1472))); + float _1531 = log2(min(mad(1.0f - _1473, _1517, _1473) * _1448, _1451)) * _1456; + float _1532 = log2(min(mad(1.0f - _1474, _1517, _1474) * _1448, _1451)) * _1456; + float _1553 = asfloat(CB1_m[7u].y); + float _1556 = clamp(mad(_1477, asfloat(CB1_m[6u].z) - _1553, _1553), 0.0f, 1.0f); + float _1581 = exp2(log2(max(_1408 * ((_1471 * _1506) + (_1556 * mad(-_1471, _1506, exp2(_1530) / mad(_1466, exp2(_1461 * _1530), _1469)))), 0.0f)) * 0.1593017578125f); + float _1582 = exp2(log2(max(((mad(-_1507, _1471, exp2(_1531) / mad(exp2(_1531 * _1461), _1466, _1469)) * _1556) + (_1507 * _1471)) * _1408, 0.0f)) * 0.1593017578125f); + float _1583 = exp2(log2(max(((mad(-_1508, _1471, exp2(_1532) / mad(exp2(_1532 * _1461), _1466, _1469)) * _1556) + (_1508 * _1471)) * _1408, 0.0f)) * 0.1593017578125f); + float _1599 = exp2(log2(mad(_1581, 18.8515625f, 0.8359375f) / mad(_1581, 18.6875f, 1.0f)) * 78.84375f); + float _1600 = exp2(log2(mad(_1582, 18.8515625f, 0.8359375f) / mad(_1582, 18.6875f, 1.0f)) * 78.84375f); + float3 _1604 = float3(_1599, _1600, exp2(log2(mad(_1583, 18.8515625f, 0.8359375f) / mad(_1583, 18.6875f, 1.0f)) * 78.84375f)); + float _1605 = dp3_f32(float3(1.61370003223419189453125f, -3.323400020599365234375f, 1.70969998836517333984375f), _1604); + float _1606 = dp3_f32(float3(4.377999782562255859375f, -4.245500087738037109375f, -0.132499992847442626953125f), _1604); + float _1610 = _1492 * asfloat(CB1_m[7u].x); + float3 _1615 = float3(dp2_f32(0.5f.xx, float2(_1599, _1600)), mad(_1610, dp3_f32(float3(1.61370003223419189453125f, -3.323400020599365234375f, 1.70969998836517333984375f), _1444) - _1605, _1605), mad(dp3_f32(float3(4.377999782562255859375f, -4.245500087738037109375f, -0.132499992847442626953125f), _1444) - _1606, _1610, _1606)); + float _1625 = exp2(log2(dp3_f32(float3(1.0f, 0.008605144917964935302734375f, 0.111035592854022979736328125f), _1615)) * 0.0126833133399486541748046875f); + float _1626 = exp2(log2(dp3_f32(float3(1.0f, -0.008605144917964935302734375f, -0.111035592854022979736328125f), _1615)) * 0.0126833133399486541748046875f); + float _1627 = exp2(log2(dp3_f32(float3(1.0f, 0.5600488185882568359375f, -0.3206374347209930419921875f), _1615)) * 0.0126833133399486541748046875f); + float _1649 = 1.0f / _1408; + float _1655 = asfloat(CB1_m[6u].w); + float3 _1659 = float3((exp2(log2(max(_1625 - 0.8359375f, 0.0f) / mad(_1625, -18.6875f, 18.8515625f)) * 6.277394771575927734375f) * _1649) * _1655, (exp2(log2(max(_1626 - 0.8359375f, 0.0f) / mad(_1626, -18.6875f, 18.8515625f)) * 6.277394771575927734375f) * _1649) * _1655, (exp2(log2(max(_1627 - 0.8359375f, 0.0f) / mad(_1627, -18.6875f, 18.8515625f)) * 6.277394771575927734375f) * _1649) * _1655); + float3 _1663 = float3(dp3_f32(float3(2.974892139434814453125f, -2.0770013332366943359375f, 0.10213525593280792236328125f), _1659), dp3_f32(float3(-0.646511554718017578125f, 1.77281856536865234375f, -0.12628759443759918212890625f), _1659), dp3_f32(float3(0.015456843189895153045654296875f, -0.01244670711457729339599609375f, 0.99701797962188720703125f), _1659)); + float _1669 = asfloat(CB1_m[1u].x); + float3 _1673 = float3(dp3_f32(float3(1.025799274444580078125f, -0.02005250938236713409423828125f, -0.005771367810666561126708984375f), _1663) * _1669, dp3_f32(float3(-0.00223502493463456630706787109375f, 1.0045826435089111328125f, -0.00235231337137520313262939453125f), _1663) * _1669, dp3_f32(float3(-0.005014003254473209381103515625f, -0.025293387472629547119140625f, 1.03044021129608154296875f), _1663) * _1669); + float _1680 = asfloat(CB1_m[1u].z) * 9.9999997473787516355514526367188e-05f; + float _1681 = dp3_f32(float3(1.66053164005279541015625f, -0.587642610073089599609375f, -0.072840072214603424072265625f), _1673) / _1680; + float _1682 = dp3_f32(float3(-0.12455357611179351806640625f, 1.13290250301361083984375f, -0.0083483643829822540283203125f), _1673) / _1680; + float _1683 = dp3_f32(float3(-0.018151201307773590087890625f, -0.100579082965850830078125f, 1.11858069896697998046875f), _1673) / _1680; + float _1706 = abs(_1681); + float _1707 = abs(_1682); + float _1708 = abs(_1683); + float3 _1745 = float3(_1680 * (float(int(((_1681 < 0.0f) ? 4294967295u : 0u) + uint(_1681 > 0.0f))) * exp2(log2((_1706 > 0.003130800090730190277099609375f) ? mad(exp2(log2(_1706) * 0.4166666567325592041015625f), 1.05499994754791259765625f, -0.054999999701976776123046875f) : (_1706 * 12.9200000762939453125f)) * 2.2000000476837158203125f)), (exp2(log2((_1707 > 0.003130800090730190277099609375f) ? mad(exp2(log2(_1707) * 0.4166666567325592041015625f), 1.05499994754791259765625f, -0.054999999701976776123046875f) : (_1707 * 12.9200000762939453125f)) * 2.2000000476837158203125f) * float(int(uint(_1682 > 0.0f) + ((_1682 < 0.0f) ? 4294967295u : 0u)))) * _1680, (exp2(log2((_1708 > 0.003130800090730190277099609375f) ? mad(exp2(log2(_1708) * 0.4166666567325592041015625f), 1.05499994754791259765625f, -0.054999999701976776123046875f) : (_1708 * 12.9200000762939453125f)) * 2.2000000476837158203125f) * float(int(uint(_1683 > 0.0f) + ((_1683 < 0.0f) ? 4294967295u : 0u)))) * _1680); + float _1755 = exp2(log2(dp3_f32(float3(0.627487957477569580078125f, 0.3292671144008636474609375f, 0.0433014929294586181640625f), _1745)) * 0.1593017578125f); + float _1756 = exp2(log2(dp3_f32(float3(0.06910823285579681396484375f, 0.91951715946197509765625f, 0.01135954819619655609130859375f), _1745)) * 0.1593017578125f); + float _1757 = exp2(log2(dp3_f32(float3(0.01639623381197452545166015625f, 0.0880229771137237548828125f, 0.895499706268310546875f), _1745)) * 0.1593017578125f); + U0[CB2_m11.y][uint3(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y, gl_GlobalInvocationID.z)] = float4( + exp2(log2(mad(_1755, 18.8515625f, 0.8359375f) / mad(_1755, 18.6875f, 1.0f)) * 78.84375f), + exp2(log2(mad(_1756, 18.8515625f, 0.8359375f) / mad(_1756, 18.6875f, 1.0f)) * 78.84375f), + exp2(log2(mad(_1757, 18.8515625f, 0.8359375f) / mad(_1757, 18.6875f, 1.0f)) * 78.84375f), + 1.0f); +} + +[numthreads(8, 8, 1)] +void main(SPIRV_Cross_Input stage_input) { + gl_GlobalInvocationID = stage_input.gl_GlobalInvocationID; + comp_main(); +} diff --git a/src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_no_gamma_correction_0x7F10A5CF.cs_6_0.hlsl b/src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_no_gamma_correction_0x7F10A5CF.cs_6_0.hlsl new file mode 100644 index 000000000..3f74356b7 --- /dev/null +++ b/src/games/avatarfop-swoutlaws/avatarfop/lutbuilder_hdr_no_gamma_correction_0x7F10A5CF.cs_6_0.hlsl @@ -0,0 +1,388 @@ +#include "..\lutbuilder.hlsli" + +cbuffer CB0_buf : register(b2200, space0) { + float3 CB0_m0 : packoffset(c0); + uint CB0_m1 : packoffset(c0.w); +}; + +cbuffer CB1_buf : register(b2201, space0) { + uint4 CB1_m[4096] : packoffset(c0); +}; + +cbuffer CB2_buf : register(b0, space2) { + uint4 CB2_m0 : packoffset(c0); + uint4 CB2_m1 : packoffset(c1); + uint4 CB2_m2 : packoffset(c2); + uint4 CB2_m3 : packoffset(c3); + uint4 CB2_m4 : packoffset(c4); + uint4 CB2_m5 : packoffset(c5); + uint4 CB2_m6 : packoffset(c6); + uint4 CB2_m7 : packoffset(c7); + uint4 CB2_m8 : packoffset(c8); + uint4 CB2_m9 : packoffset(c9); + uint4 CB2_m10 : packoffset(c10); + uint4 CB2_m11 : packoffset(c11); +}; + +RWTexture3D U0[] : register(u0, space2820); + +static uint3 gl_GlobalInvocationID; +struct SPIRV_Cross_Input { + uint3 gl_GlobalInvocationID : SV_DispatchThreadID; +}; + +float dp3_f32(float3 a, float3 b) { + precise float _229 = a.x * b.x; + return mad(a.z, b.z, mad(a.y, b.y, _229)); +} + +float dp2_f32(float2 a, float2 b) { + precise float _217 = a.x * b.x; + return mad(a.y, b.y, _217); +} + +void comp_main() { + float _246 = float(gl_GlobalInvocationID.x); + float _247 = float(gl_GlobalInvocationID.y); + float _248 = float(gl_GlobalInvocationID.z); + float _256 = _246 * CB0_m0.x; + float _257 = _247 * CB0_m0.y; + float _258 = _248 * CB0_m0.z; + float _1336; + float _1337; + float _1338; + if (CB1_m[0u].x != 0u) { + float _929; + float _930; + float _931; + if (CB1_m[0u].y != 0u) { + bool _272 = _258 < _257; + float _273 = _272 ? _257 : _258; + float _274 = _272 ? _258 : _257; + bool _277 = _256 > _273; + float _278 = _277 ? _256 : _273; + float _280 = _277 ? _273 : _256; + float _282 = _278 - min(_274, _280); + float _286 = ((_280 - _274) / mad(_282, 6.0f, 1.0000000133514319600180897396058e-10f)) + (_277 ? (_272 ? 0.0f : (-1.0f)) : (_272 ? (-0.3333333432674407958984375f) : 0.666666686534881591796875f)); + float _288 = _282 / (_278 + 1.0000000133514319600180897396058e-10f); + uint _394; + uint _395; + uint _396; + uint _397; + if (!((asfloat(CB1_m[20u].y) == 0.0f) && ((asfloat(CB1_m[20u].x) == 0.0f) && (asfloat(CB1_m[20u].z) == 0.0f)))) { + float _307 = abs(_286); + float _309 = abs(_307 - 1.0f); + float _327 = min(clamp((asfloat(CB1_m[8u].y) - min(_309, 1.0f - _309)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_288 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _328 = _327 != 0.0f; + float _332 = _307 + asfloat(CB1_m[20u].x); + float _337 = clamp(_288 + asfloat(CB1_m[20u].y), 0.0f, 1.0f); + float _364 = asfloat(CB1_m[20u].z); + _394 = _328 ? asuint(_327) : 0u; + _395 = _328 ? asuint(_327 * (_258 + (_327 * mad(-_248, CB0_m0.z, clamp(mad(mad(_337, clamp(abs(mad(frac(_332 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _364), 0.0f, 1.0f))))) : 0u; + _396 = _328 ? asuint(_327 * (_257 + (_327 * mad(-_247, CB0_m0.y, clamp(mad(mad(_337, clamp(abs(mad(frac(_332 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _364), 0.0f, 1.0f))))) : 0u; + _397 = _328 ? asuint(_327 * (_256 + (_327 * mad(-_246, CB0_m0.x, clamp(mad(mad(_337, clamp(abs(mad(frac(_332 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _364), 0.0f, 1.0f))))) : 0u; + } else { + _394 = 0u; + _395 = 0u; + _396 = 0u; + _397 = 0u; + } + float _398 = asfloat(_397); + float _399 = asfloat(_396); + float _400 = asfloat(_395); + float _401 = asfloat(_394); + float _502; + float _503; + float _504; + float _505; + if (!(((asfloat(CB1_m[21u].x) == 0.0f) && (asfloat(CB1_m[21u].z) == 0.0f)) && (asfloat(CB1_m[21u].y) == 0.0f))) { + float _418 = abs(_286); + float _420 = abs(_418 - 0.3333333432674407958984375f); + float _438 = min(clamp((asfloat(CB1_m[8u].y) - min(_420, 1.0f - _420)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_288 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _439 = _438 != 0.0f; + float _443 = _418 + asfloat(CB1_m[21u].x); + float _448 = clamp(_288 + asfloat(CB1_m[21u].y), 0.0f, 1.0f); + float _475 = asfloat(CB1_m[21u].z); + _502 = _439 ? (_438 + _401) : _401; + _503 = _439 ? mad(_438, _258 + (_438 * mad(-_248, CB0_m0.z, clamp(mad(_278, mad(_448, clamp(abs(mad(frac(_443 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _475), 0.0f, 1.0f))), _400) : _400; + _504 = _439 ? mad(_438, _257 + (_438 * mad(-_247, CB0_m0.y, clamp(mad(_278, mad(_448, clamp(abs(mad(frac(_443 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _475), 0.0f, 1.0f))), _399) : _399; + _505 = _439 ? mad(_438, _256 + (_438 * mad(-_246, CB0_m0.x, clamp(mad(mad(_448, clamp(abs(mad(frac(_443 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _475), 0.0f, 1.0f))), _398) : _398; + } else { + _502 = _401; + _503 = _400; + _504 = _399; + _505 = _398; + } + float _606; + float _607; + float _608; + float _609; + if (!((asfloat(CB1_m[22u].y) == 0.0f) && ((asfloat(CB1_m[22u].x) == 0.0f) && (asfloat(CB1_m[22u].z) == 0.0f)))) { + float _522 = abs(_286); + float _524 = abs(_522 - 0.666666686534881591796875f); + float _542 = min(clamp((asfloat(CB1_m[8u].y) - min(_524, 1.0f - _524)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_288 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _543 = _542 != 0.0f; + float _547 = _522 + asfloat(CB1_m[22u].x); + float _552 = clamp(_288 + asfloat(CB1_m[22u].y), 0.0f, 1.0f); + float _579 = asfloat(CB1_m[22u].z); + _606 = _543 ? (_542 + _502) : _502; + _607 = _543 ? mad(_542, _258 + (_542 * mad(-_248, CB0_m0.z, clamp(mad(_278, mad(_552, clamp(abs(mad(frac(_547 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _579), 0.0f, 1.0f))), _503) : _503; + _608 = _543 ? mad(_542, _257 + (_542 * mad(-_247, CB0_m0.y, clamp(mad(_278, mad(_552, clamp(abs(mad(frac(_547 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _579), 0.0f, 1.0f))), _504) : _504; + _609 = _543 ? mad(_542, _256 + (_542 * mad(-_246, CB0_m0.x, clamp(mad(mad(_552, clamp(abs(mad(frac(_547 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _579), 0.0f, 1.0f))), _505) : _505; + } else { + _606 = _502; + _607 = _503; + _608 = _504; + _609 = _505; + } + float _710; + float _711; + float _712; + float _713; + if (!((asfloat(CB1_m[23u].y) == 0.0f) && ((asfloat(CB1_m[23u].x) == 0.0f) && (asfloat(CB1_m[23u].z) == 0.0f)))) { + float _626 = abs(_286); + float _628 = abs(_626 - 0.5f); + float _646 = min(clamp((asfloat(CB1_m[8u].y) - min(_628, 1.0f - _628)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_288 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _647 = _646 != 0.0f; + float _651 = _626 + asfloat(CB1_m[23u].x); + float _656 = clamp(_288 + asfloat(CB1_m[23u].y), 0.0f, 1.0f); + float _683 = asfloat(CB1_m[23u].z); + _710 = _647 ? (_646 + _606) : _606; + _711 = _647 ? mad(_646, _258 + (_646 * mad(-_248, CB0_m0.z, clamp(mad(mad(_656, clamp(abs(mad(frac(_651 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _683), 0.0f, 1.0f))), _607) : _607; + _712 = _647 ? mad(_646, _257 + (_646 * mad(-_247, CB0_m0.y, clamp(mad(mad(_656, clamp(abs(mad(frac(_651 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _683), 0.0f, 1.0f))), _608) : _608; + _713 = _647 ? mad(_646, _256 + (_646 * mad(-_246, CB0_m0.x, clamp(mad(mad(_656, clamp(abs(mad(frac(_651 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _683), 0.0f, 1.0f))), _609) : _609; + } else { + _710 = _606; + _711 = _607; + _712 = _608; + _713 = _609; + } + float _814; + float _815; + float _816; + float _817; + if (!((asfloat(CB1_m[24u].y) == 0.0f) && ((asfloat(CB1_m[24u].x) == 0.0f) && (asfloat(CB1_m[24u].z) == 0.0f)))) { + float _730 = abs(_286); + float _732 = abs(_730 - 0.83333337306976318359375f); + float _750 = min(clamp((asfloat(CB1_m[8u].y) - min(_732, 1.0f - _732)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_288 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _751 = _750 != 0.0f; + float _755 = _730 + asfloat(CB1_m[24u].x); + float _760 = clamp(_288 + asfloat(CB1_m[24u].y), 0.0f, 1.0f); + float _787 = asfloat(CB1_m[24u].z); + _814 = _751 ? (_750 + _710) : _710; + _815 = _751 ? mad(_750, _258 + (_750 * mad(-_248, CB0_m0.z, clamp(mad(mad(_760, clamp(abs(mad(frac(_755 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _787), 0.0f, 1.0f))), _711) : _711; + _816 = _751 ? mad(_750, _257 + (_750 * mad(-_247, CB0_m0.y, clamp(mad(mad(_760, clamp(abs(mad(frac(_755 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _787), 0.0f, 1.0f))), _712) : _712; + _817 = _751 ? mad(_750, _256 + (_750 * mad(-_246, CB0_m0.x, clamp(mad(mad(_760, clamp(abs(mad(frac(_755 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _787), 0.0f, 1.0f))), _713) : _713; + } else { + _814 = _710; + _815 = _711; + _816 = _712; + _817 = _713; + } + float _918; + float _919; + float _920; + float _921; + if (!((asfloat(CB1_m[25u].y) == 0.0f) && ((asfloat(CB1_m[25u].x) == 0.0f) && (asfloat(CB1_m[25u].z) == 0.0f)))) { + float _834 = abs(_286); + float _836 = abs(_834 - 0.16666667163372039794921875f); + float _854 = min(clamp((asfloat(CB1_m[8u].y) - min(_836, 1.0f - _836)) * asfloat(CB1_m[8u].z), 0.0f, 1.0f), clamp((_288 - asfloat(CB1_m[8u].w)) * 10.0f, 0.0f, 1.0f)); + bool _855 = _854 != 0.0f; + float _859 = _834 + asfloat(CB1_m[25u].x); + float _864 = clamp(_288 + asfloat(CB1_m[25u].y), 0.0f, 1.0f); + float _891 = asfloat(CB1_m[25u].z); + _918 = _855 ? mad(_854, _258 + (_854 * mad(-_248, CB0_m0.z, clamp(mad(mad(_864, clamp(abs(mad(frac(_859 + 0.3333333432674407958984375f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _891), 0.0f, 1.0f))), _815) : _815; + _919 = _855 ? mad(_854, _257 + (_854 * mad(-_247, CB0_m0.y, clamp(mad(mad(_864, clamp(abs(mad(frac(_859 + 0.666666686534881591796875f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _891), 0.0f, 1.0f))), _816) : _816; + _920 = _855 ? mad(_854, _256 + (_854 * mad(-_246, CB0_m0.x, clamp(mad(mad(_864, clamp(abs(mad(frac(_859 + 1.0f), 6.0f, -3.0f)) - 1.0f, 0.0f, 1.0f) - 1.0f, 1.0f), _278, _891), 0.0f, 1.0f))), _817) : _817; + _921 = _855 ? (_854 + _814) : _814; + } else { + _918 = _815; + _919 = _816; + _920 = _817; + _921 = _814; + } + bool _922 = _921 >= 9.9999997473787516355514526367188e-05f; + _929 = _922 ? (_918 / _921) : _258; + _930 = _922 ? (_919 / _921) : _257; + _931 = _922 ? (_920 / _921) : _256; + } else { + _929 = _258; + _930 = _257; + _931 = _256; + } + float3 _940 = float3(asfloat(CB1_m[9u].x), asfloat(CB1_m[9u].y), asfloat(CB1_m[9u].z)); + float _950 = mad(log2(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _940)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _951 = mad(log2(dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _940)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _952 = mad(log2(dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _940)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float3 _953 = float3(_950, _951, _952); + float _955 = rsqrt(dp3_f32(_953, _953)); + float _962 = asfloat(CB1_m[9u].w) * 0.0555555559694766998291015625f; + float _966 = _962 + ((_955 * _950) * 1.73205089569091796875f); + float _967 = _962 + ((_955 * _951) * 1.73205089569091796875f); + float _968 = _962 + ((_955 * _952) * 1.73205089569091796875f); + float3 _977 = float3(asfloat(CB1_m[10u].x), asfloat(CB1_m[10u].y), asfloat(CB1_m[10u].z)); + float _987 = mad(log2(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _977)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _988 = mad(log2(dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _977)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _989 = mad(log2(dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _977)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float3 _990 = float3(_987, _988, _989); + float _992 = rsqrt(dp3_f32(_990, _990)); + float _999 = asfloat(CB1_m[10u].w) * 0.0555555559694766998291015625f; + float _1003 = ((_987 * _992) * 1.73205089569091796875f) + _999; + float _1004 = _999 + ((_992 * _988) * 1.73205089569091796875f); + float _1005 = _999 + ((_992 * _989) * 1.73205089569091796875f); + float3 _1014 = float3(asfloat(CB1_m[11u].x), asfloat(CB1_m[11u].y), asfloat(CB1_m[11u].z)); + float _1024 = mad(log2(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _1014)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1025 = mad(log2(dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _1014)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1026 = mad(log2(dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _1014)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float3 _1027 = float3(_1024, _1025, _1026); + float _1029 = rsqrt(dp3_f32(_1027, _1027)); + float _1036 = asfloat(CB1_m[11u].w) * 0.0555555559694766998291015625f; + float _1049 = clamp((_931 - 0.273893058300018310546875f) * 6.96335124969482421875f, 0.0f, 1.0f); + float _1050 = clamp((_930 - 0.273893058300018310546875f) * 6.96335124969482421875f, 0.0f, 1.0f); + float _1051 = clamp((_929 - 0.273893058300018310546875f) * 6.96335124969482421875f, 0.0f, 1.0f); + float _1067 = clamp((_931 - 0.4584445953369140625f) * 11.35673618316650390625f, 0.0f, 1.0f); + float _1068 = clamp((_930 - 0.4584445953369140625f) * 11.35673618316650390625f, 0.0f, 1.0f); + float _1069 = clamp((_929 - 0.4584445953369140625f) * 11.35673618316650390625f, 0.0f, 1.0f); + float _1099 = asfloat(CB1_m[12u].w); + float _1103 = clamp(mad(_1099, 0.0555555559694766998291015625f, clamp(mad(mad(_1049, -2.0f, 3.0f) * (_1049 * _1049), mad(mad(_1067, -2.0f, 3.0f) * (_1067 * _1067), (((_1024 * _1029) * 1.73205089569091796875f) + _1036) - _1003, _1003) - _966, _966) * _931, 0.0f, 1.0f)), 0.0f, 1.0f); + float _1104 = clamp(mad(_1099, 0.0555555559694766998291015625f, clamp(mad(mad((_1036 + ((_1029 * _1025) * 1.73205089569091796875f)) - _1004, (_1068 * _1068) * mad(_1068, -2.0f, 3.0f), _1004) - _967, (_1050 * _1050) * mad(_1050, -2.0f, 3.0f), _967) * _930, 0.0f, 1.0f)), 0.0f, 1.0f); + float _1105 = clamp(mad(_1099, 0.0555555559694766998291015625f, clamp(mad(mad((_1036 + ((_1029 * _1026) * 1.73205089569091796875f)) - _1005, (_1069 * _1069) * mad(_1069, -2.0f, 3.0f), _1005) - _968, (_1051 * _1051) * mad(_1051, -2.0f, 3.0f), _968) * _929, 0.0f, 1.0f)), 0.0f, 1.0f); + float _1108 = asfloat(CB1_m[13u].y); + bool _1109 = _1108 != 1.0f; + float _1116 = exp2((_1103 - 0.449999988079071044921875f) * 18.0f); + float _1117 = exp2((_1104 - 0.449999988079071044921875f) * 18.0f); + float _1118 = exp2((_1105 - 0.449999988079071044921875f) * 18.0f); + float _1123 = dp3_f32(float3(0.25f, 0.5f, 0.25f), float3(_1116 * 0.180000007152557373046875f, _1117 * 0.180000007152557373046875f, _1118 * 0.180000007152557373046875f)); + float _1153 = asfloat(CB1_m[13u].x); + float3 _1168 = float3(asfloat(CB1_m[12u].x), asfloat(CB1_m[12u].y), asfloat(CB1_m[12u].z)); + float _1178 = mad(log2(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _1168)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1179 = mad(log2(dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _1168)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1180 = mad(log2(dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _1168)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float3 _1181 = float3(_1178, _1179, _1180); + float _1183 = rsqrt(dp3_f32(_1181, _1181)); + float _1193 = clamp((clamp(mad((_1109 ? clamp(mad(log2(mad(_1108, mad(_1116, 0.180000007152557373046875f, -_1123), _1123)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1103) - 0.449999988079071044921875f, _1153, 0.449999988079071044921875f), 0.0f, 1.0f) * (_1178 * _1183)) * 1.73205089569091796875f, 0.0f, 1.0f); + float _1194 = clamp(((_1183 * _1179) * clamp(mad(_1153, (_1109 ? clamp(mad(log2(mad(_1108, mad(_1117, 0.180000007152557373046875f, -_1123), _1123)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1104) - 0.449999988079071044921875f, 0.449999988079071044921875f), 0.0f, 1.0f)) * 1.73205089569091796875f, 0.0f, 1.0f); + float _1195 = clamp(((_1183 * _1180) * clamp(mad(_1153, (_1109 ? clamp(mad(log2(mad(_1108, mad(_1118, 0.180000007152557373046875f, -_1123), _1123)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1105) - 0.449999988079071044921875f, 0.449999988079071044921875f), 0.0f, 1.0f)) * 1.73205089569091796875f, 0.0f, 1.0f); + float _1197 = dp3_f32(float3(_1193, _1195, _1194), float3(0.25f, 0.25f, 0.5f)); + bool _1198 = _1197 < 0.4584445953369140625f; + float _1200 = _1198 ? (-0.273893058300018310546875f) : (-0.5464980602264404296875f); + float _1204 = clamp((_1197 + _1200) / ((_1198 ? 0.4175020754337310791015625f : 0.4584445953369140625f) + _1200), 0.0f, 1.0f); + float _1207 = mad(_1204, -2.0f, 3.0f) * (_1204 * _1204); + uint _1208 = _1198 ? 14u : 18u; + float _1215 = asfloat(CB1_m[_1208].x); + float _1216 = asfloat(CB1_m[_1208].y); + float _1217 = asfloat(CB1_m[_1208].z); + float _1218 = asfloat(CB1_m[_1208].w); + float _1236 = mad(_1207, asfloat(CB1_m[16u].w) - _1218, _1218); + uint _1237 = _1198 ? 15u : 19u; + float _1242 = asfloat(CB1_m[_1237].x); + float _1243 = asfloat(CB1_m[_1237].y); + float _1252 = mad(_1207, asfloat(CB1_m[17u].x) - _1242, _1242); + float _1253 = mad(_1207, asfloat(CB1_m[17u].y) - _1243, _1243); + float _1257 = clamp(mad(_1236, 0.0555555559694766998291015625f, _1193), 0.0f, 1.0f); + float _1258 = clamp(mad(_1236, 0.0555555559694766998291015625f, _1194), 0.0f, 1.0f); + float _1259 = clamp(mad(_1236, 0.0555555559694766998291015625f, _1195), 0.0f, 1.0f); + bool _1260 = _1253 != 1.0f; + float _1267 = exp2((_1257 - 0.449999988079071044921875f) * 18.0f); + float _1268 = exp2((_1258 - 0.449999988079071044921875f) * 18.0f); + float _1269 = exp2((_1259 - 0.449999988079071044921875f) * 18.0f); + float _1274 = dp3_f32(float3(0.25f, 0.5f, 0.25f), float3(_1267 * 0.180000007152557373046875f, _1268 * 0.180000007152557373046875f, _1269 * 0.180000007152557373046875f)); + float3 _1308 = float3(mad(_1207, asfloat(CB1_m[16u].x) - _1215, _1215), mad(_1207, asfloat(CB1_m[16u].y) - _1216, _1216), mad(_1207, asfloat(CB1_m[16u].z) - _1217, _1217)); + float _1318 = mad(log2(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _1308)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1319 = mad(log2(dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _1308)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float _1320 = mad(log2(dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _1308)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f); + float3 _1321 = float3(_1318, _1319, _1320); + float _1323 = rsqrt(dp3_f32(_1321, _1321)); + _1336 = clamp(((_1320 * _1323) * clamp(mad(_1252, (_1260 ? clamp(mad(log2(mad(mad(_1269, 0.180000007152557373046875f, -_1274), _1253, _1274)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1259) - 0.449999988079071044921875f, 0.449999988079071044921875f), 0.0f, 1.0f)) * 1.73205089569091796875f, 0.0f, 1.0f); + _1337 = clamp(((_1319 * _1323) * clamp(mad(_1252, (_1260 ? clamp(mad(log2(mad(mad(_1268, 0.180000007152557373046875f, -_1274), _1253, _1274)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1258) - 0.449999988079071044921875f, 0.449999988079071044921875f), 0.0f, 1.0f)) * 1.73205089569091796875f, 0.0f, 1.0f); + _1338 = clamp((clamp(mad(_1252, (_1260 ? clamp(mad(log2(mad(mad(_1267, 0.180000007152557373046875f, -_1274), _1253, _1274)) + 2.4739310741424560546875f, 0.0555555559694766998291015625f, 0.449999988079071044921875f), 0.0f, 1.0f) : _1257) - 0.449999988079071044921875f, 0.449999988079071044921875f), 0.0f, 1.0f) * (_1318 * _1323)) * 1.73205089569091796875f, 0.0f, 1.0f); + } else { + _1336 = _258; + _1337 = _257; + _1338 = _256; + } + float _1348 = exp2((clamp(_1338, 0.0f, 1.0f) - 0.449999988079071044921875f) * 18.0f); + float _1349 = exp2((clamp(_1337, 0.0f, 1.0f) - 0.449999988079071044921875f) * 18.0f); + float _1350 = exp2((clamp(_1336, 0.0f, 1.0f) - 0.449999988079071044921875f) * 18.0f); + float _1359 = dp3_f32(float3(_1348 * 0.180000007152557373046875f, _1349 * 0.180000007152557373046875f, _1350 * 0.180000007152557373046875f), asfloat(CB1_m[0u].w).xxx); + float3 _1363 = float3(mad(_1348, 0.180000007152557373046875f, _1359), mad(_1349, 0.180000007152557373046875f, _1359), mad(_1350, 0.180000007152557373046875f, _1359)); + +#if 1 // custom tonemapper + float3 ungraded_bt709 = _1363; + if (RENODX_TONE_MAP_TYPE != 0 && RENODX_TONE_MAP_TYPE != 3.f) { + float contrast = asfloat(CB1_m[4u].y); + U0[CB2_m11.y][gl_GlobalInvocationID] = float4(GenerateOutputAvatar(ungraded_bt709, contrast), 1.f); + return; + } +#endif + + // BT.709 -> AP1 + float3 _1367 = float3(dp3_f32(float3(0.61319148540496826171875f, 0.3395120799541473388671875f, 0.0473663322627544403076171875f), _1363), dp3_f32(float3(0.070206902921199798583984375f, 0.9163358211517333984375f, 0.01345001161098480224609375f), _1363), dp3_f32(float3(0.02061887085437774658203125f, 0.109567292034626007080078125f, 0.8696067333221435546875f), _1363)); + float _1371 = max(dp3_f32(float3(0.450864851474761962890625f, 0.528371751308441162109375f, 0.02073897421360015869140625f), _1367), 0.0f); + float _1372 = max(dp3_f32(float3(0.1640706360340118408203125f, 0.756849944591522216796875f, 0.079059422016143798828125f), _1367), 0.0f); + float _1373 = max(dp3_f32(float3(-0.004941581748425960540771484375f, 0.001257075113244354724884033203125f, 1.00365674495697021484375f), _1367), 0.0f); + float _1376 = asfloat(CB1_m[1u].y); + float _1389 = exp2(log2(max(_1371 * _1376, 0.0f)) * 0.1593017578125f); + float _1390 = exp2(log2(max(_1372 * _1376, 0.0f)) * 0.1593017578125f); + float _1391 = exp2(log2(max(_1373 * _1376, 0.0f)) * 0.1593017578125f); + float _1407 = exp2(log2(mad(_1389, 18.8515625f, 0.8359375f) / mad(_1389, 18.6875f, 1.0f)) * 78.84375f); + float _1408 = exp2(log2(mad(_1390, 18.8515625f, 0.8359375f) / mad(_1390, 18.6875f, 1.0f)) * 78.84375f); + float3 _1412 = float3(_1407, _1408, exp2(log2(mad(_1391, 18.8515625f, 0.8359375f) / mad(_1391, 18.6875f, 1.0f)) * 78.84375f)); + float _1415 = max(_1373, _1372); + float _1416 = max(_1371, _1415); + float _1419 = asfloat(CB1_m[4u].x); + float _1424 = asfloat(CB1_m[4u].y); + float _1425 = log2(clamp(_1371, _1415, _1419)) * _1424; + float _1429 = asfloat(CB1_m[4u].z); + float _1434 = asfloat(CB1_m[4u].w); + float _1437 = asfloat(CB1_m[5u].x); + float _1439 = exp2(_1425) / mad(exp2(_1425 * _1429), _1434, _1437); + float _1440 = _1371 / _1416; + float _1441 = _1372 / _1416; + float _1442 = _1373 / _1416; + float _1445 = clamp(dp3_f32(float3(_1440, _1441, _1442), float3(0.60000002384185791015625f, 1.5f, -0.300000011920928955078125f)), 0.0f, 1.0f); + float _1459 = exp2(log2(clamp(mad(dp2_f32(0.5f.xx, float2(_1407, _1408)), asfloat(CB1_m[7u].z), asfloat(CB1_m[7u].w)), 0.0f, 1.0f)) * asfloat(CB1_m[8u].x)); + float _1460 = 1.0f - _1459; + float _1470 = mad(_1445, (1.0f - exp2(log2(_1439) * asfloat(CB1_m[5u].y))) + (_1459 - 1.0f), _1460); + float _1474 = mad(_1440 - 1.0f, _1470, 1.0f); + float _1475 = mad(_1441 - 1.0f, _1470, 1.0f); + float _1476 = mad(_1442 - 1.0f, _1470, 1.0f); + float _1485 = asfloat(CB1_m[6u].y); + float _1498 = _1424 * log2(min(_1419, _1416 * mad(1.0f - _1440, _1485, _1440))); + float _1499 = log2(min(mad(1.0f - _1441, _1485, _1441) * _1416, _1419)) * _1424; + float _1500 = log2(min(mad(1.0f - _1442, _1485, _1442) * _1416, _1419)) * _1424; + float _1521 = asfloat(CB1_m[7u].y); + float _1524 = clamp(mad(_1445, asfloat(CB1_m[6u].z) - _1521, _1521), 0.0f, 1.0f); + float _1549 = exp2(log2(max(_1376 * ((_1439 * _1474) + (_1524 * mad(-_1439, _1474, exp2(_1498) / mad(_1434, exp2(_1429 * _1498), _1437)))), 0.0f)) * 0.1593017578125f); + float _1550 = exp2(log2(max(((mad(-_1475, _1439, exp2(_1499) / mad(exp2(_1499 * _1429), _1434, _1437)) * _1524) + (_1475 * _1439)) * _1376, 0.0f)) * 0.1593017578125f); + float _1551 = exp2(log2(max(((mad(-_1476, _1439, exp2(_1500) / mad(exp2(_1500 * _1429), _1434, _1437)) * _1524) + (_1476 * _1439)) * _1376, 0.0f)) * 0.1593017578125f); + float _1567 = exp2(log2(mad(_1549, 18.8515625f, 0.8359375f) / mad(_1549, 18.6875f, 1.0f)) * 78.84375f); + float _1568 = exp2(log2(mad(_1550, 18.8515625f, 0.8359375f) / mad(_1550, 18.6875f, 1.0f)) * 78.84375f); + float3 _1572 = float3(_1567, _1568, exp2(log2(mad(_1551, 18.8515625f, 0.8359375f) / mad(_1551, 18.6875f, 1.0f)) * 78.84375f)); + float _1573 = dp3_f32(float3(1.61370003223419189453125f, -3.323400020599365234375f, 1.70969998836517333984375f), _1572); + float _1574 = dp3_f32(float3(4.377999782562255859375f, -4.245500087738037109375f, -0.132499992847442626953125f), _1572); + float _1578 = _1460 * asfloat(CB1_m[7u].x); + float3 _1583 = float3(dp2_f32(0.5f.xx, float2(_1567, _1568)), mad(_1578, dp3_f32(float3(1.61370003223419189453125f, -3.323400020599365234375f, 1.70969998836517333984375f), _1412) - _1573, _1573), mad(dp3_f32(float3(4.377999782562255859375f, -4.245500087738037109375f, -0.132499992847442626953125f), _1412) - _1574, _1578, _1574)); + float _1593 = exp2(log2(dp3_f32(float3(1.0f, 0.008605144917964935302734375f, 0.111035592854022979736328125f), _1583)) * 0.0126833133399486541748046875f); + float _1594 = exp2(log2(dp3_f32(float3(1.0f, -0.008605144917964935302734375f, -0.111035592854022979736328125f), _1583)) * 0.0126833133399486541748046875f); + float _1595 = exp2(log2(dp3_f32(float3(1.0f, 0.5600488185882568359375f, -0.3206374347209930419921875f), _1583)) * 0.0126833133399486541748046875f); + float _1617 = 1.0f / _1376; + float _1623 = asfloat(CB1_m[6u].w); + float3 _1627 = float3((exp2(log2(max(_1593 - 0.8359375f, 0.0f) / mad(_1593, -18.6875f, 18.8515625f)) * 6.277394771575927734375f) * _1617) * _1623, (exp2(log2(max(_1594 - 0.8359375f, 0.0f) / mad(_1594, -18.6875f, 18.8515625f)) * 6.277394771575927734375f) * _1617) * _1623, (exp2(log2(max(_1595 - 0.8359375f, 0.0f) / mad(_1595, -18.6875f, 18.8515625f)) * 6.277394771575927734375f) * _1617) * _1623); + float3 _1631 = float3(dp3_f32(float3(2.974892139434814453125f, -2.0770013332366943359375f, 0.10213525593280792236328125f), _1627), dp3_f32(float3(-0.646511554718017578125f, 1.77281856536865234375f, -0.12628759443759918212890625f), _1627), dp3_f32(float3(0.015456843189895153045654296875f, -0.01244670711457729339599609375f, 0.99701797962188720703125f), _1627)); + float _1637 = asfloat(CB1_m[1u].x); + float _1647 = exp2(log2(dp3_f32(float3(1.025799274444580078125f, -0.02005250938236713409423828125f, -0.005771367810666561126708984375f), _1631) * _1637) * 0.1593017578125f); + float _1648 = exp2(log2(dp3_f32(float3(-0.00223502493463456630706787109375f, 1.0045826435089111328125f, -0.00235231337137520313262939453125f), _1631) * _1637) * 0.1593017578125f); + float _1649 = exp2(log2(dp3_f32(float3(-0.005014003254473209381103515625f, -0.025293387472629547119140625f, 1.03044021129608154296875f), _1631) * _1637) * 0.1593017578125f); + U0[CB2_m11.y][uint3(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y, gl_GlobalInvocationID.z)] = float4( + exp2(log2(mad(_1647, 18.8515625f, 0.8359375f) / mad(_1647, 18.6875f, 1.0f)) * 78.84375f), + exp2(log2(mad(_1648, 18.8515625f, 0.8359375f) / mad(_1648, 18.6875f, 1.0f)) * 78.84375f), + exp2(log2(mad(_1649, 18.8515625f, 0.8359375f) / mad(_1649, 18.6875f, 1.0f)) * 78.84375f), + 1.0f); +} + +[numthreads(8, 8, 1)] +void main(SPIRV_Cross_Input stage_input) { + gl_GlobalInvocationID = stage_input.gl_GlobalInvocationID; + comp_main(); +} diff --git a/src/games/avatarfop-swoutlaws/lutbuilder.hlsli b/src/games/avatarfop-swoutlaws/lutbuilder.hlsli index 413851ed5..db37853f1 100644 --- a/src/games/avatarfop-swoutlaws/lutbuilder.hlsli +++ b/src/games/avatarfop-swoutlaws/lutbuilder.hlsli @@ -1,238 +1,24 @@ -#include "./macleod_boynton.hlsli" +#include "./psycho_test17_custom.hlsli" #include "./shared.h" -float3 ApplySDREOTFEmulation(float3 color) { - if (RENODX_SDR_EOTF_EMULATION == 2.f) { - color = renodx::color::correct::Hue(renodx::color::correct::GammaSafe(color), color); - } else if (RENODX_SDR_EOTF_EMULATION == 1.f) { - color = renodx::color::correct::GammaSafe(color); - } - return color; -} - -struct UserGradingConfig { - float exposure; - float highlights; - float shadows; - float contrast; - float flare; - float saturation; - float dechroma; - float hue_emulation_strength; - float highlight_saturation; - float chrominance_emulation; -}; - -UserGradingConfig CreateColorGradeConfig() { - const UserGradingConfig cg_config = { - RENODX_TONE_MAP_EXPOSURE, // float exposure; - RENODX_TONE_MAP_HIGHLIGHTS, // float highlights; - RENODX_TONE_MAP_SHADOWS, // float shadows; - RENODX_TONE_MAP_CONTRAST, // float contrast; - 0.10f * pow(RENODX_TONE_MAP_FLARE, 10.f), // float flare; - RENODX_TONE_MAP_SATURATION, // float saturation; - RENODX_TONE_MAP_DECHROMA, // float dechroma; - 0.f, // float hue_emulation_strength; - -1.f * (RENODX_TONE_MAP_HIGHLIGHT_SATURATION - 1.f), // float highlight_saturation; - 0.f // float chrominance_emulation; - }; - return cg_config; -} - -float Highlights(float x, float highlights, float mid_gray) { - if (highlights == 1.f) return x; - - if (highlights > 1.f) { - return max(x, lerp(x, mid_gray * pow(x / mid_gray, highlights), min(x, 1.f))); - } else { // highlights < 1.f - x /= mid_gray; - return lerp(x, pow(x, highlights), step(1.f, x)) * mid_gray; - } -} - -float Shadows(float x, float shadows, float mid_gray) { - if (shadows == 1.f) return x; - - const float ratio = max(renodx::math::DivideSafe(x, mid_gray, 0.f), 0.f); - const float base_term = x * mid_gray; - const float base_scale = renodx::math::DivideSafe(base_term, ratio, 0.f); - - if (shadows > 1.f) { - float raised = x * (1.f + renodx::math::DivideSafe(base_term, pow(ratio, shadows), 0.f)); - float reference = x * (1.f + base_scale); - return max(x, x + (raised - reference)); - } else { // shadows < 1.f - float lowered = x * (1.f - renodx::math::DivideSafe(base_term, pow(ratio, 2.f - shadows), 0.f)); - float reference = x * (1.f - base_scale); - return clamp(x + (lowered - reference), 0.f, x); - } -} - -float3 ApplyLuminosityGrading(float3 untonemapped, float y, UserGradingConfig config, float mid_gray = 0.18f) { - if (config.exposure == 1.f && config.shadows == 1.f && config.highlights == 1.f && config.contrast == 1.f && config.flare == 0.f) { - return untonemapped; - } - float3 color = untonemapped; - - color *= config.exposure; - - // contrast & flare - const float y_normalized = y / mid_gray; - float flare = renodx::math::DivideSafe(y_normalized + config.flare, y_normalized, 1.f); - float exponent = config.contrast * flare; - const float y_contrasted = pow(y_normalized, exponent) * mid_gray; - - // highlights - float y_highlighted = Highlights(y_contrasted, config.highlights, mid_gray); - - // shadows - float y_shadowed = Shadows(y_highlighted, config.shadows, mid_gray); - - const float y_final = y_shadowed; - - color = renodx::color::correct::Luminance(color, y, y_final); - - return color; -} - -float3 ApplyHueAndPurityGrading( - float3 tonemapped, - float3 hue_reference_color, - float lum, - UserGradingConfig config, - bool clamp_to_ap1 = true, - float curve_gamma = 1.f, - float2 mb_white_override = float2(-1.f, -1.f), - float t_min = 1e-6f) { - float3 color = tonemapped; - if (config.saturation == 1.f && config.dechroma == 0.f && config.hue_emulation_strength == 0.f && config.chrominance_emulation == 0.f && config.highlight_saturation == 0.f) { - return color; - } - - const float kNearWhiteEpsilon = renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON; - const float2 white = (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) - ? mb_white_override - : renodx_custom::color::macleod_boynton::MB_White_D65(); - - float3 color_bt2020 = renodx::color::bt2020::from::BT709(color); - float color_purity01 = renodx_custom::color::macleod_boynton::ApplyBT2020( - color_bt2020, 1.f, 1.f, mb_white_override, t_min) - .purityCur01; - - // MB hue + purity emulation (analog of OkLab hue/chrominance section). - if (config.hue_emulation_strength != 0.f || config.chrominance_emulation != 0.f) { - float3 reference_bt2020 = renodx::color::bt2020::from::BT709(hue_reference_color); - float reference_purity01 = renodx_custom::color::macleod_boynton::ApplyBT2020( - reference_bt2020, 1.f, 1.f, mb_white_override, t_min) - .purityCur01; - - float purity_current = color_purity01; - float purity_ratio = 1.f; - float3 hue_seed_bt2020 = color_bt2020; - - if (config.hue_emulation_strength != 0.f) { - float3 target_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, - mul(renodx::color::BT2020_TO_XYZ_MAT, color_bt2020)); - float3 reference_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, - mul(renodx::color::BT2020_TO_XYZ_MAT, reference_bt2020)); - - float target_t = target_lms.x + target_lms.y; - if (target_t > t_min) { - float2 target_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(target_lms) - white; - float2 reference_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_lms) - white; - - float target_len_sq = dot(target_direction, target_direction); - float reference_len_sq = dot(reference_direction, reference_direction); - - if (target_len_sq > kNearWhiteEpsilon || reference_len_sq > kNearWhiteEpsilon) { - float2 target_unit = (target_len_sq > kNearWhiteEpsilon) - ? target_direction * rsqrt(target_len_sq) - : float2(0.f, 0.f); - float2 reference_unit = (reference_len_sq > kNearWhiteEpsilon) - ? reference_direction * rsqrt(reference_len_sq) - : target_unit; - - if (target_len_sq <= kNearWhiteEpsilon) { - target_unit = reference_unit; - } - - float2 blended_unit = lerp(target_unit, reference_unit, config.hue_emulation_strength); - float blended_len_sq = dot(blended_unit, blended_unit); - if (blended_len_sq <= kNearWhiteEpsilon) { - blended_unit = (config.hue_emulation_strength >= 0.5f) ? reference_unit : target_unit; - blended_len_sq = dot(blended_unit, blended_unit); - } - blended_unit *= rsqrt(max(blended_len_sq, 1e-20f)); - - float seed_len = sqrt(max(target_len_sq, 0.f)); - if (seed_len <= 1e-6f) { - seed_len = sqrt(max(reference_len_sq, 0.f)); - } - seed_len = max(seed_len, 1e-6f); - - hue_seed_bt2020 = mul( - renodx::color::XYZ_TO_BT2020_MAT, - mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, - renodx_custom::color::macleod_boynton::LMS_From_MB_T(white + blended_unit * seed_len, target_t))); - - float purity_post = renodx_custom::color::macleod_boynton::ApplyBT2020( - hue_seed_bt2020, 1.f, 1.f, mb_white_override, t_min) - .purityCur01; - purity_ratio = renodx::math::SafeDivision(purity_current, purity_post, 1.f); - purity_current = purity_post; - } - } - } - - if (config.chrominance_emulation != 0.f) { - float target_purity_ratio = renodx::math::SafeDivision(reference_purity01, purity_current, 1.f); - purity_ratio = lerp(purity_ratio, target_purity_ratio, config.chrominance_emulation); - } - - float applied_purity01 = saturate(purity_current * max(purity_ratio, 0.f)); - color_bt2020 = renodx_custom::color::macleod_boynton::ApplyBT2020( - hue_seed_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) - .rgbOut; - color_purity01 = applied_purity01; - } - - float purity_scale = 1.f; - - // dechroma - if (config.dechroma != 0.f) { - purity_scale *= lerp(1.f, 0.f, saturate(pow(lum / (10000.f / 100.f), (1.f - config.dechroma)))); - } - - // highlight saturation - if (config.highlight_saturation != 0.f) { - float percent_max = saturate(lum * 100.f / 10000.f); - // positive = 1 to 0, negative = 1 to 2 - float blowout_strength = 100.f; - float blowout_change = pow(1.f - percent_max, blowout_strength * abs(config.highlight_saturation)); - if (config.highlight_saturation < 0) { - blowout_change = (2.f - blowout_change); - } - - purity_scale *= blowout_change; - } - - // saturation - purity_scale *= config.saturation; - - if (purity_scale != 1.f) { - float scaled_purity01 = saturate(color_purity01 * max(purity_scale, 0.f)); - color_bt2020 = renodx_custom::color::macleod_boynton::ApplyBT2020( - color_bt2020, scaled_purity01, curve_gamma, mb_white_override, t_min) - .rgbOut; - } +float3 ApplySDREOTFEmulation(float3 color_input) { + float3 color_corrected; + if (RENODX_SDR_EOTF_EMULATION == 1.f) { + color_corrected = renodx::color::correct::GammaSafe(color_input); + } else if (RENODX_SDR_EOTF_EMULATION == 2.f) { + float y_in = renodx::color::yf::from::BT709(color_input); + float y_out = renodx::color::correct::Gamma(max(0, y_in)); + float3 color_corrected_lum = renodx::color::correct::Luminance(color_input, y_in, y_out); - color = renodx::color::bt709::from::BT2020(color_bt2020); + float3 color_corrected_ch = renodx::color::correct::GammaSafe(color_input); - if (clamp_to_ap1) { - color = renodx::color::bt709::clamp::AP1(color); + color_corrected = renodx::color::bt709::from::BT2020(renodx_custom::tonemap::psycho::psycho17_ApplyPurityFromBT2020( + renodx::color::bt2020::from::BT709(color_corrected_ch), renodx::color::bt2020::from::BT709(color_corrected_lum), 1.f, 1.f)); + } else { + color_corrected = color_input; } - return color; + return color_corrected; } #define SPLIT_CONTRAST_FUNCTION_GENERATOR(T) \ @@ -248,36 +34,27 @@ SPLIT_CONTRAST_FUNCTION_GENERATOR(float3) #undef SPLIT_CONTRAST_FUNCTION_GENERATOR -float3 ApplyUserGrading(float3 ungraded) { - UserGradingConfig cg_config = CreateColorGradeConfig(); - float y = renodx::color::y::from::BT709(ungraded); - float3 graded = ApplyLuminosityGrading(ungraded, y, cg_config); - graded = ApplyHueAndPurityGrading(graded, ungraded, y, cg_config, false); - - return graded; -} - float3 GenerateOutputAvatar(float3 ungraded_bt709, float contrast) { float3 graded_bt709; if (RENODX_TONE_MAP_TYPE == 1.f) { // None graded_bt709 = ungraded_bt709; if (RENODX_SDR_EOTF_EMULATION == 2.f) { - float lum_in = LuminosityFromBT709LuminanceNormalized(ungraded_bt709); + float lum_in = renodx::color::y::from::BT709(ungraded_bt709); float lum_out = renodx::color::correct::GammaSafe(lum_in); float3 corrected_lum = renodx::color::correct::Luminance(ungraded_bt709, lum_in, lum_out); float3 corrected_ch = renodx::color::correct::GammaSafe(ungraded_bt709); - graded_bt709 = CorrectPurityMB(corrected_lum, corrected_ch); + graded_bt709 = renodx_custom::tonemap::psycho::psycho17_ApplyPurityFromBT2020(corrected_lum, corrected_ch, 1.f, 1.f); } - } else { // Vanilla+ - // `pow(c, contrast) * 2.f` per channel will essentially give uncapped version of vanilla + } else { // RenoDX + // `pow(c, contrast) * exposure_adjustment` per channel will essentially give uncapped version of vanilla float shadow_contrast = contrast; // lower highlight contrast so image isn't overly harsh, but make sure sun still reaches 100.f (10k nits with 100 game brightness) float highlight_contrast = contrast * 0.681f; float exposure_adjustment = 2.f; - // apply by luminosity to keep hues intact and scale lightness evenly - float lum_in = LuminosityFromBT709LuminanceNormalized(ungraded_bt709); + // apply by yf to keep hues intact and scale lightness evenly + float lum_in = renodx::color::yf::from::BT709(ungraded_bt709); float lum_out = SplitContrast(lum_in, shadow_contrast, highlight_contrast, 1.f) * exposure_adjustment; if (RENODX_SDR_EOTF_EMULATION == 2.f) { lum_out = renodx::color::correct::GammaSafe(lum_out); @@ -285,56 +62,84 @@ float3 GenerateOutputAvatar(float3 ungraded_bt709, float contrast) { float3 contrasted_lum = renodx::color::correct::Luminance(ungraded_bt709, lum_in, lum_out); // apply grading per channel as reference color to take purity from - float3 contrasted_ch = renodx::color::bt709::from::BT2020(SplitContrast(renodx::color::bt2020::from::BT709(ungraded_bt709), shadow_contrast, highlight_contrast, 1.f) * exposure_adjustment); + float3 contrasted_ch = SplitContrast(ungraded_bt709, shadow_contrast, highlight_contrast, 1.f) * exposure_adjustment; if (RENODX_SDR_EOTF_EMULATION == 2.f) { contrasted_ch = renodx::color::correct::GammaSafe(contrasted_ch); } - // use reinhard to blow out and hue shift, peak of 10.f found to look good in testing - float3 hue_and_chrominance_source = renodx::tonemap::ReinhardPiecewise(contrasted_ch, 10.f, 1.f); - // apply purity and hue (only on highlights) of per channel contrasted to luminosity contrasted - // this gives us our graded color which will be compressed by max channel to monitor peak later - graded_bt709 = CorrectHueAndPurityMBGated(contrasted_lum, hue_and_chrominance_source, 1.f, 1.f, 2.f); + // apply purity of per channel contrasted to yf contrasted + // this gives us our graded color which will be tonemapped to monitor peak later + graded_bt709 = renodx::color::bt709::from::BT2020( + renodx_custom::tonemap::psycho::psycho17_ApplyPurityFromBT2020( + renodx::color::bt2020::from::BT709(contrasted_ch), + renodx::color::bt2020::from::BT709(contrasted_lum), 1.f, 1.f)); } if (RENODX_SDR_EOTF_EMULATION == 1.f) { graded_bt709 = renodx::color::correct::GammaSafe(graded_bt709); } - float3 final_bt709 = ApplyUserGrading(graded_bt709); + float3 final_bt709 = graded_bt709; float3 color_bt2020 = renodx::color::bt2020::from::BT709(final_bt709); - if (RENODX_TONE_MAP_TYPE == 2.f) { // display map by max channel - color_bt2020 = renodx::tonemap::neutwo::MaxChannel(color_bt2020, RENODX_PEAK_WHITE_NITS / RENODX_DIFFUSE_WHITE_NITS, RENODX_TONE_MAP_WHITE_CLIP); - } + renodx_custom::tonemap::psycho::config17::Config psycho17_config = + renodx_custom::tonemap::psycho::config17::Create(); + psycho17_config.peak_value = RENODX_PEAK_WHITE_NITS / RENODX_DIFFUSE_WHITE_NITS; + psycho17_config.clip_point = RENODX_TONE_MAP_WHITE_CLIP; + psycho17_config.exposure = RENODX_TONE_MAP_EXPOSURE; + psycho17_config.gamma = RENODX_TONE_MAP_GAMMA; + psycho17_config.highlights = RENODX_TONE_MAP_HIGHLIGHTS; + psycho17_config.shadows = RENODX_TONE_MAP_SHADOWS; + psycho17_config.contrast = RENODX_TONE_MAP_CONTRAST; + psycho17_config.flare = 0.10f * pow(RENODX_TONE_MAP_FLARE, 10.f); + psycho17_config.contrast_highlights = RENODX_TONE_MAP_CONTRAST_HIGHLIGHTS; + psycho17_config.contrast_shadows = RENODX_TONE_MAP_CONTRAST_SHADOWS; + psycho17_config.purity_scale = RENODX_TONE_MAP_SATURATION; + psycho17_config.purity_highlights = -1.f * (RENODX_TONE_MAP_HIGHLIGHT_SATURATION - 1.f); + psycho17_config.dechroma = RENODX_TONE_MAP_DECHROMA; + psycho17_config.adaptation_contrast = RENODX_TONE_MAP_ADAPTATION_CONTRAST; + psycho17_config.bleaching_intensity = 0.f; + psycho17_config.hue_emulation = RENODX_TONE_MAP_HUE_EMULATION; + psycho17_config.pre_gamut_compress = false; + psycho17_config.post_gamut_compress = true; + + if (RENODX_TONE_MAP_TYPE == 1.f) { + psycho17_config.apply_tonemap = false; + } + + float3 hue_shift_source_bt2020 = color_bt2020; + if (psycho17_config.hue_emulation != 0.f) { + hue_shift_source_bt2020 = renodx::tonemap::ReinhardPiecewise(color_bt2020, 2.5f, psycho17_config.mid_gray); + } + color_bt2020 = renodx_custom::tonemap::psycho::ApplyTest17BT2020(color_bt2020, hue_shift_source_bt2020, psycho17_config); float3 color_pq = renodx::color::pq::EncodeSafe(color_bt2020, RENODX_DIFFUSE_WHITE_NITS); return color_pq; } -float3 GenerateOutputStarWarsOutlaws(float3 ungraded_bt709, float contrast) { +float3 GenerateOutputOutlaws(float3 ungraded_bt709, float contrast) { float3 graded_bt709; if (RENODX_TONE_MAP_TYPE == 1.f) { // None graded_bt709 = ungraded_bt709; if (RENODX_SDR_EOTF_EMULATION == 2.f) { - float lum_in = LuminosityFromBT709LuminanceNormalized(ungraded_bt709); + float lum_in = renodx::color::y::from::BT709(ungraded_bt709); float lum_out = renodx::color::correct::GammaSafe(lum_in); float3 corrected_lum = renodx::color::correct::Luminance(ungraded_bt709, lum_in, lum_out); float3 corrected_ch = renodx::color::correct::GammaSafe(ungraded_bt709); - graded_bt709 = CorrectPurityMB(corrected_lum, corrected_ch); + graded_bt709 = renodx_custom::tonemap::psycho::psycho17_ApplyPurityFromBT2020(corrected_lum, corrected_ch, 1.f, 1.f); } - } else { // Vanilla+ - // `pow(c, contrast) * 2.f` per channel will essentially give uncapped version of vanilla + } else { // RenoDX + // `pow(c, contrast) * exposure_adjustment` per channel will essentially give uncapped version of vanilla float shadow_contrast = contrast; // lower highlight contrast so image isn't overly harsh, but make sure sun still reaches 100.f (10k nits with 100 game brightness) float highlight_contrast = contrast * 0.7375f; float exposure_adjustment = 1.7f; - // apply by luminosity to keep hues intact and scale lightness evenly - float lum_in = LuminosityFromBT709LuminanceNormalized(ungraded_bt709); + // apply by yf to keep hues intact and scale lightness evenly + float lum_in = renodx::color::yf::from::BT709(ungraded_bt709); float lum_out = SplitContrast(lum_in, shadow_contrast, highlight_contrast, 1.f) * exposure_adjustment; if (RENODX_SDR_EOTF_EMULATION == 2.f) { lum_out = renodx::color::correct::GammaSafe(lum_out); @@ -342,31 +147,59 @@ float3 GenerateOutputStarWarsOutlaws(float3 ungraded_bt709, float contrast) { float3 contrasted_lum = renodx::color::correct::Luminance(ungraded_bt709, lum_in, lum_out); // apply grading per channel as reference color to take purity from - float3 contrasted_ch = renodx::color::bt709::from::BT2020(SplitContrast(renodx::color::bt2020::from::BT709(ungraded_bt709), shadow_contrast, highlight_contrast, 1.f) * exposure_adjustment); + float3 contrasted_ch = SplitContrast(ungraded_bt709, shadow_contrast, highlight_contrast, 1.f) * exposure_adjustment; if (RENODX_SDR_EOTF_EMULATION == 2.f) { contrasted_ch = renodx::color::correct::GammaSafe(contrasted_ch); } - // use reinhard to blow out and hue shift, peak of 10.f found to look good in testing - float3 hue_and_chrominance_source = renodx::tonemap::ReinhardPiecewise(contrasted_ch, 10.f, 1.f); - // apply purity and hue (only on highlights) of per channel contrasted to luminosity contrasted - // this gives us our graded color which will be compressed by max channel to monitor peak later - graded_bt709 = CorrectHueAndPurityMBGated(contrasted_lum, hue_and_chrominance_source, 1.f, 1.f, 2.f); + // apply purity of per channel contrasted to yf contrasted + // this gives us our graded color which will be tonemapped to monitor peak later + graded_bt709 = renodx::color::bt709::from::BT2020( + renodx_custom::tonemap::psycho::psycho17_ApplyPurityFromBT2020( + renodx::color::bt2020::from::BT709(contrasted_ch), + renodx::color::bt2020::from::BT709(contrasted_lum), 1.f, 1.f)); } if (RENODX_SDR_EOTF_EMULATION == 1.f) { graded_bt709 = renodx::color::correct::GammaSafe(graded_bt709); } - float3 final_bt709 = ApplyUserGrading(graded_bt709); + float3 final_bt709 = graded_bt709; float3 color_bt2020 = renodx::color::bt2020::from::BT709(final_bt709); - if (RENODX_TONE_MAP_TYPE == 2.f) { // display map by max channel - color_bt2020 = renodx::tonemap::neutwo::MaxChannel(color_bt2020, RENODX_PEAK_WHITE_NITS / RENODX_DIFFUSE_WHITE_NITS, RENODX_TONE_MAP_WHITE_CLIP); - } + renodx_custom::tonemap::psycho::config17::Config psycho17_config = + renodx_custom::tonemap::psycho::config17::Create(); + psycho17_config.peak_value = RENODX_PEAK_WHITE_NITS / RENODX_DIFFUSE_WHITE_NITS; + psycho17_config.clip_point = RENODX_TONE_MAP_WHITE_CLIP; + psycho17_config.exposure = RENODX_TONE_MAP_EXPOSURE; + psycho17_config.gamma = RENODX_TONE_MAP_GAMMA; + psycho17_config.highlights = RENODX_TONE_MAP_HIGHLIGHTS; + psycho17_config.shadows = RENODX_TONE_MAP_SHADOWS; + psycho17_config.contrast = RENODX_TONE_MAP_CONTRAST; + psycho17_config.flare = 0.10f * pow(RENODX_TONE_MAP_FLARE, 10.f); + psycho17_config.contrast_highlights = RENODX_TONE_MAP_CONTRAST_HIGHLIGHTS; + psycho17_config.contrast_shadows = RENODX_TONE_MAP_CONTRAST_SHADOWS; + psycho17_config.purity_scale = RENODX_TONE_MAP_SATURATION; + psycho17_config.purity_highlights = -1.f * (RENODX_TONE_MAP_HIGHLIGHT_SATURATION - 1.f); + psycho17_config.dechroma = RENODX_TONE_MAP_DECHROMA; + psycho17_config.adaptation_contrast = RENODX_TONE_MAP_ADAPTATION_CONTRAST; + psycho17_config.bleaching_intensity = 0.f; + psycho17_config.hue_emulation = RENODX_TONE_MAP_HUE_EMULATION; + psycho17_config.pre_gamut_compress = false; + psycho17_config.post_gamut_compress = true; + + if (RENODX_TONE_MAP_TYPE == 1.f) { + psycho17_config.apply_tonemap = false; + } + + float3 hue_shift_source_bt2020 = color_bt2020; + if (psycho17_config.hue_emulation != 0.f) { + hue_shift_source_bt2020 = renodx::tonemap::ReinhardPiecewise(color_bt2020, 2.5f, psycho17_config.mid_gray); + } + color_bt2020 = renodx_custom::tonemap::psycho::ApplyTest17BT2020(color_bt2020, hue_shift_source_bt2020, psycho17_config); float3 color_pq = renodx::color::pq::EncodeSafe(color_bt2020, RENODX_DIFFUSE_WHITE_NITS); return color_pq; -} +} \ No newline at end of file diff --git a/src/games/avatarfop-swoutlaws/macleod_boynton.hlsli b/src/games/avatarfop-swoutlaws/macleod_boynton.hlsli index 36992fdf2..1e5bf8768 100644 --- a/src/games/avatarfop-swoutlaws/macleod_boynton.hlsli +++ b/src/games/avatarfop-swoutlaws/macleod_boynton.hlsli @@ -1,5 +1,5 @@ -#ifndef XSRC_SHADERS_COLOR_MACLEOD_BOYNTON_HLSL_ -#define XSRC_SHADERS_COLOR_MACLEOD_BOYNTON_HLSL_ +#ifndef SRC_GAMES_CRIMSONDESERT_MACLEOD_BOYNTON_HLSLI_ +#define SRC_GAMES_CRIMSONDESERT_MACLEOD_BOYNTON_HLSLI_ #include "./shared.h" @@ -522,34 +522,42 @@ float Purity01FromBT2020MB( return saturate(p_cur); } -float3 CorrectPurityMB( +float3 CorrectPurityMBBT709WithBT2020( float3 target_color_bt709, float3 purity_reference_bt709, float strength = 1.f, float curve_gamma = 1.f, float2 mb_white_override = float2(-1.f, -1.f), - float t_min = 1e-6f) { + float t_min = 1e-7f, + float clamp_purity_loss = 0.f) { if (strength <= 0.f) return target_color_bt709; float3 target_color_bt2020 = renodx::color::bt2020::from::BT709(target_color_bt709); float3 purity_reference_bt2020 = renodx::color::bt2020::from::BT709(purity_reference_bt709); + float reference_purity01 = + renodx_custom::color::macleod_boynton::ApplyBT2020(purity_reference_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01; + float applied_purity01; - if (strength == 1.f) { + if (strength == 1.f && clamp_purity_loss <= 0.f) { // Fast path: full transfer only needs donor purity. - applied_purity01 = - renodx_custom::color::macleod_boynton::ApplyBT2020(purity_reference_bt2020, 1.f, 1.f, - mb_white_override, t_min) - .purityCur01; + applied_purity01 = reference_purity01; } else { - applied_purity01 = lerp( + float target_purity01 = renodx_custom::color::macleod_boynton::ApplyBT2020(target_color_bt2020, 1.f, 1.f, mb_white_override, t_min) - .purityCur01, - renodx_custom::color::macleod_boynton::ApplyBT2020(purity_reference_bt2020, 1.f, 1.f, - mb_white_override, t_min) - .purityCur01, - strength); + .purityCur01; + + applied_purity01 = lerp(target_purity01, reference_purity01, strength); + + if (clamp_purity_loss > 0.f) { + float clamp_strength = saturate(clamp_purity_loss); + // Only clamp purity reductions: if applied < target, pull back toward target. + float t = 1.f - step(target_purity01, applied_purity01); + applied_purity01 = lerp(applied_purity01, target_purity01, t * clamp_strength); + } } return renodx::color::bt709::from::BT2020( @@ -558,22 +566,26 @@ float3 CorrectPurityMB( .rgbOut); } -float3 CorrectHueAndPurityMB( +float3 CorrectHueAndPurityMBBT709WithBT2020( float3 target_color_bt709, float3 reference_color_bt709, - float purity_scale = 1.f, + float hue_strength = 1.f, + float purity_strength = 1.f, float curve_gamma = 1.f, float2 mb_white_override = float2(-1.f, -1.f), float t_min = 1e-6f) { + if (purity_strength <= 0.f && hue_strength <= 0.f) { + return target_color_bt709; + } + + if (hue_strength <= 0.f) { + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); + } + float3 target_color_bt2020 = renodx::color::bt2020::from::BT709(target_color_bt709); float3 reference_color_bt2020 = renodx::color::bt2020::from::BT709(reference_color_bt709); - float reference_purity01 = saturate( - renodx_custom::color::macleod_boynton::ApplyBT2020(reference_color_bt2020, 1.f, 1.f, - mb_white_override, t_min) - .purityCur01 - * max(purity_scale, 0.f)); - float3 target_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, mul(renodx::color::BT2020_TO_XYZ_MAT, target_color_bt2020)); float target_t = target_lms.x + target_lms.y; @@ -581,6 +593,26 @@ float3 CorrectHueAndPurityMB( return target_color_bt709; } + float hue_blend = saturate(hue_strength); + + if (hue_blend <= 0.f) { + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); + } + + float target_purity01 = + renodx_custom::color::macleod_boynton::ApplyBT2020(target_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01; + float applied_purity01 = target_purity01; + if (purity_strength > 0.f) { + float reference_purity01 = + renodx_custom::color::macleod_boynton::ApplyBT2020(reference_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01; + applied_purity01 = lerp(target_purity01, reference_purity01, saturate(purity_strength)); + } + float3 reference_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, mul(renodx::color::BT2020_TO_XYZ_MAT, reference_color_bt2020)); @@ -590,38 +622,143 @@ float3 CorrectHueAndPurityMB( float2 target_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(target_lms) - white; float2 reference_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_lms) - white; + + float target_len_sq = dot(target_direction, target_direction); float reference_len_sq = dot(reference_direction, reference_direction); - // If donor hue is undefined (near white), fallback to purity-only transfer. - if (reference_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { - return renodx::color::bt709::from::BT2020( - renodx_custom::color::macleod_boynton::ApplyBT2020( - target_color_bt2020, reference_purity01, curve_gamma, mb_white_override, t_min) - .rgbOut); + if (target_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON && reference_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); } - float2 mb_seed = white + reference_direction * rsqrt(reference_len_sq) * length(target_direction); + float2 target_unit = (target_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? target_direction * rsqrt(target_len_sq) + : float2(0.f, 0.f); + float2 reference_unit = (reference_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? reference_direction * rsqrt(reference_len_sq) + : target_unit; + if (target_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + target_unit = reference_unit; + } - float3 lms_seed = renodx_custom::color::macleod_boynton::LMS_From_MB_T(mb_seed, target_t); - float3 xyz_seed = mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, lms_seed); - float3 seed_bt2020 = mul(renodx::color::XYZ_TO_BT2020_MAT, xyz_seed); + float2 blended_unit = lerp(target_unit, reference_unit, hue_blend); + float blended_len_sq = dot(blended_unit, blended_unit); + if (blended_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + blended_unit = (hue_blend >= 0.5f) ? reference_unit : target_unit; + blended_len_sq = dot(blended_unit, blended_unit); + } + blended_unit *= rsqrt(max(blended_len_sq, 1e-20f)); + + float seed_len = sqrt(max(target_len_sq, 0.f)); + if (seed_len <= 1e-6f) { + seed_len = sqrt(max(reference_len_sq, 0.f)); + } + seed_len = max(seed_len, 1e-6f); + + float3 seed_bt2020 = mul( + renodx::color::XYZ_TO_BT2020_MAT, + mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, + renodx_custom::color::macleod_boynton::LMS_From_MB_T(white + blended_unit * seed_len, target_t))); return renodx::color::bt709::from::BT2020( renodx_custom::color::macleod_boynton::ApplyBT2020( - seed_bt2020, reference_purity01, curve_gamma, mb_white_override, t_min) + seed_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) .rgbOut); } -// Full-strength single-reference transfer: -// - Hue from reference at full strength. -// - Purity from reference at full strength. -// - No luminance/ramp gating. -float3 CorrectHueAndPurityMBFullStrength( - float3 target_color_bt709, - float3 reference_color_bt709, +float3 CorrectHueAndPurityMB_BT2020( + float3 target_color_bt2020, + float3 reference_color_bt2020, + float hue_strength = 1.f, + float purity_strength = 1.f, + float curve_gamma = 1.f, float2 mb_white_override = float2(-1.f, -1.f), - float t_min = 1e-6f) { - return CorrectHueAndPurityMB(target_color_bt709, reference_color_bt709, 1.f, mb_white_override, t_min); + float t_min = 1e-7f) { + if (purity_strength <= 0.f && hue_strength <= 0.f) { + return target_color_bt2020; + } + + float applied_purity01 = lerp( + renodx_custom::color::macleod_boynton::ApplyBT2020(target_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01, + renodx_custom::color::macleod_boynton::ApplyBT2020(reference_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01, + saturate(purity_strength)); + + if (hue_strength <= 0.f) { + return renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut; + } + + float3 target_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, target_color_bt2020)); + float target_t = target_lms.x + target_lms.y; + if (target_t <= t_min) { + return target_color_bt2020; + } + + float hue_blend = saturate(hue_strength); + + if (hue_blend <= 0.f) { + return renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut; + } + + float3 reference_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, reference_color_bt2020)); + + float2 white = (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) + ? mb_white_override + : renodx_custom::color::macleod_boynton::MB_White_D65(); + + float2 target_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(target_lms) - white; + float2 reference_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_lms) - white; + + float target_len_sq = dot(target_direction, target_direction); + float reference_len_sq = dot(reference_direction, reference_direction); + + if (target_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON && reference_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + return renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut; + } + + float2 target_unit = (target_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? target_direction * rsqrt(target_len_sq) + : float2(0.f, 0.f); + float2 reference_unit = (reference_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? reference_direction * rsqrt(reference_len_sq) + : target_unit; + if (target_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + target_unit = reference_unit; + } + + float2 blended_unit = lerp(target_unit, reference_unit, hue_blend); + float blended_len_sq = dot(blended_unit, blended_unit); + if (blended_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + blended_unit = (hue_blend >= 0.5f) ? reference_unit : target_unit; + blended_len_sq = dot(blended_unit, blended_unit); + } + blended_unit *= rsqrt(max(blended_len_sq, 1e-20f)); + + float seed_len = sqrt(max(target_len_sq, 0.f)); + if (seed_len <= 1e-6f) { + seed_len = sqrt(max(reference_len_sq, 0.f)); + } + seed_len = max(seed_len, 1e-6f); + + float3 seed_bt2020 = mul( + renodx::color::XYZ_TO_BT2020_MAT, + mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, + renodx_custom::color::macleod_boynton::LMS_From_MB_T(white + blended_unit * seed_len, target_t))); + + return renodx_custom::color::macleod_boynton::ApplyBT2020( + seed_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut; } float3 CorrectHueAndPurityMBGated( @@ -639,8 +776,8 @@ float3 CorrectHueAndPurityMBGated( } if (hue_strength <= 0.f) { - return CorrectPurityMB(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, - mb_white_override, t_min); + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); } float3 target_color_bt2020 = renodx::color::bt2020::from::BT709(target_color_bt709); @@ -657,8 +794,8 @@ float3 CorrectHueAndPurityMBGated( float hue_blend = hue_strength * saturate((target_t - hue_t_ramp_start) / (hue_t_ramp_end - hue_t_ramp_start)); if (hue_blend <= 0.f) { - return CorrectPurityMB(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, - mb_white_override, t_min); + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); } float applied_purity01 = lerp( @@ -684,8 +821,8 @@ float3 CorrectHueAndPurityMBGated( float reference_len_sq = dot(reference_direction, reference_direction); if (target_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON && reference_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { - return CorrectPurityMB(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, - mb_white_override, t_min); + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); } float2 target_unit = (target_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) @@ -1144,4 +1281,26 @@ float LuminosityFromBT709LuminanceNormalized(float3 bt709_linear) { return luminosity / LuminosityFromBT709(1.f); } -#endif // XSRC_SHADERS_COLOR_MACLEOD_BOYNTON_HLSL_ +float LuminosityFromBT2020(float3 bt2020_linear) { + float3 xyz = mul(renodx::color::BT2020_TO_XYZ_MAT, bt2020_linear); + float3 lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, xyz); + return 1.55f * lms.x + lms.y; +} + +float LuminosityFromBT2020LuminanceNormalized(float3 bt2020_linear) { + float luminosity = LuminosityFromBT2020(bt2020_linear); + + return luminosity / LuminosityFromBT2020(1.f); +} + +float LuminosityFromAP1(float3 ap1_linear) { + float3 xyz = mul(renodx::color::AP1_TO_XYZ_MAT, ap1_linear); + float3 lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, xyz); + return 1.55f * lms.x + lms.y; +} + +float LuminosityFromAP1LuminanceNormalized(float3 ap1_linear) { + return LuminosityFromAP1(ap1_linear) / LuminosityFromAP1(1.f); +} + +#endif // SRC_GAMES_CRIMSONDESERT_MACLEOD_BOYNTON_HLSLI_ \ No newline at end of file diff --git a/src/games/avatarfop-swoutlaws/psycho_test17_custom.hlsli b/src/games/avatarfop-swoutlaws/psycho_test17_custom.hlsli new file mode 100644 index 000000000..8c2418926 --- /dev/null +++ b/src/games/avatarfop-swoutlaws/psycho_test17_custom.hlsli @@ -0,0 +1,1129 @@ +#include "./macleod_boynton.hlsli" +#include "./shared.h" + +#ifndef RENODX_SHADERS_TONEMAP_PSYCHO_TEST17_HLSLI_ +#define RENODX_SHADERS_TONEMAP_PSYCHO_TEST17_HLSLI_ + +namespace renodx_custom { +namespace tonemap { +namespace psycho { + +float psycho17_RayExitTCIE1702(float2 origin, float2 direction) { + return renodx::color::gamut::RayExitTCIE1702(origin, direction); +} + +float psycho17_HueRelativePuritySignalFromTClip(float t_clip) { + return saturate(renodx::math::DivideSafe(1.f, t_clip, 0.f)); +} + +float psycho17_AdaptiveHueSensitivityFromTClip(float t_clip) { + static const float kMeanD65RayDistance = 0.20139844f; + static const float kMaxD65RayDistance = 1.02634534f; + static const float kMinSensitivity = 0.35f; + + float long_ray_weight = saturate(renodx::math::DivideSafe( + t_clip - kMeanD65RayDistance, + kMaxD65RayDistance - kMeanD65RayDistance, + 0.f)); + return lerp(1.f, kMinSensitivity, long_ray_weight); +} + +float psycho17_HueRelativePuritySignalFromMB(float2 mb_xy, float2 mb_anchor) { + float2 direction = mb_xy - mb_anchor; + if (dot(direction, direction) <= renodx::color::gamut::MB_NEAR_WHITE_EPSILON) { + return 0.f; + } + + return psycho17_HueRelativePuritySignalFromTClip( + psycho17_RayExitTCIE1702(mb_anchor, direction)); +} + +float psycho17_HueRelativePuritySignalFromMB(float3 mb, float2 mb_anchor) { + if (!(mb.z > renodx::color::gamut::EPSILON)) { + return 0.f; + } + + return psycho17_HueRelativePuritySignalFromMB(mb.xy, mb_anchor); +} + +float psycho17_HueRelativePuritySignal(float3 lms_input, float2 mb_anchor) { + float3 lms_weighted = renodx::color::macleod_boynton::WeighLMS(max(lms_input, 0.f)); + float3 mb = renodx::color::macleod_boynton::from::WeightedLMS(lms_weighted); + if (!(mb.z > renodx::color::gamut::EPSILON)) { + return 0.f; + } + + return psycho17_HueRelativePuritySignalFromMB(mb, mb_anchor); +} + +float psycho17_D65HueSensitivity(float2 mb_xy) { + float2 mb_white = renodx::color::macleod_boynton::from::D65XY(); + float2 direction = mb_xy - mb_white; + if (dot(direction, direction) <= renodx::color::gamut::MB_NEAR_WHITE_EPSILON) { + return 1.f; + } + + return psycho17_AdaptiveHueSensitivityFromTClip( + psycho17_RayExitTCIE1702(mb_white, direction)); +} + +float3 psycho17_ToAdaptiveRelativeLMS(float3 lms_input, float3 current_adaptive_state_lms) { + return renodx::math::DivideSafe(lms_input, current_adaptive_state_lms, 0.f.xxx); +} + +float3 psycho17_FromAdaptiveRelativeLMS(float3 lms_relative, float3 current_adaptive_state_lms) { + return lms_relative * max(current_adaptive_state_lms, 1e-6f.xxx); +} + +float3 psycho17_ToAdaptiveRelativeWeightedLMS(float3 lms_input, float3 current_adaptive_state_lms) { + return renodx::math::DivideSafe( + renodx::color::macleod_boynton::WeighLMS(lms_input), + current_adaptive_state_lms, + 0.f.xxx); +} + +float3 psycho17_FromAdaptiveRelativeWeightedLMS( + float3 lms_weighted_relative, + float3 current_adaptive_state_lms) { + return lms_weighted_relative * max(current_adaptive_state_lms, 1e-6f.xxx); +} + +float3 psycho17_GamutCompressLMSBoundAdaptive( + float3 lms_input, + float3 current_adaptive_state_lms, + float3x3 bound_rgb_to_lms_weighted_mat, + float strength) { + float3 lms_weighted_relative = + psycho17_ToAdaptiveRelativeWeightedLMS(lms_input, current_adaptive_state_lms); + float3 lms_weighted_relative_out = + renodx::color::gamut::GamutCompressWeightedLMSCoreRGBBoundFromAdaptiveWeightedInput( + lms_weighted_relative, + current_adaptive_state_lms, + bound_rgb_to_lms_weighted_mat, + strength); + return renodx::color::macleod_boynton::UnweighLMS( + psycho17_FromAdaptiveRelativeWeightedLMS( + lms_weighted_relative_out, + current_adaptive_state_lms)); +} + +float3 psycho17_GamutCompressAdaptiveRelativeWeightedLMSBound( + float3 lms_weighted_relative_input, + float3 current_adaptive_state_lms, + float3x3 bound_rgb_to_lms_weighted_mat, + float strength) { + return renodx::color::gamut::GamutCompressWeightedLMSCoreRGBBoundFromAdaptiveWeightedInput( + lms_weighted_relative_input, + current_adaptive_state_lms, + bound_rgb_to_lms_weighted_mat, + strength); +} + +float psycho17_AdaptiveHueSensitivity(float2 mb_xy, float2 mb_anchor) { + float2 direction = mb_xy - mb_anchor; + if (dot(direction, direction) <= renodx::color::gamut::MB_NEAR_WHITE_EPSILON) { + return 1.f; + } + + return psycho17_AdaptiveHueSensitivityFromTClip( + psycho17_RayExitTCIE1702(mb_anchor, direction)); +} + +float3 psycho17_ComputeReinhardScale(float3 peak = 1.f, float minimum = 0.f, float3 gray_in = 0.18f, float3 gray_out = 0.18f) { + // s = (p * y - p * m) / (x * p - x * y) + + float3 num = peak * (gray_out - minimum); // p * (y - m) + float3 den = gray_in * (peak - gray_out); // x * (p - y) + + return num / den; +} + +float3 psycho17_ReinhardPiecewise(float3 x, float3 x_max = 1.f, float3 shoulder = 0.18f) { + const float x_min = 0.f; + float3 exposure = psycho17_ComputeReinhardScale(x_max, x_min, shoulder, shoulder); + float3 tonemapped = mad(x, exposure, x_min) / mad(x, exposure / x_max, 1.f - x_min); + + return lerp(x, tonemapped, step(shoulder, x)); +} + +float3 psycho17_ScalePurityMBAdaptive( + float3 lms_input, + float purity_scale, + float3 lms_adaptive_state, + float eps = 1e-7f) { + if (abs(purity_scale - 1.f) <= eps) return lms_input; + + float3 lms_relative = psycho17_ToAdaptiveRelativeLMS(lms_input, lms_adaptive_state); + float3 mb = renodx::color::macleod_boynton::from::LMS(lms_relative); + float2 mb_white = renodx::color::macleod_boynton::from::LMS(1.f.xxx).xy; + float2 mb_scaled = mb_white + (mb.xy - mb_white) * purity_scale; + + return psycho17_FromAdaptiveRelativeLMS( + renodx::color::lms::from::MacLeodBoynton(float3(mb_scaled, mb.z)), + lms_adaptive_state); +} + +float3 psycho17_ApplyPurityFromLMS( + float3 lms_source, + float3 lms_target, + float amount = 1.f, + float clamp_purity_loss = 0.f, + float eps = 1e-7f) { + float3 mb_source = renodx::color::macleod_boynton::from::LMS(lms_source); + float3 mb_target = renodx::color::macleod_boynton::from::LMS(lms_target); + float2 mb_white = renodx::color::macleod_boynton::from::D65XY(); + + float2 source_offset = mb_source.xy - mb_white; + float2 target_offset = mb_target.xy - mb_white; + float src_radius = length(source_offset); + float tgt_radius = length(target_offset); + if (tgt_radius <= eps) return lms_target; + + float transfer_scale = src_radius / max(tgt_radius, eps); + float no_purity_loss_scale = max(transfer_scale, 1.f); + transfer_scale = lerp(transfer_scale, no_purity_loss_scale, clamp_purity_loss); + float scale = lerp(1.f, transfer_scale, amount); + float2 mb_scaled = mb_white + target_offset * scale; + return renodx::color::lms::from::MacLeodBoynton(float3(mb_scaled, mb_target.z)); +} + +float3 psycho17_ApplyPurityFromBT2020( + float3 bt2020_source, + float3 bt2020_target, + float amount = 1.f, + float clamp_purity_loss = 0.f, + float eps = 1e-7f, + bool compress_gamut = true) { + if (amount <= 0.f) return bt2020_source; + + float3 lms_target = renodx::color::lms::from::BT2020(bt2020_target); + float3 lms_source = renodx::color::lms::from::BT2020(bt2020_source); + float3 lms_out = psycho17_ApplyPurityFromLMS( + lms_source, + lms_target, + amount, + clamp_purity_loss, + eps); + + lms_out = psycho17_GamutCompressLMSBoundAdaptive( + lms_out, + 1.f.xxx, + renodx::color::macleod_boynton::BT2020_TO_LMS_WEIGHTED_MAT, + 1.f); + return renodx::color::bt2020::from::LMS(lms_out); +} + +float3 psycho17_RestoreHueAdaptive( + float3 lms_source, + float3 lms_target, + float3 lms_adaptive_state, + float amount, + bool weight_by_purity_loss = true, + float eps = 1e-7f) { + if (amount <= 0.f) return lms_target; + + float3 lms_source_relative_weighted = psycho17_ToAdaptiveRelativeWeightedLMS( + lms_source, + lms_adaptive_state); + float3 lms_target_relative_weighted = psycho17_ToAdaptiveRelativeWeightedLMS( + lms_target, + lms_adaptive_state); + + float3 mb_source = renodx::color::macleod_boynton::from::WeightedLMS(lms_source_relative_weighted); + float3 mb_target = renodx::color::macleod_boynton::from::WeightedLMS(lms_target_relative_weighted); + float3 mb_adapted_bg = renodx::color::macleod_boynton::from::LMS(1.f.xxx); + + float2 source_offset = mb_source.xy - mb_adapted_bg.xy; + float2 target_offset = mb_target.xy - mb_adapted_bg.xy; + float src2 = dot(source_offset, source_offset); + float tgt2 = dot(target_offset, target_offset); + if (src2 <= eps || tgt2 <= eps) return lms_target; + + float target_t_clip = psycho17_RayExitTCIE1702(mb_adapted_bg.xy, target_offset); + float hue_sensitivity = psycho17_AdaptiveHueSensitivityFromTClip(target_t_clip); + float purity_loss_weight = 1.f; + if (weight_by_purity_loss) { + float source_t_clip = psycho17_RayExitTCIE1702(mb_adapted_bg.xy, source_offset); + float source_purity_signal = psycho17_HueRelativePuritySignalFromTClip(source_t_clip); + float target_purity_signal = psycho17_HueRelativePuritySignalFromTClip(target_t_clip); + purity_loss_weight = source_purity_signal > eps ? saturate(target_purity_signal / source_purity_signal) : 1.f; + } + + float restore_weight = amount * hue_sensitivity * purity_loss_weight; + if (restore_weight <= 0.f) return lms_target; + + float inv_target_radius = rsqrt(tgt2); + float target_radius = tgt2 * inv_target_radius; + float inv_source_radius = rsqrt(src2); + float2 source_dir = source_offset * inv_source_radius; + float2 target_dir = target_offset * inv_target_radius; + float2 blended_dir = lerp(target_dir, source_dir, restore_weight); + float blended_len2 = dot(blended_dir, blended_dir); + if (blended_len2 > eps) { + blended_dir *= rsqrt(blended_len2); + } else { + blended_dir = target_dir; + } + + float2 mb_restored_xy = mb_adapted_bg.xy + blended_dir * target_radius; + float3 mb_restored = float3(mb_restored_xy, mb_target.z); + float3 lms_restored_relative_weighted = renodx::color::macleod_boynton::WeightedLMSFromMacleodBoynton(mb_restored); + + return renodx::color::macleod_boynton::UnweighLMS( + psycho17_FromAdaptiveRelativeWeightedLMS( + lms_restored_relative_weighted, + lms_adaptive_state)); +} +// psychov-14 +// +// Objective: +// psychov-14 first targets the observer-side bend of the scene: +// - what state the eye adapts to, +// - how the scene is converted to contrast around that adapted state, +// - how the response is shaped around that adapted state, +// - which nonlinear curve applies at each stage. +// The human observer is not a linear gain system, so the first job of this +// test is to model how a cone/adaptation/opponent/normalization cascade bends +// scene light before any device mapping is considered. +// +// psychov-14 therefore treats the problem as two coupled but distinct systems: +// - observer flow: approximate the ordered flow of the human cone visual +// pathway with a literature-backed cascade, so each stage in the code +// corresponds to a recognizable stage in human vision rather than an +// arbitrary tone curve, +// - device-hull mapping: tonemap the observer-domain result into the display's +// luminance / gamut hull as plausibly as possible. +// Tonemapping itself remains a device-hull problem, not an eye model, but the +// observer model decides which scene differences remain perceptually important +// enough to preserve when the device hull forces compression. +// +// Intended human-flow model and supporting references: +// 1) Receptor basis: +// Stockman-Sharpe LMS with CIE 170-2 physiological luminance Yf / weighted +// LMS bookkeeping, not CIE 1931 Y. +// Reference split: +// - Brainard, "Colorimetry" (chapter 10): the cone stage / color match +// foundation. Chapter 11 explicitly points back to this chapter when it +// says "The first stage of color vision is now well understood (see +// Chap. 10)." For psychov, this is the source for step 1: +// scene RGB/XYZ -> absolute cone excitations L, M, S. +// - Stockman & Brainard (chapter 11): builds on that receptor basis for +// first-site and second-site adaptation. +// Sources: +// https://color2.psych.upenn.edu/brainard/papers/Brainard_Stockman_Colorimetry.pdf +// https://color2.psych.upenn.edu/brainard/papers/Stockman_Brainard_ColorVision.pdf +// CVRL background notes that cone signals are formed only after +// prereceptoral filtering by the ocular media and macular pigment, both of +// which absorb mainly at short wavelengths and vary substantially across +// observers. The current repo plumbing should therefore be understood as an +// average-observer receptor basis unless those filters are modeled +// explicitly. +// Reference: CVRL background hub; "Macular and lens pigments" +// (http://www.cvrl.org/background.htm, +// http://www.cvrl.org/database/text/intros/intromaclens.htm). +// MacLeod-Boynton is important here: it is not itself the cortical flow, +// but a weighted cone-chromaticity representation in an equal-luminance +// plane with a separately carried achromatic scale term. In repo notation: +// l = Lw / (Lw + Mw) +// s = Sw / (Lw + Mw) +// y = Lw + Mw +// The weights here are fixed observer-transform coefficients used to form +// weighted LMS, Yf-like achromatic response, and MB coordinates from LMS. +// They are not adaptation, gain, or bleaching terms. CVRL describes the +// CIE physiological functions as linear transformations of the Stockman & +// Sharpe cone fundamentals, and Mantiuk et al. describe a practical LMS +// scaling "so that the sum of L and M cone responses corresponds to +// luminance". That is the math role of the weights in this stage. +// Reference: MacLeod & Boynton (1979, doi:10.1364/JOSA.69.001183); modern +// CIE 170-2 implementations replace ad hoc weights with standardized +// physiological cone-fundamental / luminance weights. +// Citation split for the weights used in this file: +// - Explicit CIE 170-2 / physiological-weight usage: +// CIE / CVRL physiological functions; Psychtoolbox LMSToMacBoyn; this +// repo's stockman_macleod_boynton.hlsl wiring. +// - Classic or modified MacLeod-Boynton without an explicit CIE 170-2 +// coefficient claim: +// MacLeod & Boynton (1979); Webster & Leonard (2008). +// - LMS scaled so the achromatic term is L+M, but without an explicit +// CIE 170-2 MacLeod-Boynton coefficient claim: +// Mantiuk et al. (2020). +// So classic MB, modified MB, and plain L+M-scaled LMS should not be cited +// as if they automatically justify the exact CIE 170-2 coefficients used +// here. +// Sources: +// http://www.cvrl.org/ciexyzpr.htm +// https://psychtoolbox.org/docs/LMSToMacBoyn +// https://pmc.ncbi.nlm.nih.gov/articles/PMC2657039/ +// https://www.cl.cam.ac.uk/~rkm38/pdfs/mantiuk2020practical_csf.pdf +// 2) Early cone adaptation: +// Maintain an adapting background state (L0, M0, S0, Yf0), then express the +// stimulus relative to that background before any postreceptoral transform. +// Chapter split: +// - chapter 10 gives the absolute cone excitations, +// - chapter 11 then defines how those cone excitations depend on the +// adapting background and are converted to a contrast representation. +// Source-backed first-site math is cone-specific contrast / gain control, +// not a rule that every adapted background is mapped to one fixed output +// level. Stockman & Brainard write the first-site cone contrast for the +// L-cone as: +// C_L = ΔL / (L_b + L_0) +// with analogous forms for M and S. Equivalently, a background-dependent +// gain g_L = 1 / (L_b + L_0) acts on the increment: +// g_L * (L - L_b) = ΔL / (L_b + L_0) +// Thus the observer is approximately normalizing cone signals by the +// adapted background, not forcing all backgrounds to one arbitrary response +// value. First-site adaptation is also not complete or instantaneous, and +// later second-site adaptation further reshapes postreceptoral signals. +// References: Stockman & Brainard (2010); Stockman et al. (JOV 2006, +// doi:10.1167/6.11.5). +// Webster & Leonard (2008) add an important structural point, but their +// terms need to stay separate. Their "response norm" is the adapting level +// that does not bias white judgments, while their "perceptual norm" is the +// stimulus that appears white. Those psychophysical norms tracked each +// other closely in their experiments, but they are not the same term as the +// background cone excitations L_b / M_b / S_b in Stockman & Brainard or +// the background responses L0 / M0 / S0 in Mantiuk et al. For psychov, the +// directly modeled early state is therefore best named the adapted +// background reference (L0, M0, S0, optional Yf0), while Webster's +// response-norm / perceptual-norm language remains useful as higher-level +// interpretation of why that adapted reference acts as the current neutral +// coding state. Webster & Leonard also argue that steady uniform-field +// chromatic adaptation appeared to arise largely at early stages affected +// by adaptation. +// Source: +// https://pmc.ncbi.nlm.nih.gov/articles/PMC2657039/ +// CVRL further notes that luminosity functions are strongly dependent on +// chromatic adaptation and observing conditions, whereas cone spectral +// sensitivities remain fixed until photopigment bleaching becomes +// significant. That is the reason to keep Yf / luminosity bookkeeping tied +// to the adapted observer state rather than treating a single photometric Y +// curve as condition-invariant. +// Reference: CVRL "Luminosity functions" +// (http://www.cvrl.org/database/text/intros/introvl.htm). +// 2a) Dim cone-noise regime: +// Before true rod-dominated vision, cone-mediated detection can already be +// limited by quantal / transduction noise. In this dim-but-still-cone +// regime, threshold cone contrast follows approximately De Vries-Rose +// behavior: in log-log space, threshold contrast decreases with retinal +// illuminance with slope near -0.5. At higher light levels the system moves +// toward Weber-like behavior, where threshold contrast is roughly constant +// relative to the adapted background. This matters for psychov because +// weak scene differences can disappear into a cone-noise-limited threshold +// floor before rod vision becomes dominant. +// Reference direction: +// - Stockman & Brainard (2010): cone-contrast space is most useful when +// first-site adaptation is in the Weber regime, and less useful when +// adaptation falls short of Weber's law at lower levels. +// - Angueyra & Rieke (2013): primate cone photoreceptors exhibit measurable +// phototransduction noise, giving a photoreceptor-level source for the +// dim-light threshold floor. +// Sources: +// https://color2.psych.upenn.edu/brainard/papers/Stockman_Brainard_ColorVision.pdf +// https://pmc.ncbi.nlm.nih.gov/articles/PMC3815624/ +// 2b) High-light bleaching: +// At sufficiently high retinal illuminance, reduce per-cone pigment +// availability with a Rushton-Henry-style law in trolands: +// p(I) = 1 / (1 + I / I0) +// This is the complementary "available pigment" form of the more commonly +// cited fraction-bleached law: +// p_bleached(I) = I / (I + I0) +// with I0 ~ 10^4.3 Td for cones. +// Then apply that availability to cone excursions around an adapted white +// anchor. In the current repo bleaching helper this is implemented as +// per-cone attenuation of LMS deltas around a white-at-achromatic-level +// anchor, so availability -> 0 drives the response toward equal white at the +// same carried achromatic level. That is the desired "intensely bright tends +// to bleach to white" behavior for this test. +// Source and attribution: +// - Stockman et al. (JOV 2006, doi:10.1167/6.11.5): high-light sensitivity +// regulation is maintained mainly by photopigment bleaching. +// - Stockman et al. (JOV 2018, 18(6):12): appendix states the steady-state +// bleaching law p = I / (I + I0), I0 = 10^4.3 Td, citing Rushton & Henry +// (1968). +// - CVRL "Bleaching": bleaching reduces effective pigment concentration and +// narrows spectral sensitivity without changing lambda_max; in cones this +// matters enough to affect chromatic adaptation and color matching, so a +// pure scalar availability model is only a first-order approximation. +// (http://www.cvrl.org/database/text/intros/introbleaches.htm) +// - The final white-relative application used here is the repo's rendering +// interpretation of that availability law for color signals; see +// color/bleaching.hlsl for the exact helper. +// Placement in the overall flow: +// - bleaching belongs inside the observer model, +// - after the adapting background state is defined, +// - before postreceptoral opponent encoding and pooled cortical gain, +// - and therefore before any device-hull tonemapping / gamut compression. +// 3) Background-normalized opponent drive: +// Convert cone-domain responses into ACC / DKL-style opponent coordinates +// using a background-referenced, weighted-LMS achromatic axis. +// Reference direction: derive postreceptoral opponent coordinates from the +// adapted cone-domain state and keep this stage clearly separated from the +// receptor / adaptation math above. +// Important distinction: MacLeod-Boynton describes chromaticity on the +// equal-luminance plane, while ACC / DKL are opponent combinations of cone +// increments around a background. MB is therefore the right place to carry +// hue / gamut geometry and achromatic Yf bookkeeping; ACC / DKL is the +// better place to describe postreceptoral opponent response and gain. +// 4) Saturating contrast response: +// Use a Michaelis-Menten / Naka-Rushton-like nonlinearity for receptor or +// early cortical contrast response. A supersaturating variant may be needed +// later for some cortical fits. +// Reference: Peirce (JOV 2007, doi:10.1167/7.6.13). +// 5) ON/OFF separation: +// Split increments and decrements with half-wave rectification before the +// pooled gain stage. +// Reference: Schiller (1992). +// 6) Pooled cortical gain: +// Apply divisive normalization, potentially with energy-like pooling across +// achromatic and chromatic channels. +// Reference: Heeger (1992); Carandini & Heeger (2012); Bun & Horwitz +// (2023); Li et al. (2022). +// 7) Device-hull tonemapping / gamut mapping: +// Map the observer-domain result into the display hull in a space that keeps +// enough achromatic and chromatic contrast / JND energy to preserve the +// scene plausibly on the target device. White is one valid attractor when +// bleaching or the achromatic optimum dominates, but it is not the only +// valid out-of-hull destination. +// Inference for RGB display hulls: +// - many device hulls can produce more total achromatic output by combining +// primaries than they can produce at the same brightness with a high-purity +// chromatic excursion, +// - therefore an out-of-hull observer response may need to trade chromatic +// shape / purity toward the achromatic axis if that is what the device +// hull allows, +// - the preferred mapping is not blind clipping to white, but the in-hull +// point that preserves the most plausible observer-domain contrast energy. +// Engineering direction inferred from the sources above: +// - use MB / weighted-LMS to carry achromatic Yf and hue geometry, +// - use ACC / opponent space to judge postreceptoral contrast structure, +// - construct or project to a display hull in that combined space rather +// than clipping in RGB. +// Coupling constraint: +// - hue preservation and device-hull compression are not independent steps, +// - a hue change applied after hull compression can push the result back out +// of the device hull, +// - therefore hue-preserving motion should either be solved inside the hull +// projection itself or followed by another explicit in-hull reprojection. +// Reference direction: MacLeod-Boynton / CIE 170-2 geometry; +// repo weighted-LMS / MB geometry plus the device-hull notes above. +// 7a) Optional hue model inside the device-hull solve: +// If gamut compression or display desaturation bends hue in a way that +// looks wrong, the hull solve can preserve hue by an "equivalent Gaussian +// peak" proxy rather than by preserving a raw opponent angle. The idea is +// that at short and medium wavelengths, perceived hue can behave more like a +// constant spectral peak of an equivalent Gaussian than a constant cone +// ratio when purity changes. +// Practical form: +// - offline, map weighted LMS / MB chromaticities to an equivalent Gaussian +// peak parameter mu_eq using a spectral forward model, +// - online, preserve mu_eq during gamut compression / display mapping while +// carrying Yf separately, +// - do not apply an unconstrained post-hoc hue shift after final hull +// compression unless the result is reprojected back into the device hull. +// This is not a separate chronological eye stage after stage 7. It is an +// optional hue objective used inside the device-hull mapping stage. +// Reference: Mizokami et al. (JOV 2006, doi:10.1167/6.9.12); +// O'Neil et al. (JOSAA 2012, doi:10.1364/JOSAA.29.00A165). +// +// Mermaid source map of planned psychov inputs, derived states, and outputs: +// ```mermaid +// flowchart TB +// classDef raw fill:#223041,stroke:#7aa2d2,color:#e8f0ff +// classDef func fill:#3c2a4d,stroke:#b48ef7,color:#f5ecff +// classDef state fill:#294436,stroke:#77c79a,color:#effff5 +// classDef out fill:#5a3a1f,stroke:#f2bc6b,color:#fff6e8 +// +// subgraph inputs["Raw inputs / assumptions"] +// direction TB +// rgb["Scene-linear R / G / B"]:::raw +// src_color["Source colorimetry\nprimaries + white + RGB->XYZ/LMS"]:::raw +// abs_scale["Absolute scene scale\nscene-linear -> nits"]:::raw +// local_bg["Adaptation drivers\nrolling average + local background"]:::raw +// scene_range["Late image context\nluminance range / percentile span"]:::raw +// retinal["Retinal context\npupil area + trolands"]:::raw +// observer_basis["Observer basis assumptions\nStockman/CVRL LMS + lens/macula"]:::raw +// display["Display/device context\nprimaries + white + peak + black + hull"]:::raw +// end +// +// subgraph pipeline["Observer pipeline"] +// direction TB +// src_to_lms["RGB -> receptor LMS"]:::func +// abs_lms["Absolute cone-energy state\nL, M, S"]:::state +// adapt_fn["Estimate adapted background reference"]:::func +// adapt["Adapted background reference\nL0, M0, S0, optional Yf0"]:::state +// cone_contrast_fn["Form per-cone background-relative signal"]:::func +// cone_contrast["Per-cone contrast state\nDeltaL/(Lb+L0), DeltaM/(Mb+M0), DeltaS/(Sb+S0)"]:::state +// bleach_fn["Apply per-cone bleaching availability"]:::func +// bleach["Bleaching availability state"]:::state +// cone_nl_fn["Apply per-cone Naka-Rushton"]:::func +// cone_nl["Per-cone nonlinear response"]:::state +// noise_fn["Apply dim cone-noise threshold"]:::func +// noise_floor["Visibility-limited cone response"]:::state +// weighted_basis_fn["Optional weighted LMS / Yf / MB transform"]:::func +// weighted_basis["Observer-summary basis state"]:::state +// opponent_fn["Recombine to opponent / achromatic channels"]:::func +// opponent["Opponent / achromatic response"]:::state +// onoff_fn["Split ON / OFF pathways"]:::func +// onoff["ON / OFF responses"]:::state +// late_gain_fn["Apply late polarity / range gain"]:::func +// late_gain["Late polarity / range-gated response"]:::state +// pool_fn["Apply pooling / divisive normalization"]:::func +// pooled["Pooled / normalized response"]:::state +// observer_out["Observer-domain response"]:::state +// end +// +// subgraph device_map["Device-hull mapping"] +// direction TB +// hue_obj_fn["Optional hue objective\nMB / ACC / mu_eq"]:::func +// hue_obj["Hue-preserving objective state"]:::state +// hull_fn["Solve device-hull tone + gamut mapping"]:::func +// hull["Display-hull output"]:::out +// end +// +// rgb --> src_to_lms +// src_color --> src_to_lms +// observer_basis --> src_to_lms +// src_to_lms --> abs_lms +// abs_scale --> abs_lms +// +// abs_lms --> adapt_fn --> adapt +// local_bg --> adapt_fn +// retinal --> adapt_fn +// +// abs_lms --> cone_contrast_fn --> cone_contrast +// adapt --> cone_contrast_fn +// +// abs_lms --> bleach_fn --> bleach +// adapt --> bleach_fn +// retinal --> bleach_fn +// +// cone_contrast --> cone_nl_fn --> cone_nl +// bleach --> cone_nl_fn +// +// cone_nl --> noise_fn --> noise_floor +// retinal --> noise_fn +// +// cone_nl --> weighted_basis_fn --> weighted_basis +// +// noise_floor --> opponent_fn --> opponent +// weighted_basis --> opponent_fn +// adapt --> opponent_fn +// +// opponent --> onoff_fn --> onoff +// onoff --> late_gain_fn --> late_gain +// scene_range --> late_gain_fn +// late_gain --> pool_fn --> pooled --> observer_out +// +// observer_out --> hue_obj_fn --> hue_obj +// observer_out --> hull_fn +// hue_obj --> hull_fn +// display --> hull_fn +// hull_fn --> hull +// ``` +// +// Current implementation status: +// - This file currently implements the stage-3 to stage-6 scaffold plus a +// first-pass receptor front end: +// absolute Stockman LMS -> explicit adapted background reference input -> +// per-cone bleaching availability -> local receptor Naka-Rushton -> +// cone-contrast coding -> weighted-LMS ACC placeholder. +// - The full planned early-cone model is still incomplete: +// rolling scene / local surround adaptation plumbing and dim-light noise +// thresholding are not wired into test14 yet. +// - The device-hull tonemapping stage is also not wired into test14 yet. +// - The intended receptor basis should be read as an average-observer, mainly +// foveal Stockman / CVRL basis with prereceptoral lens and macular filtering +// already folded into the standard functions, not a personalized observer +// model with explicit lens / macular / eccentricity variation. +// - The adapted background is now an explicit input with a default +// diffuse-gray proxy, but the caller still needs to supply a real rolling +// scene / local surround estimate before this can count as a complete +// adaptation model. +// - The scalar defaults below are unit-normalized test settings and are not +// yet fitted to a specific physiology dataset. +// - The optional Abney / equivalent-Gaussian hue stage is not implemented yet; +// if used later, it should be bounded because the Gaussian account works best +// at short and medium wavelengths and breaks down toward yellow / red. +// +// Secondary seminar notes (useful framing, not primary citation): +// - "Bright lights ... bleach the cones" and make them less sensitive, with +// slow recovery. This supports the placement of bleaching in the observer +// model before device mapping. +// - "Gamut ... is the technical container." This supports treating tonemapping +// as a device-hull problem distinct from the eye model. +// - Diffuse white and peak luminance were discussed separately, which supports +// keeping display white / diffuse white as explicit anchors in the hull solve. +// Source: "Mythbusting: Colour, Camera, Cinema" (Colorist Society, +// Camerimage 2024 panel with Andrew Stockman / Charles Poynton / Dirk Meier), +// YouTube transcript dated January 13, 2025. +// Ordered summary: +// scene RGB +// -> absolute Stockman LMS (chapter 10 receptor basis) +// -> early cone adaptation (chapter 11 first-site background L0/M0/S0/Yf0) +// -> high-light bleaching +// -> opponent drive +// -> saturating response / ON-OFF / pooled gain +// -> observer-domain result +// -> device-hull mapping +float3 psychotm_test17( + float3 bt709_linear_input, + float peak_value = 1000.f / 203.f, + float exposure = 1.f, + float highlights = 1.f, + float shadows = 1.f, + float contrast = 1.f, + float purity_scale = 1.f, + float bleaching_intensity = 1.f, + float clip_point = 100.f, + float hue_restore = 1.f, + float adaptation_contrast = 1.f, + int white_curve_mode = 0, + float cone_response_exponent = 1.f, + float3 current_adaptive_state_bt709 = 0.18f, + float3 current_background_state_bt709 = 0.18f, + float gamut_compression = 1.f, + int gamut_compression_mode = 1, + float adaptive_normalization = 1.f) { + float3 bt709_scene = bt709_linear_input * exposure; + + float3 lms_in = renodx::color::lms::from::BT709(bt709_scene); + float3 lms_peak = renodx::color::lms::from::BT709(float(peak_value).xxx); + float3 current_adaptive_state_lms = renodx::color::lms::from::BT709(current_adaptive_state_bt709); + float3 desired_background_state_lms = renodx::color::lms::from::BT709(current_background_state_bt709); + float3 lms_working = lms_in; + if (true) { + // noop + } else if (gamut_compression == 0) { + lms_working = psycho17_GamutCompressLMSBoundAdaptive( + lms_in, + current_adaptive_state_lms, + renodx::color::macleod_boynton::LMS_TO_LMS_WEIGHTED_MAT, + 1.f); + } else if (gamut_compression_mode == 0) { + lms_working = psycho17_GamutCompressLMSBoundAdaptive( + lms_in, + current_adaptive_state_lms, + renodx::color::macleod_boynton::BT709_TO_LMS_WEIGHTED_MAT, + 1.f); + } else { + lms_working = psycho17_GamutCompressLMSBoundAdaptive( + lms_in, + current_adaptive_state_lms, + renodx::color::macleod_boynton::BT2020_TO_LMS_WEIGHTED_MAT, + 1.f); + } + + float yf_input = renodx::color::yf::from::LMS(lms_working); + float yf_midgray = renodx::color::yf::from::BT709(0.18f); + float yf_target = yf_input; + + // Stage 1: apply UI highlight/shadow/contrast controls in luminosity space. + if (highlights != 1.f) { + yf_target = renodx::color::grade::Highlights(yf_target, highlights, yf_midgray); + } + if (shadows != 1.f) { + yf_target = renodx::color::grade::Shadows(yf_target, shadows, yf_midgray); + } + if (contrast != 1.f) { + yf_target = renodx::color::grade::ContrastSafe(yf_target, contrast, yf_midgray); + } + + float yf_scale = renodx::math::DivideSafe(yf_target, yf_input, 1.f); + + float3 lms_graded = lms_working * yf_scale; + if (purity_scale != 1.f) { + float3 lms_graded_relative = psycho17_ToAdaptiveRelativeLMS( + lms_graded, + current_adaptive_state_lms); + float3 mb = renodx::color::macleod_boynton::from::LMS(lms_graded_relative); + float2 mb_white = renodx::color::macleod_boynton::from::LMS(1.f.xxx).xy; + float2 mb_scaled = lerp(mb_white, mb.xy, purity_scale); + lms_graded = psycho17_FromAdaptiveRelativeLMS( + renodx::color::lms::from::MacLeodBoynton(float3(mb_scaled, mb.z)), + current_adaptive_state_lms); + } + + float3 lms_cones = lms_graded; + + // if (bleaching_intensity != 0.f) { + // float3 availability = 1.f.xxx / (1.f.xxx + (peak_value / current_adaptive_state_lms)); + // availability = lerp(1.f.xxx, availability, bleaching_intensity); + + // float input_energy = lms_cones.x + lms_cones.y + lms_cones.z; + // float white_y = current_adaptive_state_lms.x + current_adaptive_state_lms.y + current_adaptive_state_lms.z; + // float3 white_at_y = current_adaptive_state_lms * (input_energy / white_y); + // float3 delta = (lms_cones - white_at_y) * availability; + // lms_cones = max(0, white_at_y + delta); + // } + + // Naka-Rushton is scale-equivariant if input, peak, and anchors are all + // normalized by the same adaptive LMS state, so keep the absolute-LMS form. + float3 display_scaled = renodx::tonemap::NakaRushton( + lms_cones, + lms_peak, + current_adaptive_state_lms, + desired_background_state_lms, + cone_response_exponent); + float3 display_scaled_relative_weighted = psycho17_ToAdaptiveRelativeWeightedLMS( + display_scaled, + current_adaptive_state_lms); + + if (hue_restore > 0.f) { + float3 lms_cones_relative_weighted = psycho17_ToAdaptiveRelativeWeightedLMS( + lms_cones, + current_adaptive_state_lms); + float3 mb_source = + renodx::color::macleod_boynton::from::WeightedLMS(lms_cones_relative_weighted); + float3 mb_display_target = + renodx::color::macleod_boynton::from::WeightedLMS(display_scaled_relative_weighted); + float3 mb_adapted_bg = renodx::color::macleod_boynton::from::LMS(1.f.xxx); + + float2 source_offset = mb_source.xy - mb_adapted_bg.xy; + float2 display_target_offset = mb_display_target.xy - mb_adapted_bg.xy; + float src2 = dot(source_offset, source_offset); + float display_tgt2 = dot(display_target_offset, display_target_offset); + if (src2 > 1e-7 && display_tgt2 > 1e-7) { + float inv_target_radius = rsqrt(display_tgt2); + float target_radius = display_tgt2 * inv_target_radius; + float source_t_clip = psycho17_RayExitTCIE1702(mb_adapted_bg.xy, source_offset); + float display_t_clip = psycho17_RayExitTCIE1702(mb_adapted_bg.xy, display_target_offset); + // Scale hue restoration by purity loss relative to the adapted neutral anchor. + float source_purity_signal = psycho17_HueRelativePuritySignalFromTClip(source_t_clip); + float display_purity_signal = psycho17_HueRelativePuritySignalFromTClip(display_t_clip); + float purity_signal_loss = saturate(display_purity_signal / source_purity_signal); + float hue_sensitivity = psycho17_AdaptiveHueSensitivityFromTClip(display_t_clip); + float restore_weight = 1.f * hue_sensitivity * hue_restore * purity_signal_loss; + if (restore_weight > 0.f) { + float inv_source_radius = rsqrt(src2); + float2 source_dir = source_offset * inv_source_radius; + float2 display_target_dir = display_target_offset * inv_target_radius; + float2 blended_dir = lerp(display_target_dir, source_dir, restore_weight); + float blended_len2 = dot(blended_dir, blended_dir); + if (blended_len2 > 1e-7) { + blended_dir *= rsqrt(blended_len2); + } else { + blended_dir = display_target_dir; + } + + // Keep display-scaled chroma radius and y_MB; only replace hue direction. + float2 mb_restored_xy = mb_adapted_bg.xy + blended_dir * target_radius; + float3 mb_restored = float3(mb_restored_xy, mb_display_target.z); + display_scaled_relative_weighted = + renodx::color::macleod_boynton::WeightedLMSFromMacleodBoynton(mb_restored); + } + } + } + + if (gamut_compression != 0.f) { + if (gamut_compression_mode == 0) { + display_scaled_relative_weighted = psycho17_GamutCompressAdaptiveRelativeWeightedLMSBound( + display_scaled_relative_weighted, + current_adaptive_state_lms, + renodx::color::macleod_boynton::BT709_TO_LMS_WEIGHTED_MAT, + gamut_compression); + } else if (gamut_compression_mode == 1) { + display_scaled_relative_weighted = psycho17_GamutCompressAdaptiveRelativeWeightedLMSBound( + display_scaled_relative_weighted, + current_adaptive_state_lms, + renodx::color::macleod_boynton::BT2020_TO_LMS_WEIGHTED_MAT, + gamut_compression); + } + } + // Scale back from first-site adaptation; + float3 final_bt709 = renodx::color::bt709::from::LMS( + renodx::color::macleod_boynton::UnweighLMS( + psycho17_FromAdaptiveRelativeWeightedLMS( + display_scaled_relative_weighted, + current_adaptive_state_lms))); + return final_bt709; +} + +float psycho17_Highlights(float x, float highlights, float mid_gray) { + if (highlights == 1.f) return x; + + if (highlights > 1.f) { + return max(x, lerp(x, mid_gray * pow(x / mid_gray, highlights), min(x, 1.f))); + } else { // highlights < 1 + float b = mid_gray * pow(x / mid_gray, 2.f - highlights); + float t = min(x, 1.f); + return min(x, renodx::math::DivideSafe(x * x, lerp(x, b, t), x)); + } +} + +float psycho17_Shadows(float x, float shadows, float mid_gray) { + if (shadows == 1.f) return x; + + const float ratio = max(renodx::math::DivideSafe(x, mid_gray, 0.f), 0.f); + const float base_term = x * mid_gray; + const float base_scale = renodx::math::DivideSafe(base_term, ratio, 0.f); + + if (shadows > 1.f) { + float raised = x * (1.f + renodx::math::DivideSafe(base_term, pow(ratio, shadows), 0.f)); + float reference = x * (1.f + base_scale); + return max(x, x + (raised - reference)); + } else { // shadows < 1 + float lowered = x * (1.f - renodx::math::DivideSafe(base_term, pow(ratio, 2.f - shadows), 0.f)); + float reference = x * (1.f - base_scale); + return clamp(x + (lowered - reference), 0.f, x); + } +} + +float psycho17_ContrastAndFlare( + float x, + float contrast, + float contrast_highlights, + float contrast_shadows, + float flare, + float mid_gray = 0.18f) { + if (contrast == 1.f && flare == 0.f && contrast_highlights == 1.f && contrast_shadows == 1.f) return x; + + const float x_normalized = x / mid_gray; + const float split_contrast = (x < mid_gray) ? contrast_shadows : contrast_highlights; + float flare_ratio = renodx::math::DivideSafe(x_normalized + flare, x_normalized, 1.f); + float exponent = contrast * split_contrast * flare_ratio; + return pow(x_normalized, exponent) * mid_gray; +} + +namespace config17 { + +struct Config { + bool apply_tonemap; + float peak_value; + float exposure; + float gamma; + float highlights; + float shadows; + float contrast; + float flare; + float contrast_highlights; + float contrast_shadows; + float purity_scale; + float purity_highlights; + float dechroma; + float adaptation_contrast; + float bleaching_intensity; + float clip_point; + float mid_gray; + bool pre_gamut_compress; + bool post_gamut_compress; + float hue_emulation; +}; + +Config Create( + bool apply_tonemap = true, + float peak_value = 1000.f / 203.f, + float exposure = 1.f, + float gamma = 1.f, + float highlights = 1.f, + float shadows = 1.f, + float contrast = 1.f, + float flare = 0.f, + float contrast_highlights = 1.f, + float contrast_shadows = 1.f, + float purity_scale = 1.f, + float purity_highlights = 1.f, + float dechroma = 0.f, + float adaptation_contrast = 1.f, + float bleaching_intensity = 0.f, + float clip_point = 100.f, + float mid_gray = 0.18f, + bool pre_gamut_compress = true, + bool post_gamut_compress = true, + float hue_emulation = 0.f) { + const Config psycho17_config = { + apply_tonemap, + peak_value, + exposure, + gamma, + highlights, + shadows, + contrast, + flare, + contrast_highlights, + contrast_shadows, + purity_scale, + purity_highlights, + dechroma, + adaptation_contrast, + bleaching_intensity, + clip_point, + mid_gray, + pre_gamut_compress, + post_gamut_compress, + hue_emulation + }; + return psycho17_config; +} + +} // namespace config17 + +float3 ApplyTest17BT2020(float3 color_bt2020, float3 color_hue_shift_source_bt2020, config17::Config psycho_config) { + const float kEps = 1e-7f; + float clip_point = psycho_config.clip_point; + + float3 midgray_lms = renodx::color::lms::from::BT2020(psycho_config.mid_gray.xxx); + + float3 color_lms_raw = renodx::color::lms::from::BT2020(color_bt2020); + if (psycho_config.pre_gamut_compress) { + color_lms_raw = psycho17_GamutCompressLMSBoundAdaptive( + color_lms_raw, + midgray_lms, + renodx::color::macleod_boynton::BT2020_TO_LMS_WEIGHTED_MAT, + 1.f); + } + + float3 color_lms = color_lms_raw; + float lum_original = renodx::color::yf::from::LMS(color_lms_raw); + + if (psycho_config.bleaching_intensity != 0.f) { + const float kHalfBleachTrolands = 20000.f; + + float adapted_lum = max(lum_original, psycho_config.mid_gray); + float3 lms_adapted_unit = renodx::color::lms::from::BT2020(adapted_lum.xxx); + float3 lms_signal_unit = color_lms; + + float3 stimulus_nits = max(lms_adapted_unit, 0.f) * 100.f; + float3 stimulus_trolands = stimulus_nits * 4.f; + float3 availability_raw = 1.f / (1.f + stimulus_trolands / max(kHalfBleachTrolands, kEps)); + float3 availability = lerp(1.f, availability_raw, psycho_config.bleaching_intensity); + color_lms = lms_signal_unit * max(availability, 0.f); + } + + if (psycho_config.apply_tonemap) { + float3 lms_peak_unit = renodx::color::lms::from::BT2020(psycho_config.peak_value.xxx); + color_lms = psycho17_ReinhardPiecewise(color_lms, lms_peak_unit, midgray_lms); + + // adaptive hue restore not needed + // color_lms = psycho17_RestoreHueAdaptive( + // color_lms_raw, + // color_lms, + // midgray_lms, + // psycho_config.hue_restore, + // kEps); + + color_lms *= renodx::math::DivideSafe( + lum_original, + renodx::color::yf::from::LMS(color_lms), + 1.f); + } + + if (psycho_config.adaptation_contrast != 1.f || psycho_config.hue_emulation != 0.f) { + float3 source_lms = color_lms; + if (psycho_config.adaptation_contrast != 1.f) { + float3 lms_sigma_unit = max(midgray_lms, kEps.xxx); + float exponent = max(psycho_config.adaptation_contrast, kEps); + + float3 ax = abs(color_lms); + float3 ax_n = pow(ax, exponent); + float3 s_n = pow(lms_sigma_unit, exponent); + float3 response_target = ax_n / max(ax_n + s_n, kEps.xxx); + float3 response_baseline = ax / max(ax + lms_sigma_unit, kEps.xxx); + float3 gain = response_target / max(response_baseline, kEps.xxx); + float3 sign_raw = float3( + color_lms.x < 0.f ? -1.f : 1.f, + color_lms.y < 0.f ? -1.f : 1.f, + color_lms.z < 0.f ? -1.f : 1.f); + color_lms = sign_raw * (ax * gain); + } + + if (psycho_config.hue_emulation != 0.f) { + source_lms = lerp(source_lms, renodx::color::lms::from::BT2020(color_hue_shift_source_bt2020), psycho_config.hue_emulation); + } + + color_lms = psycho17_RestoreHueAdaptive( + source_lms, + color_lms, + midgray_lms, + 1.f, + false); + } + + if (psycho_config.exposure != 1.f + || psycho_config.gamma != 1.f + || psycho_config.highlights != 1.f + || psycho_config.shadows != 1.f + || psycho_config.contrast != 1.f + || psycho_config.contrast_highlights != 1.f + || psycho_config.contrast_shadows != 1.f + || psycho_config.flare != 0.f + || psycho_config.purity_scale != 1.f + || psycho_config.dechroma != 0.f + || psycho_config.purity_highlights != 0.f) { + float midgray_lum = renodx::color::yf::from::LMS(midgray_lms); + float lum_target = lum_original; + + lum_target *= psycho_config.exposure; + if (psycho_config.gamma != 1.f) { + lum_target = select(lum_target < 1.f, pow(lum_target, psycho_config.gamma), lum_target); + } + + if (psycho_config.highlights != 1.f) { + lum_target = psycho17_Highlights(lum_target, psycho_config.highlights, midgray_lum); + } + + if (psycho_config.shadows != 1.f) { + lum_target = psycho17_Shadows(lum_target, psycho_config.shadows, midgray_lum); + } + + if (psycho_config.contrast != 1.f + || psycho_config.contrast_highlights != 1.f + || psycho_config.contrast_shadows != 1.f + || psycho_config.flare != 0.f) { + lum_target = psycho17_ContrastAndFlare( + lum_target, + psycho_config.contrast, + psycho_config.contrast_highlights, + psycho_config.contrast_shadows, + psycho_config.flare, + midgray_lum); + } + + float lum_scale = renodx::math::DivideSafe(lum_target, lum_original, 1.f); + clip_point *= lum_scale; + color_lms *= lum_scale; + + float purity_scale = psycho_config.purity_scale; + + if (psycho_config.dechroma != 0.f) { + purity_scale *= lerp(1.f, 0.f, saturate(pow(lum_target / (10000.f / 100.f), (1.f - psycho_config.dechroma)))); + } + + if (psycho_config.purity_highlights != 0.f) { + float percent_max = saturate(lum_target * 100.f / 10000.f); + float blowout_change = pow(1.f - percent_max, 100.f * abs(psycho_config.purity_highlights)); + if (psycho_config.purity_highlights < 0.f) { + blowout_change = 2.f - blowout_change; + } + purity_scale *= blowout_change; + } + + if (purity_scale != 1.f) { + color_lms = psycho17_ScalePurityMBAdaptive(color_lms, purity_scale, midgray_lms, kEps); + } + } + + if (psycho_config.post_gamut_compress) { + color_lms = psycho17_GamutCompressLMSBoundAdaptive( + color_lms, + midgray_lms, + renodx::color::macleod_boynton::BT2020_TO_LMS_WEIGHTED_MAT, + 1.f); + } + + color_bt2020 = renodx::color::bt2020::from::LMS(color_lms); + + if (psycho_config.apply_tonemap) { + color_bt2020 = renodx::tonemap::neutwo::MaxChannel( + max(color_bt2020, 0.f.xxx), + psycho_config.peak_value, + clip_point); + } + + return color_bt2020; +} + +} // namespace psycho +} // namespace tonemap +} // namespace renodx + +#endif // RENODX_SHADERS_TONEMAP_PSYCHO_TEST17_HLSLI_ diff --git a/src/games/avatarfop-swoutlaws/shared.h b/src/games/avatarfop-swoutlaws/shared.h index 7d3912ce0..8bda19ab5 100644 --- a/src/games/avatarfop-swoutlaws/shared.h +++ b/src/games/avatarfop-swoutlaws/shared.h @@ -10,11 +10,17 @@ struct ShaderInjectData { float graphics_white_nits; float sdr_eotf_emulation; float sdr_eotf_emulation_ui; + float tone_map_hue_emulation; float tone_map_white_clip; + float tone_map_exposure; + float tone_map_gamma; float tone_map_highlights; float tone_map_shadows; float tone_map_contrast; + float tone_map_contrast_shadows; + float tone_map_contrast_highlights; + float tone_map_adaptation_contrast; float tone_map_saturation; float tone_map_highlight_saturation; float tone_map_dechroma; @@ -29,17 +35,23 @@ cbuffer cb13 : register(b13, space50) { ShaderInjectData shader_injection : packoffset(c0); } -#define RENODX_TONE_MAP_TYPE shader_injection.tone_map_type -#define RENODX_PEAK_WHITE_NITS shader_injection.peak_white_nits -#define RENODX_DIFFUSE_WHITE_NITS shader_injection.diffuse_white_nits -#define RENODX_GRAPHICS_WHITE_NITS shader_injection.graphics_white_nits -#define RENODX_SDR_EOTF_EMULATION shader_injection.sdr_eotf_emulation -#define RENODX_SDR_EOTF_EMULATION_UI shader_injection.sdr_eotf_emulation_ui -#define RENODX_TONE_MAP_WHITE_CLIP shader_injection.tone_map_white_clip +#define RENODX_TONE_MAP_TYPE shader_injection.tone_map_type +#define RENODX_PEAK_WHITE_NITS shader_injection.peak_white_nits +#define RENODX_DIFFUSE_WHITE_NITS shader_injection.diffuse_white_nits +#define RENODX_GRAPHICS_WHITE_NITS shader_injection.graphics_white_nits +#define RENODX_TONE_MAP_HUE_EMULATION shader_injection.tone_map_hue_emulation +#define RENODX_SDR_EOTF_EMULATION shader_injection.sdr_eotf_emulation +#define RENODX_SDR_EOTF_EMULATION_UI shader_injection.sdr_eotf_emulation_ui +#define RENODX_TONE_MAP_WHITE_CLIP shader_injection.tone_map_white_clip + #define RENODX_TONE_MAP_EXPOSURE shader_injection.tone_map_exposure +#define RENODX_TONE_MAP_GAMMA shader_injection.tone_map_gamma #define RENODX_TONE_MAP_HIGHLIGHTS shader_injection.tone_map_highlights #define RENODX_TONE_MAP_SHADOWS shader_injection.tone_map_shadows #define RENODX_TONE_MAP_CONTRAST shader_injection.tone_map_contrast +#define RENODX_TONE_MAP_CONTRAST_SHADOWS shader_injection.tone_map_contrast_shadows +#define RENODX_TONE_MAP_CONTRAST_HIGHLIGHTS shader_injection.tone_map_contrast_highlights +#define RENODX_TONE_MAP_ADAPTATION_CONTRAST shader_injection.tone_map_adaptation_contrast #define RENODX_TONE_MAP_SATURATION shader_injection.tone_map_saturation #define RENODX_TONE_MAP_HIGHLIGHT_SATURATION shader_injection.tone_map_highlight_saturation #define RENODX_TONE_MAP_FLARE shader_injection.tone_map_flare diff --git a/src/games/avatarfop-swoutlaws/starwarsoutlaws/lutbuilder_hdr_0x9BBB3E97.cs_6_0.hlsl b/src/games/avatarfop-swoutlaws/starwarsoutlaws/lutbuilder_hdr_0x9BBB3E97.cs_6_0.hlsl index 51a8db7e4..e28b89cad 100644 --- a/src/games/avatarfop-swoutlaws/starwarsoutlaws/lutbuilder_hdr_0x9BBB3E97.cs_6_0.hlsl +++ b/src/games/avatarfop-swoutlaws/starwarsoutlaws/lutbuilder_hdr_0x9BBB3E97.cs_6_0.hlsl @@ -312,7 +312,7 @@ void comp_main() { float3 ungraded_bt709 = _1363; if (RENODX_TONE_MAP_TYPE != 0 && RENODX_TONE_MAP_TYPE != 3.f) { float contrast = asfloat(CB1_m[4u].x); - U0[CB2_m11.y][gl_GlobalInvocationID] = float4(GenerateOutputStarWarsOutlaws(ungraded_bt709, contrast), 1.f); + U0[CB2_m11.y][gl_GlobalInvocationID] = float4(GenerateOutputOutlaws(ungraded_bt709, contrast), 1.f); return; } #endif diff --git a/src/games/deathstranding2/addon.cpp b/src/games/deathstranding2/addon.cpp index d486dbc1d..17d75b11b 100644 --- a/src/games/deathstranding2/addon.cpp +++ b/src/games/deathstranding2/addon.cpp @@ -80,15 +80,13 @@ renodx::utils::settings::Settings settings = { .is_enabled = []() { return shader_injection.tone_map_type != 0.f; }, }, new renodx::utils::settings::Setting{ - .key = "ToneMapScaling", - .binding = &shader_injection.tone_map_scaling, - .value_type = renodx::utils::settings::SettingValueType::INTEGER, - .default_value = 1.f, - .label = "Scaling", + .key = "ToneMapHueEmulation", + .binding = &shader_injection.tone_map_hue_emulation, + .value_type = renodx::utils::settings::SettingValueType::BOOLEAN, + .default_value = 0.f, + .label = "Vanilla Hue Emulation", .section = "Tone Mapping", - .tooltip = "Max Channel: Hand-tuned to match the original tonemapper's behavior.\n" - "LMS (PsychoV): Based on emulating human vision.", - .labels = {"Max Channel", "LMS (PsychoV)"}, + .tooltip = "Adjusts hues to match the original tonemapper's", .is_enabled = []() { return shader_injection.tone_map_type != 0.f; }, }, new renodx::utils::settings::Setting{ @@ -190,7 +188,7 @@ renodx::utils::settings::Settings settings = { .section = "Color Grading", .tooltip = "Adds or removes highlight color.", .max = 100.f, - .is_enabled = []() { return shader_injection.tone_map_type != 0.f && shader_injection.tone_map_scaling != 0.f; }, + .is_enabled = []() { return shader_injection.tone_map_type != 0.f; }, .parse = [](float value) { return value * 0.02f; }, }, new renodx::utils::settings::Setting{ @@ -248,7 +246,7 @@ renodx::utils::settings::Settings settings = { renodx::utils::settings::ResetSettings(); renodx::utils::settings::UpdateSettings({ {"GammaCorrection", 1.f}, - {"ToneMapScaling", 0.f}, + {"ToneMapHueEmulation", 1.f}, {"ColorGradeShadows", 50.f}, {"ColorGradeLUTScaling", 0.f}, }); @@ -343,7 +341,7 @@ void OnPresetOff() { {"ToneMapPeakNits", 1000.f}, {"ToneMapGameNits", 203.f}, {"ToneMapUINits", 203.f}, - {"ToneMapScaling", 0.f}, + {"ToneMapHueEmulation", 1.f}, {"GammaCorrection", 1.f}, {"ColorGradeExposure", 1.f}, {"ColorGradeGamma", 1.f}, diff --git a/src/games/deathstranding2/shared.h b/src/games/deathstranding2/shared.h index 1837c114a..1189cb982 100644 --- a/src/games/deathstranding2/shared.h +++ b/src/games/deathstranding2/shared.h @@ -9,7 +9,7 @@ struct ShaderInjectData { float diffuse_white_nits; float graphics_white_nits; float gamma_correction; - float tone_map_scaling; + float tone_map_hue_emulation; float tone_map_exposure; float tone_map_gamma; @@ -31,12 +31,12 @@ cbuffer shader_injection : register(b0, space50) { ShaderInjectData shader_injection : packoffset(c0); } -#define RENODX_TONE_MAP_TYPE shader_injection.tone_map_type -#define RENODX_PEAK_WHITE_NITS shader_injection.peak_white_nits -#define RENODX_DIFFUSE_WHITE_NITS shader_injection.diffuse_white_nits -#define RENODX_GRAPHICS_WHITE_NITS shader_injection.graphics_white_nits -#define RENODX_GAMMA_CORRECTION shader_injection.gamma_correction -#define RENODX_TONE_MAP_SCALING shader_injection.tone_map_scaling +#define RENODX_TONE_MAP_TYPE shader_injection.tone_map_type +#define RENODX_PEAK_WHITE_NITS shader_injection.peak_white_nits +#define RENODX_DIFFUSE_WHITE_NITS shader_injection.diffuse_white_nits +#define RENODX_GRAPHICS_WHITE_NITS shader_injection.graphics_white_nits +#define RENODX_GAMMA_CORRECTION shader_injection.gamma_correction +#define RENODX_TONE_MAP_HUE_EMULATION shader_injection.tone_map_hue_emulation #define RENODX_TONE_MAP_EXPOSURE shader_injection.tone_map_exposure #define RENODX_TONE_MAP_GAMMA shader_injection.tone_map_gamma diff --git a/src/games/deathstranding2/tonemap/macleod_boynton.hlsli b/src/games/deathstranding2/tonemap/macleod_boynton.hlsli new file mode 100644 index 000000000..e671f45c5 --- /dev/null +++ b/src/games/deathstranding2/tonemap/macleod_boynton.hlsli @@ -0,0 +1,1306 @@ +#ifndef SRC_GAMES_CRIMSONDESERT_MACLEOD_BOYNTON_HLSLI_ +#define SRC_GAMES_CRIMSONDESERT_MACLEOD_BOYNTON_HLSLI_ + +#include "../shared.h" + +namespace renodx_custom { +namespace color { +namespace macleod_boynton { + +// MacLeod-Boynton purity model in RGB gamut space. +// +// Core idea: +// 1) Convert RGB -> XYZ -> LMS. +// 2) Represent hue as MB ratios at fixed T = L + M. +// 3) Move along the MB ray from adapted white toward the input hue. +// 4) Solve exactly where that ray intersects the selected RGB gamut boundary. +// +// This gives a saturation/purity control that is geometrically bounded by gamut, +// instead of scaling perceptual coordinates and clipping later. +// +// Reference material: +// - MacLeod & Boynton (1979), MB chromaticity: +// https://pubmed.ncbi.nlm.nih.gov/490231/ +// - Derrington, Krauskopf, Lennie (1984), DKL axes: +// https://pubmed.ncbi.nlm.nih.gov/6512691/ +// - Stockman & Sharpe (2000), cone fundamentals: +// https://pubmed.ncbi.nlm.nih.gov/10814758/ +// - CIE 170-1:2006 (physiological axes / LMS standardization context): +// https://cie.co.at/publications/fundamental-chromaticity-diagram-physiological-axes-part-1 +// - ITU-R BT.709-6 (HDTV primaries / transfer context): +// https://www.itu.int/rec/R-REC-BT.709-6-201506-I +// - ITU-R BT.2020-2 (UHDTV wide-gamut primaries): +// https://www.itu.int/rec/R-REC-BT.2020-2-201510-I/en +// +// Comparison context from discussion: +// - Oklab (Ottosson): https://bottosson.github.io/posts/oklab/ +// - Oklab critique (Levien): https://raphlinus.github.io/color/2021/01/18/oklab-critique.html +static const float3x3 XYZ_TO_LMS_2006 = float3x3( + 0.185082982238733f, 0.584081279463687f, -0.0240722415044404f, + -0.134433056469973f, 0.405752392775348f, 0.0358252602217631f, + 0.000789456671966863f, -0.000912281325916184f, 0.0198490812339463f); + +static const float3x3 LMS_TO_XYZ_2006 = renodx::math::Invert3x3(XYZ_TO_LMS_2006); + +static const float EPSILON = 1e-20f; +static const float INTERVAL_MAX = 1e30f; +static const float MB_NEAR_WHITE_EPSILON = 1e-14f; + +static const int MB_PURITY_MODE_DISTANCE = 0; +static const int MB_PURITY_MODE_NORMALIZED = 1; +static const int MB_PURITY_MODE_SCALE_NEUTWO = 2; +static const int MB_PURITY_ADJUST_NONE = 0; +static const int MB_PURITY_ADJUST_CLIP_MAX = 1; +static const float ONE_MINUS_EPSILON = 1.f - 1e-6f; + +// Neutwo (x / sqrt(x^2 + 1)) and its inverse. +// Used to shape purity scaling with a smooth shoulder near gamut edge. +float Neutwo(float x) { + float denominator_squared = mad(x, x, 1.f); + return x * rsqrt(denominator_squared); +} + +float InverseNeutwo(float x) { + float clamped = min(max(x, 0.f), ONE_MINUS_EPSILON); + float denominator_squared = mad(-clamped, clamped, 1.f); + return clamped * rsqrt(denominator_squared); +} + +// MB coordinate from LMS. +// r = L / (L + M), b = S / (L + M) +// T = (L + M) is intensity anchor and is preserved while changing purity. +float2 MB_From_LMS(float3 lms) { + float t = lms.x + lms.y; + + if (t <= 0.f) { + return float2(0.f, 0.f); + } + + return float2( + renodx::math::DivideSafe(lms.x, t, 0.f), + renodx::math::DivideSafe(lms.z, t, 0.f)); +} + +// Reconstruct LMS from MB coordinates while holding T = L + M fixed. +float3 LMS_From_MB_T(float2 mb, float t) { + float r = mb.x; + float b = mb.y; + return float3(r * t, (1.f - r) * t, b * t); +} + +// Default adaptation white in MB space. +float2 MB_White_D65() { + float3 d65_xyz = renodx::color::xyz::from::xyY(float3(renodx::color::WHITE_POINT_D65, 1.f)); + float3 d65_lms = mul(XYZ_TO_LMS_2006, d65_xyz); + return MB_From_LMS(d65_lms); +} + +// Half-space constraint for one channel in affine form: +// rgb(t) = a * t + b, and we require rgb(t) >= 0. +// Returns interval [lo, hi] where that channel is valid. +void IntervalLower0(float a, float b, out float lo, out float hi) { + if (abs(a) < EPSILON) { + if (b >= 0.f) { + lo = -INTERVAL_MAX; + hi = INTERVAL_MAX; + } else { + lo = 1.f; + hi = 0.f; + } + return; + } + + float t0 = renodx::math::DivideSafe(-b, a, 0.f); + + if (a > 0.f) { + lo = t0; + hi = INTERVAL_MAX; + } else { + lo = -INTERVAL_MAX; + hi = t0; + } +} + +struct MBPurityDebug { + float3 rgbOut; + float3 rgbT0; + float3 rgbEdgeGamut; + + // Max reachable t before first channel becomes negative. + float tMaxGamut; + // Applied t after user control mapping. + float tFinal; + + // Purity for input color in normalized 0..1 form (1 / tMax for input at t=1). + float purityCur01; + // Requested normalized purity (user input). + float purity01_in; + // Effective normalized purity after shaping curve. + float purity01_used; +}; + +// Main solver. +// +// There are three control modes: +// - purity_input_mode == MB_PURITY_MODE_NORMALIZED: +// purity_value is 0..1 "fraction of available purity headroom". +// - purity_input_mode == MB_PURITY_MODE_DISTANCE: +// purity_value is direct MB ray distance t. +// - purity_input_mode == MB_PURITY_MODE_SCALE_NEUTWO: +// purity_value is a scale multiplier in Neutwo inverse space (1 = unchanged). +// +// Optional adjust mode: +// - MB_PURITY_ADJUST_NONE: +// use selected input mode as-is. +// - MB_PURITY_ADJUST_CLIP_MAX: +// force max purity for this hue/gamut (tFinal = tMaxGamut). +// +// Important behavior: +// - Constraint is gamut-only (RGB >= 0), no arbitrary <= 1 clamp. +// - This allows scene-linear HDR values above 1.0 to pass through naturally. +MBPurityDebug ApplyInternal(float3 rgb_linear, float purity_value, int purity_input_mode, + float curve_gamma, float2 mb_white_override, float t_min, + int purity_adjust_mode, float3x3 rgb_to_xyz_mat, float3x3 xyz_to_rgb_mat) { + MBPurityDebug output; + + output.purity01_in = 0.f; + + // 1) RGB -> XYZ -> LMS + float3 xyz = mul(rgb_to_xyz_mat, rgb_linear); + float3 lms = mul(XYZ_TO_LMS_2006, xyz); + + // T = L + M is the intensity anchor for MB purity moves. + float t = lms.x + lms.y; + + if (t <= t_min) { + output.rgbOut = rgb_linear; + output.rgbT0 = rgb_linear; + output.rgbEdgeGamut = rgb_linear; + output.tMaxGamut = 0.f; + output.purityCur01 = 0.f; + output.purity01_used = 0.f; + return output; + } + + float2 white = + (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) ? mb_white_override : MB_White_D65(); + + // 2) MB ray from adapted white to input hue. + float2 mb0 = MB_From_LMS(lms); + float2 direction = mb0 - white; + + if (dot(direction, direction) < MB_NEAR_WHITE_EPSILON) { + output.rgbOut = rgb_linear; + output.rgbT0 = rgb_linear; + output.rgbEdgeGamut = rgb_linear; + output.tMaxGamut = 0.f; + output.tFinal = 0.f; + output.purityCur01 = 0.f; + output.purity01_used = 0.f; + return output; + } + + float3 lms_t0 = LMS_From_MB_T(white, t); + float3 xyz_t0 = mul(LMS_TO_XYZ_2006, lms_t0); + float3 rgb_t0 = mul(xyz_to_rgb_mat, xyz_t0); + output.rgbT0 = rgb_t0; + + // 4) Affine form of RGB along the MB ray at fixed T. + // t = 0 -> white in MB space, t = 1 -> original input. + float3 a = rgb_linear - rgb_t0; + + // 5) Intersect channel constraints RGB(t) >= 0 across R,G,B. + float t_lo = 0.f; + float t_hi = INTERVAL_MAX; + + float lo; + float hi; + + IntervalLower0(a.x, rgb_t0.x, lo, hi); + t_lo = max(t_lo, lo); + t_hi = min(t_hi, hi); + + IntervalLower0(a.y, rgb_t0.y, lo, hi); + t_lo = max(t_lo, lo); + t_hi = min(t_hi, hi); + + IntervalLower0(a.z, rgb_t0.z, lo, hi); + t_lo = max(t_lo, lo); + t_hi = min(t_hi, hi); + + if (t_hi < t_lo) { + output.rgbOut = max(rgb_linear, 0.f); + output.rgbEdgeGamut = rgb_t0; + output.tMaxGamut = 0.f; + output.tFinal = 0.f; + output.purityCur01 = 0.f; + output.purity01_used = 0.f; + return output; + } + + float t_max = max(0.f, t_hi); + output.tMaxGamut = t_max; + + // Current normalized purity for the input (which is at t = 1). + float p_cur = (t_max > EPSILON) ? renodx::math::DivideSafe(1.f, t_max, 0.f) : 0.f; + output.purityCur01 = saturate(p_cur); + + // Useful validation output: point on the gamut edge for this MB ray. + float3 rgb_edge = a * t_max + rgb_t0; + output.rgbEdgeGamut = rgb_edge; + + float t_final = 0.f; + + if (purity_adjust_mode == MB_PURITY_ADJUST_CLIP_MAX) { + output.purity01_used = 1.f; + output.purity01_in = 1.f; + t_final = t_max; + } else { + if (purity_input_mode == MB_PURITY_MODE_NORMALIZED) { + // Normalized mode: user operates in [0,1] of available gamut headroom. + output.purity01_in = saturate(purity_value); + float gamma = max(curve_gamma, 1e-6f); + float purity01 = pow(output.purity01_in, gamma); + output.purity01_used = purity01; + t_final = purity01 * t_max; + } else if (purity_input_mode == MB_PURITY_MODE_SCALE_NEUTWO) { + // Scale mode: user controls a saturation multiplier around current purity. + // 1 = no change, >1 increases, <1 decreases, with a smooth shoulder near edge. + float saturation_scale = max(purity_value, 0.f); + float purity01_target; + if (output.purityCur01 >= ONE_MINUS_EPSILON && saturation_scale >= 1.f) { + purity01_target = 1.f; + } else { + float z = InverseNeutwo(output.purityCur01); + float z_scaled = z * saturation_scale; + purity01_target = saturate(Neutwo(z_scaled)); + } + output.purity01_in = output.purityCur01; + output.purity01_used = purity01_target; + t_final = purity01_target * t_max; + } else { + // Distance mode: user value is interpreted as MB ray distance t. + float t_user = max(purity_value, 0.f); + t_final = min(t_user, t_max); + output.purity01_used = + (t_max > EPSILON) ? saturate(renodx::math::DivideSafe(t_final, t_max, 0.f)) : 0.f; + output.purity01_in = output.purity01_used; + } + } + + output.tFinal = t_final; + + float2 mb_final = white + t_final * direction; + + float3 lms_final = LMS_From_MB_T(mb_final, t); + float3 xyz_final = mul(LMS_TO_XYZ_2006, lms_final); + float3 rgb_final = mul(xyz_to_rgb_mat, xyz_final); + + // Clean up float math + output.rgbOut = max(rgb_final, 0.f); + + return output; +} + +MBPurityDebug ApplyBT709(float3 rgb709_linear, float purity01, float curve_gamma = 1.f, + float2 mb_white_override = float2(-1.f, -1.f), float t_min = 1e-6f, + int purity_adjust_mode = MB_PURITY_ADJUST_NONE) { + return ApplyInternal(rgb709_linear, purity01, MB_PURITY_MODE_NORMALIZED, curve_gamma, + mb_white_override, t_min, purity_adjust_mode, renodx::color::BT709_TO_XYZ_MAT, + renodx::color::XYZ_TO_BT709_MAT); +} + +MBPurityDebug ApplyBT2020(float3 rgb2020_linear, float purity01, float curve_gamma = 1.f, + float2 mb_white_override = float2(-1.f, -1.f), float t_min = 1e-6f, + int purity_adjust_mode = MB_PURITY_ADJUST_NONE) { + return ApplyInternal(rgb2020_linear, purity01, MB_PURITY_MODE_NORMALIZED, curve_gamma, + mb_white_override, t_min, purity_adjust_mode, renodx::color::BT2020_TO_XYZ_MAT, + renodx::color::XYZ_TO_BT2020_MAT); +} + +MBPurityDebug ApplyScaleBT709(float3 rgb709_linear, float saturation_scale, + float2 mb_white_override = float2(-1.f, -1.f), float t_min = 1e-6f, + int purity_adjust_mode = MB_PURITY_ADJUST_NONE) { + return ApplyInternal(rgb709_linear, saturation_scale, MB_PURITY_MODE_SCALE_NEUTWO, 1.f, + mb_white_override, t_min, purity_adjust_mode, renodx::color::BT709_TO_XYZ_MAT, + renodx::color::XYZ_TO_BT709_MAT); +} + +MBPurityDebug ApplyScaleBT2020(float3 rgb2020_linear, float saturation_scale, + float2 mb_white_override = float2(-1.f, -1.f), float t_min = 1e-6f, + int purity_adjust_mode = MB_PURITY_ADJUST_NONE) { + return ApplyInternal(rgb2020_linear, saturation_scale, MB_PURITY_MODE_SCALE_NEUTWO, 1.f, + mb_white_override, t_min, purity_adjust_mode, renodx::color::BT2020_TO_XYZ_MAT, + renodx::color::XYZ_TO_BT2020_MAT); +} + +float3 BT709(float3 rgb709_linear, float purity_scale, float2 mb_white) { + return ApplyInternal(rgb709_linear, purity_scale, MB_PURITY_MODE_DISTANCE, 1.f, mb_white, 0.f, + MB_PURITY_ADJUST_NONE, renodx::color::BT709_TO_XYZ_MAT, renodx::color::XYZ_TO_BT709_MAT) + .rgbOut; +} + +float3 BT2020(float3 rgb2020_linear, float purity_scale, float2 mb_white) { + return ApplyInternal(rgb2020_linear, purity_scale, MB_PURITY_MODE_DISTANCE, 1.f, mb_white, 0.f, + MB_PURITY_ADJUST_NONE, renodx::color::BT2020_TO_XYZ_MAT, renodx::color::XYZ_TO_BT2020_MAT) + .rgbOut; +} + +// Explicit max-purity helpers for testing. +float3 BT709MaxPurity(float3 rgb709_linear, float2 mb_white) { + return ApplyInternal(rgb709_linear, 0.f, MB_PURITY_MODE_DISTANCE, 1.f, mb_white, 0.f, + MB_PURITY_ADJUST_CLIP_MAX, renodx::color::BT709_TO_XYZ_MAT, renodx::color::XYZ_TO_BT709_MAT) + .rgbOut; +} + +float3 BT2020MaxPurity(float3 rgb2020_linear, float2 mb_white) { + return ApplyInternal(rgb2020_linear, 0.f, MB_PURITY_MODE_DISTANCE, 1.f, mb_white, 0.f, + MB_PURITY_ADJUST_CLIP_MAX, renodx::color::BT2020_TO_XYZ_MAT, renodx::color::XYZ_TO_BT2020_MAT) + .rgbOut; +} + +// Gamut compression in MB space: +// Use the white->hue MB ray and clamp t to at most 1.0 (input point). +// - If already in gamut, color is unchanged. +// - If out of gamut, color moves toward MB white until it hits gamut edge. +float3 GamutCompressBT709(float3 rgb709_linear, float2 mb_white = float2(-1.f, -1.f), + float t_min = 1e-6f) { + return ApplyInternal(rgb709_linear, 1.f, MB_PURITY_MODE_DISTANCE, 1.f, mb_white, t_min, + MB_PURITY_ADJUST_NONE, renodx::color::BT709_TO_XYZ_MAT, renodx::color::XYZ_TO_BT709_MAT) + .rgbOut; +} + +float3 GamutCompressBT2020(float3 rgb2020_linear, float2 mb_white = float2(-1.f, -1.f), + float t_min = 1e-6f) { + return ApplyInternal(rgb2020_linear, 1.f, MB_PURITY_MODE_DISTANCE, 1.f, mb_white, t_min, + MB_PURITY_ADJUST_NONE, renodx::color::BT2020_TO_XYZ_MAT, renodx::color::XYZ_TO_BT2020_MAT) + .rgbOut; +} + +// MB-space gamut compression with additive white in LMS. +// Derivation: +// - Let t_max be the white->input MB ray limit (input is at t=1). +// - To move input toward white to exactly t_max, MB blend weight is a = 1 - t_max. +// - Adding white in LMS with MB unit-T white vector gives: +// white_add = T * a / (1 - a) = T * (1 - t_max) / t_max +// where T = L + M of input. +// This preserves MB hue direction while compressing out-of-gamut colors by "adding white". +float3 GamutCompressAddWhiteInternal(float3 rgb_linear, float2 mb_white_override, float t_min, + float3x3 rgb_to_xyz_mat, float3x3 xyz_to_rgb_mat) { + float3 xyz = mul(rgb_to_xyz_mat, rgb_linear); + float3 lms = mul(XYZ_TO_LMS_2006, xyz); + float t = lms.x + lms.y; + + if (t <= t_min) { + return max(rgb_linear, 0.f); + } + + float2 white = (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) + ? mb_white_override + : MB_White_D65(); + + float2 mb0 = MB_From_LMS(lms); + float2 direction = mb0 - white; + if (dot(direction, direction) < MB_NEAR_WHITE_EPSILON) { + return max(rgb_linear, 0.f); + } + + float3 lms_t0 = LMS_From_MB_T(white, t); + float3 xyz_t0 = mul(LMS_TO_XYZ_2006, lms_t0); + float3 rgb_t0 = mul(xyz_to_rgb_mat, xyz_t0); + float3 ray_a = rgb_linear - rgb_t0; + + float t_lo = 0.f; + float t_hi = INTERVAL_MAX; + float lo; + float hi; + + IntervalLower0(ray_a.x, rgb_t0.x, lo, hi); + t_lo = max(t_lo, lo); + t_hi = min(t_hi, hi); + + IntervalLower0(ray_a.y, rgb_t0.y, lo, hi); + t_lo = max(t_lo, lo); + t_hi = min(t_hi, hi); + + IntervalLower0(ray_a.z, rgb_t0.z, lo, hi); + t_lo = max(t_lo, lo); + t_hi = min(t_hi, hi); + + if (t_hi < t_lo) { + return max(rgb_linear, 0.f); + } + + float t_max = max(0.f, t_hi); + float white_ratio = max(renodx::math::DivideSafe(1.f - t_max, t_max, 0.f), 0.f); + float white_add = t * white_ratio; + + // MB unit-T white vector in LMS (T = L+M = 1). + float3 white_unit_lms = LMS_From_MB_T(white, 1.f); + float3 lms_out = lms + white_unit_lms * white_add; + float3 xyz_out = mul(LMS_TO_XYZ_2006, lms_out); + float3 rgb_out = mul(xyz_to_rgb_mat, xyz_out); + return max(rgb_out, 0.f); +} + +float3 GamutCompressAddWhiteBT709(float3 rgb709_linear, float2 mb_white = float2(-1.f, -1.f), + float t_min = 1e-6f) { + return GamutCompressAddWhiteInternal(rgb709_linear, mb_white, t_min, renodx::color::BT709_TO_XYZ_MAT, + renodx::color::XYZ_TO_BT709_MAT); +} + +float3 GamutCompressAddWhiteBT2020(float3 rgb2020_linear, float2 mb_white = float2(-1.f, -1.f), + float t_min = 1e-6f) { + return GamutCompressAddWhiteInternal(rgb2020_linear, mb_white, t_min, renodx::color::BT2020_TO_XYZ_MAT, + renodx::color::XYZ_TO_BT2020_MAT); +} + +} // namespace macleod_boynton +} // namespace color +} // namespace renodx + +float3 ApplyPurityOnlyMBToBT709( + float3 target_color_bt2020, + float purity01, + float curve_gamma, + float2 mb_white_override, + float t_min) { + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); +} + +// Purity-only MB solve: +// Computes the same purityCur01 as ApplyBT2020(...).purityCur01, but skips final RGB reconstruction. +float Purity01FromBT2020MB( + float3 rgb2020_linear, + float2 mb_white_override = float2(-1.f, -1.f), + float t_min = 1e-6f) { + float3 xyz = mul(renodx::color::BT2020_TO_XYZ_MAT, rgb2020_linear); + float3 lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, xyz); + float t = lms.x + lms.y; + if (t <= t_min) return 0.f; + + float2 white = + (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) + ? mb_white_override + : renodx_custom::color::macleod_boynton::MB_White_D65(); + + float2 mb0 = renodx_custom::color::macleod_boynton::MB_From_LMS(lms); + float2 direction = mb0 - white; + if (dot(direction, direction) < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) return 0.f; + + float3 lms_t0 = renodx_custom::color::macleod_boynton::LMS_From_MB_T(white, t); + float3 xyz_t0 = mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, lms_t0); + float3 rgb_t0 = mul(renodx::color::XYZ_TO_BT2020_MAT, xyz_t0); + float3 a = rgb2020_linear - rgb_t0; + + float t_lo = 0.f; + float t_hi = renodx_custom::color::macleod_boynton::INTERVAL_MAX; + float lo; + float hi; + + renodx_custom::color::macleod_boynton::IntervalLower0(a.x, rgb_t0.x, lo, hi); + t_lo = max(t_lo, lo); + t_hi = min(t_hi, hi); + + renodx_custom::color::macleod_boynton::IntervalLower0(a.y, rgb_t0.y, lo, hi); + t_lo = max(t_lo, lo); + t_hi = min(t_hi, hi); + + renodx_custom::color::macleod_boynton::IntervalLower0(a.z, rgb_t0.z, lo, hi); + t_lo = max(t_lo, lo); + t_hi = min(t_hi, hi); + + if (t_hi < t_lo) return 0.f; + + float t_max = max(0.f, t_hi); + float p_cur = (t_max > renodx_custom::color::macleod_boynton::EPSILON) + ? renodx::math::DivideSafe(1.f, t_max, 0.f) + : 0.f; + return saturate(p_cur); +} + +float3 CorrectPurityMBBT709WithBT2020( + float3 target_color_bt709, + float3 purity_reference_bt709, + float strength = 1.f, + float curve_gamma = 1.f, + float2 mb_white_override = float2(-1.f, -1.f), + float t_min = 1e-7f, + float clamp_purity_loss = 0.f) { + if (strength <= 0.f) return target_color_bt709; + + float3 target_color_bt2020 = renodx::color::bt2020::from::BT709(target_color_bt709); + float3 purity_reference_bt2020 = renodx::color::bt2020::from::BT709(purity_reference_bt709); + + float reference_purity01 = + renodx_custom::color::macleod_boynton::ApplyBT2020(purity_reference_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01; + + float applied_purity01; + if (strength == 1.f && clamp_purity_loss <= 0.f) { + // Fast path: full transfer only needs donor purity. + applied_purity01 = reference_purity01; + } else { + float target_purity01 = + renodx_custom::color::macleod_boynton::ApplyBT2020(target_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01; + + applied_purity01 = lerp(target_purity01, reference_purity01, strength); + + if (clamp_purity_loss > 0.f) { + float clamp_strength = saturate(clamp_purity_loss); + // Only clamp purity reductions: if applied < target, pull back toward target. + float t = 1.f - step(target_purity01, applied_purity01); + applied_purity01 = lerp(applied_purity01, target_purity01, t * clamp_strength); + } + } + + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); +} + +float3 CorrectHueAndPurityMBBT709WithBT2020( + float3 target_color_bt709, + float3 reference_color_bt709, + float hue_strength = 1.f, + float purity_strength = 1.f, + float curve_gamma = 1.f, + float2 mb_white_override = float2(-1.f, -1.f), + float t_min = 1e-6f) { + if (purity_strength <= 0.f && hue_strength <= 0.f) { + return target_color_bt709; + } + + if (hue_strength <= 0.f) { + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); + } + + float3 target_color_bt2020 = renodx::color::bt2020::from::BT709(target_color_bt709); + float3 reference_color_bt2020 = renodx::color::bt2020::from::BT709(reference_color_bt709); + + float3 target_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, target_color_bt2020)); + float target_t = target_lms.x + target_lms.y; + if (target_t <= t_min) { + return target_color_bt709; + } + + float hue_blend = saturate(hue_strength); + + if (hue_blend <= 0.f) { + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); + } + + float target_purity01 = + renodx_custom::color::macleod_boynton::ApplyBT2020(target_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01; + float applied_purity01 = target_purity01; + if (purity_strength > 0.f) { + float reference_purity01 = + renodx_custom::color::macleod_boynton::ApplyBT2020(reference_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01; + applied_purity01 = lerp(target_purity01, reference_purity01, saturate(purity_strength)); + } + + float3 reference_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, reference_color_bt2020)); + + float2 white = (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) + ? mb_white_override + : renodx_custom::color::macleod_boynton::MB_White_D65(); + + float2 target_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(target_lms) - white; + float2 reference_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_lms) - white; + + float target_len_sq = dot(target_direction, target_direction); + float reference_len_sq = dot(reference_direction, reference_direction); + + if (target_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON && reference_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); + } + + float2 target_unit = (target_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? target_direction * rsqrt(target_len_sq) + : float2(0.f, 0.f); + float2 reference_unit = (reference_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? reference_direction * rsqrt(reference_len_sq) + : target_unit; + if (target_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + target_unit = reference_unit; + } + + float2 blended_unit = lerp(target_unit, reference_unit, hue_blend); + float blended_len_sq = dot(blended_unit, blended_unit); + if (blended_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + blended_unit = (hue_blend >= 0.5f) ? reference_unit : target_unit; + blended_len_sq = dot(blended_unit, blended_unit); + } + blended_unit *= rsqrt(max(blended_len_sq, 1e-20f)); + + float seed_len = sqrt(max(target_len_sq, 0.f)); + if (seed_len <= 1e-6f) { + seed_len = sqrt(max(reference_len_sq, 0.f)); + } + seed_len = max(seed_len, 1e-6f); + + float3 seed_bt2020 = mul( + renodx::color::XYZ_TO_BT2020_MAT, + mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, + renodx_custom::color::macleod_boynton::LMS_From_MB_T(white + blended_unit * seed_len, target_t))); + + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + seed_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); +} + +float3 CorrectHueAndPurityMB_BT2020( + float3 target_color_bt2020, + float3 reference_color_bt2020, + float hue_strength = 1.f, + float purity_strength = 1.f, + float curve_gamma = 1.f, + float2 mb_white_override = float2(-1.f, -1.f), + float t_min = 1e-7f) { + if (purity_strength <= 0.f && hue_strength <= 0.f) { + return target_color_bt2020; + } + + float applied_purity01 = lerp( + renodx_custom::color::macleod_boynton::ApplyBT2020(target_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01, + renodx_custom::color::macleod_boynton::ApplyBT2020(reference_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01, + saturate(purity_strength)); + + if (hue_strength <= 0.f) { + return renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut; + } + + float3 target_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, target_color_bt2020)); + float target_t = target_lms.x + target_lms.y; + if (target_t <= t_min) { + return target_color_bt2020; + } + + float hue_blend = saturate(hue_strength); + + if (hue_blend <= 0.f) { + return renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut; + } + + float3 reference_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, reference_color_bt2020)); + + float2 white = (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) + ? mb_white_override + : renodx_custom::color::macleod_boynton::MB_White_D65(); + + float2 target_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(target_lms) - white; + float2 reference_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_lms) - white; + + float target_len_sq = dot(target_direction, target_direction); + float reference_len_sq = dot(reference_direction, reference_direction); + + if (target_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON && reference_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + return renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut; + } + + float2 target_unit = (target_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? target_direction * rsqrt(target_len_sq) + : float2(0.f, 0.f); + float2 reference_unit = (reference_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? reference_direction * rsqrt(reference_len_sq) + : target_unit; + if (target_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + target_unit = reference_unit; + } + + float2 blended_unit = lerp(target_unit, reference_unit, hue_blend); + float blended_len_sq = dot(blended_unit, blended_unit); + if (blended_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + blended_unit = (hue_blend >= 0.5f) ? reference_unit : target_unit; + blended_len_sq = dot(blended_unit, blended_unit); + } + blended_unit *= rsqrt(max(blended_len_sq, 1e-20f)); + + float seed_len = sqrt(max(target_len_sq, 0.f)); + if (seed_len <= 1e-6f) { + seed_len = sqrt(max(reference_len_sq, 0.f)); + } + seed_len = max(seed_len, 1e-6f); + + float3 seed_bt2020 = mul( + renodx::color::XYZ_TO_BT2020_MAT, + mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, + renodx_custom::color::macleod_boynton::LMS_From_MB_T(white + blended_unit * seed_len, target_t))); + + return renodx_custom::color::macleod_boynton::ApplyBT2020( + seed_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut; +} + +float3 CorrectHueAndPurityMBGated( + float3 target_color_bt709, + float3 reference_color_bt709, + float hue_strength = 1.f, + float hue_t_ramp_start = 0.5f, + float hue_t_ramp_end = 1.f, + float purity_strength = 1.f, + float curve_gamma = 1.f, + float2 mb_white_override = float2(-1.f, -1.f), + float t_min = 1e-6f) { + if (purity_strength <= 0.f && hue_strength <= 0.f) { + return target_color_bt709; + } + + if (hue_strength <= 0.f) { + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); + } + + float3 target_color_bt2020 = renodx::color::bt2020::from::BT709(target_color_bt709); + float3 reference_color_bt2020 = renodx::color::bt2020::from::BT709(reference_color_bt709); + + float3 target_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, target_color_bt2020)); + float target_t = target_lms.x + target_lms.y; + if (target_t <= t_min) { + return target_color_bt709; + } + + // Hue gating ramp in MB intensity anchor space (T = L + M). + float hue_blend = hue_strength * saturate((target_t - hue_t_ramp_start) / (hue_t_ramp_end - hue_t_ramp_start)); + + if (hue_blend <= 0.f) { + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); + } + + float applied_purity01 = lerp( + renodx_custom::color::macleod_boynton::ApplyBT2020(target_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01, + renodx_custom::color::macleod_boynton::ApplyBT2020(reference_color_bt2020, 1.f, 1.f, + mb_white_override, t_min) + .purityCur01, + purity_strength); + + float3 reference_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, reference_color_bt2020)); + + float2 white = (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) + ? mb_white_override + : renodx_custom::color::macleod_boynton::MB_White_D65(); + + float2 target_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(target_lms) - white; + float2 reference_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_lms) - white; + + float target_len_sq = dot(target_direction, target_direction); + float reference_len_sq = dot(reference_direction, reference_direction); + + if (target_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON && reference_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + return CorrectPurityMBBT709WithBT2020(target_color_bt709, reference_color_bt709, purity_strength, curve_gamma, + mb_white_override, t_min); + } + + float2 target_unit = (target_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? target_direction * rsqrt(target_len_sq) + : float2(0.f, 0.f); + float2 reference_unit = (reference_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? reference_direction * rsqrt(reference_len_sq) + : target_unit; + if (target_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + target_unit = reference_unit; + } + + float2 blended_unit = lerp(target_unit, reference_unit, hue_blend); + float blended_len_sq = dot(blended_unit, blended_unit); + if (blended_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + blended_unit = (hue_blend >= 0.5f) ? reference_unit : target_unit; + blended_len_sq = dot(blended_unit, blended_unit); + } + blended_unit *= rsqrt(max(blended_len_sq, 1e-20f)); + + float seed_len = sqrt(max(target_len_sq, 0.f)); + if (seed_len <= 1e-6f) { + seed_len = sqrt(max(reference_len_sq, 0.f)); + } + seed_len = max(seed_len, 1e-6f); + + float3 seed_bt2020 = mul( + renodx::color::XYZ_TO_BT2020_MAT, + mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, + renodx_custom::color::macleod_boynton::LMS_From_MB_T(white + blended_unit * seed_len, target_t))); + + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + seed_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); +} + +// Single-reference MB correction with luminosity-gated hue: +// - Purity from reference is always applied at full strength. +// - Hue from reference is gated by LMS luminosity ramp (1.55 * L + M). +float3 CorrectHueLuminosityGatedAndPurityMB( + float3 target_color_bt709, + float3 reference_color_bt709, + float hue_lum_ramp_start = 0.5f, + float hue_lum_ramp_end = 1.f, + float purity_scale = 1.f, + float curve_gamma = 1.f, + float2 mb_white_override = float2(-1.f, -1.f), + float t_min = 1e-6f) { + const float kNearWhiteEpsilon = renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON; + + float3 target_color_bt2020 = renodx::color::bt2020::from::BT709(target_color_bt709); + + float3 target_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, target_color_bt2020)); + float target_t = target_lms.x + target_lms.y; + if (target_t <= t_min) { + return target_color_bt709; + } + + float target_luminosity = 1.55f * target_lms.x + target_lms.y; + float hue_blend = saturate(renodx::math::DivideSafe( + target_luminosity - hue_lum_ramp_start, hue_lum_ramp_end - hue_lum_ramp_start, 0.f)); + + float2 white = (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) + ? mb_white_override + : renodx_custom::color::macleod_boynton::MB_White_D65(); + + float3 reference_color_bt2020 = renodx::color::bt2020::from::BT709(reference_color_bt709); + float reference_purity01 = saturate(Purity01FromBT2020MB(reference_color_bt2020, white, t_min) * purity_scale); + + if (hue_blend <= 0.f) { + return ApplyPurityOnlyMBToBT709( + target_color_bt2020, reference_purity01, curve_gamma, mb_white_override, t_min); + } + + float3 reference_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, reference_color_bt2020)); + + float2 target_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(target_lms) - white; + float2 reference_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_lms) - white; + + float target_len_sq = dot(target_direction, target_direction); + float reference_len_sq = dot(reference_direction, reference_direction); + + if (target_len_sq < kNearWhiteEpsilon && reference_len_sq < kNearWhiteEpsilon) { + return ApplyPurityOnlyMBToBT709( + target_color_bt2020, reference_purity01, curve_gamma, mb_white_override, t_min); + } + + float2 target_unit = (target_len_sq > kNearWhiteEpsilon) + ? target_direction * rsqrt(target_len_sq) + : float2(0.f, 0.f); + float2 reference_unit = (reference_len_sq > kNearWhiteEpsilon) + ? reference_direction * rsqrt(reference_len_sq) + : target_unit; + if (target_len_sq <= kNearWhiteEpsilon) { + target_unit = reference_unit; + } + + float2 blended_unit = lerp(target_unit, reference_unit, hue_blend); + float blended_len_sq = dot(blended_unit, blended_unit); + if (blended_len_sq <= kNearWhiteEpsilon) { + blended_unit = (hue_blend >= 0.5f) ? reference_unit : target_unit; + blended_len_sq = dot(blended_unit, blended_unit); + } + blended_unit *= rsqrt(max(blended_len_sq, 1e-20f)); + + float seed_len = sqrt(max(target_len_sq, 0.f)); + if (seed_len <= 1e-6f) { + seed_len = sqrt(max(reference_len_sq, 0.f)); + } + seed_len = max(seed_len, 1e-6f); + + float3 seed_bt2020 = mul( + renodx::color::XYZ_TO_BT2020_MAT, + mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, + renodx_custom::color::macleod_boynton::LMS_From_MB_T(white + blended_unit * seed_len, target_t))); + + return ApplyPurityOnlyMBToBT709( + seed_bt2020, reference_purity01, curve_gamma, mb_white_override, t_min); +} + +// Single-reference MB correction with split low/high strengths: +// - One reference color drives both hue and purity donors. +// - Hue and purity each have independent low/high strengths. +// - A shared ramp drives both strengths, anchored to reference luminosity. +float3 CorrectHueAndPurityMBSplitStrength( + float3 target_color_bt709, + float3 reference_color_bt709, + float hue_strength_low = 0.f, + float hue_strength_high = 1.f, + float purity_strength_low = 0.f, + float purity_strength_high = 1.f, + float ramp_start_offset = 0.5f, + float ramp_end_offset = 1.f, + float curve_gamma = 1.f, + float2 mb_white_override = float2(-1.f, -1.f), + float t_min = 1e-6f) { + const float kNearWhiteEpsilon = renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON; + + float3 target_color_bt2020 = renodx::color::bt2020::from::BT709(target_color_bt709); + float3 reference_color_bt2020 = renodx::color::bt2020::from::BT709(reference_color_bt709); + + float3 target_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, target_color_bt2020)); + float target_t = target_lms.x + target_lms.y; + if (target_t <= t_min) { + return target_color_bt709; + } + + float3 reference_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, reference_color_bt2020)); + float3 white_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, float3(1.f, 1.f, 1.f))); + + float white_luminosity = max(1e-6f, 1.55f * white_lms.x + white_lms.y); + float target_luminosity = (1.55f * target_lms.x + target_lms.y) / white_luminosity; + float reference_luminosity = (1.55f * reference_lms.x + reference_lms.y) / white_luminosity; + + float ramp_start = reference_luminosity + ramp_start_offset; + float ramp_end = reference_luminosity + ramp_end_offset; + float ramp_t = saturate(renodx::math::DivideSafe( + target_luminosity - ramp_start, ramp_end - ramp_start, 0.f)); + + float hue_strength = saturate(lerp(hue_strength_low, hue_strength_high, ramp_t)); + float purity_strength = saturate(lerp(purity_strength_low, purity_strength_high, ramp_t)); + + if (purity_strength <= 0.f && hue_strength <= 0.f) { + return target_color_bt709; + } + + float target_purity01 = renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, 1.f, 1.f, mb_white_override, t_min) + .purityCur01; + float reference_purity01 = renodx_custom::color::macleod_boynton::ApplyBT2020( + reference_color_bt2020, 1.f, 1.f, mb_white_override, t_min) + .purityCur01; + float applied_purity01 = lerp(target_purity01, reference_purity01, purity_strength); + + if (hue_strength <= 0.f) { + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); + } + + float2 white = (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) + ? mb_white_override + : renodx_custom::color::macleod_boynton::MB_White_D65(); + + float2 target_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(target_lms) - white; + float2 reference_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_lms) - white; + + float target_len_sq = dot(target_direction, target_direction); + float reference_len_sq = dot(reference_direction, reference_direction); + + if (target_len_sq < kNearWhiteEpsilon && reference_len_sq < kNearWhiteEpsilon) { + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); + } + + float2 target_unit = (target_len_sq > kNearWhiteEpsilon) + ? target_direction * rsqrt(target_len_sq) + : float2(0.f, 0.f); + float2 reference_unit = (reference_len_sq > kNearWhiteEpsilon) + ? reference_direction * rsqrt(reference_len_sq) + : target_unit; + if (target_len_sq <= kNearWhiteEpsilon) { + target_unit = reference_unit; + } + + float2 blended_unit = lerp(target_unit, reference_unit, hue_strength); + float blended_len_sq = dot(blended_unit, blended_unit); + if (blended_len_sq <= kNearWhiteEpsilon) { + blended_unit = (hue_strength >= 0.5f) ? reference_unit : target_unit; + blended_len_sq = dot(blended_unit, blended_unit); + } + blended_unit *= rsqrt(max(blended_len_sq, 1e-20f)); + + float seed_len = sqrt(max(target_len_sq, 0.f)); + if (seed_len <= 1e-6f) { + seed_len = sqrt(max(reference_len_sq, 0.f)); + } + seed_len = max(seed_len, 1e-6f); + + float3 seed_bt2020 = mul( + renodx::color::XYZ_TO_BT2020_MAT, + mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, + renodx_custom::color::macleod_boynton::LMS_From_MB_T(white + blended_unit * seed_len, target_t))); + + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + seed_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); +} + +float3 CorrectHueAndPurityMB2References( + float3 target_color_bt709, + float3 reference_low_bt709, + float3 reference_high_bt709, + float hue_strength = 1.f, + float hue_t_ramp_start = 0.5f, + float hue_t_ramp_end = 1.f, + float purity_strength = 1.f, + float curve_gamma = 1.f, + float2 mb_white_override = float2(-1.f, -1.f), + float t_min = 1e-6f) { + if (purity_strength <= 0.f && hue_strength <= 0.f) { + return target_color_bt709; + } + + float3 target_color_bt2020 = renodx::color::bt2020::from::BT709(target_color_bt709); + float3 reference_low_bt2020 = renodx::color::bt2020::from::BT709(reference_low_bt709); + float3 reference_high_bt2020 = renodx::color::bt2020::from::BT709(reference_high_bt709); + + float3 target_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, target_color_bt2020)); + float target_t = target_lms.x + target_lms.y; + if (target_t <= t_min) { + return target_color_bt709; + } + + float ramp_t = saturate((target_t - hue_t_ramp_start) / (hue_t_ramp_end - hue_t_ramp_start)); + + float target_purity01 = renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, 1.f, 1.f, mb_white_override, t_min) + .purityCur01; + float low_purity01 = renodx_custom::color::macleod_boynton::ApplyBT2020( + reference_low_bt2020, 1.f, 1.f, mb_white_override, t_min) + .purityCur01; + float high_purity01 = renodx_custom::color::macleod_boynton::ApplyBT2020( + reference_high_bt2020, 1.f, 1.f, mb_white_override, t_min) + .purityCur01; + float applied_purity01 = lerp(target_purity01, lerp(low_purity01, high_purity01, ramp_t), purity_strength); + + if (hue_strength <= 0.f) { + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); + } + + float3 reference_low_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, reference_low_bt2020)); + float3 reference_high_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, reference_high_bt2020)); + + float2 white = (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) + ? mb_white_override + : renodx_custom::color::macleod_boynton::MB_White_D65(); + + float2 target_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(target_lms) - white; + float2 low_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_low_lms) - white; + float2 high_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_high_lms) - white; + + float target_len_sq = dot(target_direction, target_direction); + float low_len_sq = dot(low_direction, low_direction); + float high_len_sq = dot(high_direction, high_direction); + + if (low_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON && high_len_sq < renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); + } + + float2 target_unit = (target_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? target_direction * rsqrt(target_len_sq) + : float2(0.f, 0.f); + float2 low_unit = (low_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? low_direction * rsqrt(low_len_sq) + : target_unit; + float2 high_unit = (high_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) + ? high_direction * rsqrt(high_len_sq) + : low_unit; + + float2 reference_unit = lerp(low_unit, high_unit, ramp_t); + float reference_len_sq = dot(reference_unit, reference_unit); + if (reference_len_sq > renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + reference_unit *= rsqrt(reference_len_sq); + } else { + reference_unit = high_unit; + } + + if (target_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + target_unit = reference_unit; + } + + float2 blended_unit = lerp(target_unit, reference_unit, hue_strength); + float blended_len_sq = dot(blended_unit, blended_unit); + if (blended_len_sq <= renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON) { + blended_unit = (hue_strength >= 0.5f) ? reference_unit : target_unit; + blended_len_sq = dot(blended_unit, blended_unit); + } + blended_unit *= rsqrt(max(blended_len_sq, 1e-20f)); + + float seed_len = sqrt(max(target_len_sq, 0.f)); + if (seed_len <= 1e-6f) { + seed_len = sqrt(max(lerp(low_len_sq, high_len_sq, ramp_t), 0.f)); + } + seed_len = max(seed_len, 1e-6f); + + float3 seed_bt2020 = mul( + renodx::color::XYZ_TO_BT2020_MAT, + mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, + renodx_custom::color::macleod_boynton::LMS_From_MB_T(white + blended_unit * seed_len, target_t))); + + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + seed_bt2020, applied_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); +} + +// Fused variant: +// 1) Low reference hue is the full-strength base hue. +// 2) High reference hue is layered by ramp in MB T = L + M space. +// 3) High reference purity is applied at full strength over full range. +float3 CorrectLowHueThenHighHueAndPurityMB( + float3 target_color_bt709, + float3 reference_low_bt709, + float3 reference_high_bt709, + float high_hue_strength = 1.f, + float hue_t_ramp_start = 0.5f, + float hue_t_ramp_end = 1.f, + float curve_gamma = 1.f, + float2 mb_white_override = float2(-1.f, -1.f), + float t_min = 1e-6f) { + const float kNearWhiteEpsilon = renodx_custom::color::macleod_boynton::MB_NEAR_WHITE_EPSILON; + + float3 target_color_bt2020 = renodx::color::bt2020::from::BT709(target_color_bt709); + float3 reference_low_bt2020 = renodx::color::bt2020::from::BT709(reference_low_bt709); + float3 reference_high_bt2020 = renodx::color::bt2020::from::BT709(reference_high_bt709); + + float3 target_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, target_color_bt2020)); + float target_t = target_lms.x + target_lms.y; + if (target_t <= t_min) { + return target_color_bt709; + } + + float ramp_t = saturate(renodx::math::DivideSafe(target_t - hue_t_ramp_start, hue_t_ramp_end - hue_t_ramp_start, 0.f)); + float high_hue_blend = saturate(high_hue_strength) * ramp_t; + + // Full-strength purity from high reference (one donor purity solve). + float high_purity01 = renodx_custom::color::macleod_boynton::ApplyBT2020( + reference_high_bt2020, 1.f, 1.f, mb_white_override, t_min) + .purityCur01; + + float3 reference_low_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, reference_low_bt2020)); + float3 reference_high_lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, + mul(renodx::color::BT2020_TO_XYZ_MAT, reference_high_bt2020)); + + float2 white = (mb_white_override.x >= 0.f && mb_white_override.y >= 0.f) + ? mb_white_override + : renodx_custom::color::macleod_boynton::MB_White_D65(); + + float2 target_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(target_lms) - white; + float2 low_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_low_lms) - white; + float2 high_direction = renodx_custom::color::macleod_boynton::MB_From_LMS(reference_high_lms) - white; + + float target_len_sq = dot(target_direction, target_direction); + float low_len_sq = dot(low_direction, low_direction); + float high_len_sq = dot(high_direction, high_direction); + + float2 low_unit = float2(0.f, 0.f); + if (low_len_sq > kNearWhiteEpsilon) { + low_unit = low_direction * rsqrt(low_len_sq); + } else if (target_len_sq > kNearWhiteEpsilon) { + low_unit = target_direction * rsqrt(target_len_sq); + } else if (high_len_sq > kNearWhiteEpsilon) { + low_unit = high_direction * rsqrt(high_len_sq); + } + + float2 high_unit = (high_len_sq > kNearWhiteEpsilon) ? high_direction * rsqrt(high_len_sq) : low_unit; + + float2 blended_unit = lerp(low_unit, high_unit, high_hue_blend); + float blended_len_sq = dot(blended_unit, blended_unit); + if (blended_len_sq <= kNearWhiteEpsilon) { + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + target_color_bt2020, high_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); + } + blended_unit *= rsqrt(blended_len_sq); + + float seed_len = sqrt(max(target_len_sq, 0.f)); + if (seed_len <= 1e-6f) { + seed_len = sqrt(max(lerp(low_len_sq, high_len_sq, ramp_t), 0.f)); + } + seed_len = max(seed_len, 1e-6f); + + float3 seed_bt2020 = mul( + renodx::color::XYZ_TO_BT2020_MAT, + mul(renodx_custom::color::macleod_boynton::LMS_TO_XYZ_2006, + renodx_custom::color::macleod_boynton::LMS_From_MB_T(white + blended_unit * seed_len, target_t))); + + return renodx::color::bt709::from::BT2020( + renodx_custom::color::macleod_boynton::ApplyBT2020( + seed_bt2020, high_purity01, curve_gamma, mb_white_override, t_min) + .rgbOut); +} + +float LuminosityFromBT709(float3 bt709_linear) { + float3 xyz = mul(renodx::color::BT709_TO_XYZ_MAT, bt709_linear); + float3 lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, xyz); + return 1.55f * lms.x + lms.y; +} + +float LuminosityFromBT709LuminanceNormalized(float3 bt709_linear) { + float luminosity = LuminosityFromBT709(bt709_linear); + + return luminosity / LuminosityFromBT709(1.f); +} + +float LuminosityFromBT2020(float3 bt2020_linear) { + float3 xyz = mul(renodx::color::BT2020_TO_XYZ_MAT, bt2020_linear); + float3 lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, xyz); + return 1.55f * lms.x + lms.y; +} + +float LuminosityFromBT2020LuminanceNormalized(float3 bt2020_linear) { + float luminosity = LuminosityFromBT2020(bt2020_linear); + + return luminosity / LuminosityFromBT2020(1.f); +} + +float LuminosityFromAP1(float3 ap1_linear) { + float3 xyz = mul(renodx::color::AP1_TO_XYZ_MAT, ap1_linear); + float3 lms = mul(renodx_custom::color::macleod_boynton::XYZ_TO_LMS_2006, xyz); + return 1.55f * lms.x + lms.y; +} + +float LuminosityFromAP1LuminanceNormalized(float3 ap1_linear) { + return LuminosityFromAP1(ap1_linear) / LuminosityFromAP1(1.f); +} + +#endif // SRC_GAMES_CRIMSONDESERT_MACLEOD_BOYNTON_HLSLI_ \ No newline at end of file diff --git a/src/games/deathstranding2/tonemap/psycho_test11.hlsli b/src/games/deathstranding2/tonemap/psycho_test11.hlsli deleted file mode 100644 index f16b08a84..000000000 --- a/src/games/deathstranding2/tonemap/psycho_test11.hlsli +++ /dev/null @@ -1,720 +0,0 @@ -#ifndef RENODX_SHADERS_TONEMAP_PSYCHO_TEST11_HLSL_ -#define RENODX_SHADERS_TONEMAP_PSYCHO_TEST11_HLSL_ - -namespace renodx_custom { -namespace tonemap { -namespace psycho { - -static const float3x3 PSYCHO11_BT709_TO_XYZ_MAT = float3x3( - 0.4123907993f, 0.3575843394f, 0.1804807884f, - 0.2126390059f, 0.7151686788f, 0.0721923154f, - 0.0193308187f, 0.1191947798f, 0.9505321522f); - -static const float3x3 PSYCHO11_XYZ_TO_BT709_MAT = float3x3( - 3.2409699419f, -1.5373831776f, -0.4986107603f, - -0.9692436363f, 1.8759675015f, 0.0415550574f, - 0.0556300797f, -0.2039769589f, 1.0569715142f); - -static const float3x3 PSYCHO11_BT2020_TO_XYZ_MAT = float3x3( - 0.6369580483f, 0.1446169036f, 0.1688809752f, - 0.2627002120f, 0.6779980715f, 0.0593017165f, - 0.0000000000f, 0.0280726930f, 1.0609850577f); - -static const float3x3 PSYCHO11_XYZ_TO_BT2020_MAT = float3x3( - 1.7166511880f, -0.3556707838f, -0.2533662814f, - -0.6666843518f, 1.6164812366f, 0.0157685458f, - 0.0176398574f, -0.0427706133f, 0.9421031212f); - -static const float3x3 PSYCHO11_XYZ_TO_STOCKMAN_SHARP_LMS_MAT = float3x3( - 0.2670502842655792f, 0.8471990148492798f, -0.03470416612462053f, - -0.38706882411220156f, 1.165429935890458f, 0.10302286696614202f, - 0.026727793989083093f, -0.02729131667566509f, 0.5333267257603284f); - -static const float3 PSYCHO11_CIE1702_MB_CIE_WEIGHTS = float3( - 0.68990272f, 0.34832189f, 0.0371597f); - -static const float2 PSYCHO11_WHITE_POINT_D65 = float2(0.31272f, 0.32903f); -// Precomputed psycho11_MB2FromLMS(XYZ_TO_LMS(xyY(D65, 1))).xy -static const float2 PSYCHO11_WHITE_D65_MB = float2(0.6983281224f, 0.0204761309f); - -float psycho11_DivideSafe(float dividend, float divisor, float fallback) { - return divisor == 0.f ? fallback : (dividend / divisor); -} - -float3 psycho11_SignPow(float3 x, float3 exponent) { - return float3( - (x.x < 0.f ? -1.f : 1.f) * pow(abs(x.x), exponent.x), - (x.y < 0.f ? -1.f : 1.f) * pow(abs(x.y), exponent.y), - (x.z < 0.f ? -1.f : 1.f) * pow(abs(x.z), exponent.z)); -} - -float3x3 psycho11_Invert3x3(float3x3 m) { - float a = m[0][0], b = m[0][1], c = m[0][2]; - float d = m[1][0], e = m[1][1], f = m[1][2]; - float g = m[2][0], h = m[2][1], i = m[2][2]; - - float A = (e * i - f * h); - float B = -(d * i - f * g); - float C = (d * h - e * g); - float D = -(b * i - c * h); - float E = (a * i - c * g); - float F = -(a * h - b * g); - float G = (b * f - c * e); - float H = -(a * f - c * d); - float I = (a * e - b * d); - - float det = a * A + b * B + c * C; - float inv_det = psycho11_DivideSafe(1.f, det, 0.f); - - return float3x3( - A, D, G, - B, E, H, - C, F, I) - * inv_det; -} - -float3 psycho11_XYZFromxyY(float3 xyY) { - float3 xyz; - xyz.xz = float2(xyY.x, (1.f - xyY.x - xyY.y)) / xyY.y * xyY.z; - xyz.y = xyY.z; - return xyz; -} - -float3 psycho11_BT2020FromBT709(float3 bt709) { - return mul(PSYCHO11_XYZ_TO_BT2020_MAT, mul(PSYCHO11_BT709_TO_XYZ_MAT, bt709)); -} - -float3 psycho11_BT709FromBT2020(float3 bt2020) { - return mul(PSYCHO11_XYZ_TO_BT709_MAT, mul(PSYCHO11_BT2020_TO_XYZ_MAT, bt2020)); -} - -float3 psycho11_LMSFromBT2020(float3 bt2020) { - float3 xyz = mul(PSYCHO11_BT2020_TO_XYZ_MAT, bt2020); - return mul(PSYCHO11_XYZ_TO_STOCKMAN_SHARP_LMS_MAT, xyz); -} - -float3 psycho11_BT2020FromLMS(float3 lms_abs) { - float3x3 lms_to_xyz = psycho11_Invert3x3(PSYCHO11_XYZ_TO_STOCKMAN_SHARP_LMS_MAT); - float3 xyz = mul(lms_to_xyz, lms_abs); - return mul(PSYCHO11_XYZ_TO_BT2020_MAT, xyz); -} - -float psycho11_StockmanLuminanceFromLMS(float3 lms_abs) { - return dot(lms_abs, float3(0.68990272f, 0.34832189f, 0.0f)); -} - -float psycho11_StockmanLuminanceFromBT2020(float3 bt2020) { - float3 lms_abs = psycho11_LMSFromBT2020(bt2020); - return psycho11_StockmanLuminanceFromLMS(lms_abs); -} - -float psycho11_StockmanLuminanceFromBT709(float3 bt709) { - float3 bt2020 = psycho11_BT2020FromBT709(bt709); - return psycho11_StockmanLuminanceFromBT2020(bt2020); -} - -float3 psycho11_MB2FromLMS(float3 lms_abs) { - const float mb2_eps = 1e-12f; - - float weighted_l = PSYCHO11_CIE1702_MB_CIE_WEIGHTS.x * lms_abs.x; - float weighted_m = PSYCHO11_CIE1702_MB_CIE_WEIGHTS.y * lms_abs.y; - float y_mb = weighted_l + weighted_m; - if (y_mb <= mb2_eps) return 0.f.xxx; - - float inv = psycho11_DivideSafe(1.f, y_mb, 0.f); - return float3( - weighted_l * inv, - PSYCHO11_CIE1702_MB_CIE_WEIGHTS.z * lms_abs.z * inv, - y_mb); -} - -float3 psycho11_LMSFromMB2(float3 mb2_lsy) { - float l = mb2_lsy.x; - float s = mb2_lsy.y; - float y = max(mb2_lsy.z, 0.f); - - float L = psycho11_DivideSafe(l * y, PSYCHO11_CIE1702_MB_CIE_WEIGHTS.x, 0.f); - float M = psycho11_DivideSafe((1.f - l) * y, PSYCHO11_CIE1702_MB_CIE_WEIGHTS.y, 0.f); - float S = psycho11_DivideSafe(s * y, PSYCHO11_CIE1702_MB_CIE_WEIGHTS.z, 0.f); - return float3(L, M, S); -} - -float2 psycho11_WhiteD65Chromaticity() { - return PSYCHO11_WHITE_D65_MB; -} - -float psycho11_Highlights(float x, float highlights, float mid_gray) { - if (highlights == 1.f) return x; - - if (highlights > 1.f) { - return max(x, lerp(x, mid_gray * pow(x / mid_gray, highlights), min(x, 1.f))); - } else { // highlights < 1 - float b = mid_gray * pow(x / mid_gray, 2.f - highlights); - float t = min(x, 1.f); - return min(x, psycho11_DivideSafe(x * x, lerp(x, b, t), x)); - } -} - -float psycho11_Shadows(float x, float shadows, float mid_gray) { - if (shadows == 1.f) return x; - - const float ratio = max(psycho11_DivideSafe(x, mid_gray, 0.f), 0.f); - const float base_term = x * mid_gray; - const float base_scale = psycho11_DivideSafe(base_term, ratio, 0.f); - - if (shadows > 1.f) { - float raised = x * (1.f + psycho11_DivideSafe(base_term, pow(ratio, shadows), 0.f)); - float reference = x * (1.f + base_scale); - return max(x, x + (raised - reference)); - } else { // shadows < 1 - float lowered = x * (1.f - psycho11_DivideSafe(base_term, pow(ratio, 2.f - shadows), 0.f)); - float reference = x * (1.f - base_scale); - return clamp(x + (lowered - reference), 0.f, x); - } -} - -float psycho11_ContrastAndFlare( - float x, - float contrast, - float contrast_highlights, - float contrast_shadows, - float flare, - float mid_gray = 0.18f) { - if (contrast == 1.f && flare == 0.f && contrast_highlights == 1.f && contrast_shadows == 1.f) return x; - - const float x_normalized = x / mid_gray; - const float split_contrast = (x < mid_gray) ? contrast_shadows : contrast_highlights; - float flare_ratio = psycho11_DivideSafe(x_normalized + flare, x_normalized, 1.f); - float exponent = contrast * split_contrast * flare_ratio; - return pow(x_normalized, exponent) * mid_gray; -} - -float psycho11_Neutwo(float x) { - return x * rsqrt(mad(x, x, 1.f)); -} - -float psycho11_Neutwo(float x, float peak) { - return (peak * x) * rsqrt(mad(x, x, peak * peak)); -} - -float psycho11_Neutwo(float x, float peak, float clip) { - float cc = clip * clip; - float pp = peak * peak; - float xx = x * x; - float numerator = clip * peak * x; - float denominator_squared = mad(xx, (cc - pp), cc * pp); - return numerator * rsqrt(denominator_squared); -} - -// f_{mi}\left(x\right)=\frac{qzx\left(cc-gg\right)}{\sqrt{\left(cc-gg\right)\cdot\left(-xx\cdot\left(cczz-qqgg\right)+ccgg\cdot\left(qq-zz\right)\right)}}-m -float psycho11_NeutwoMin(float x, float peak, float clip, float gray_in, float gray_out, float minimum) { - float m = minimum; - float g = gray_in; - float z = gray_out - m; - float q = peak - m; - float c = clip; - - float cc = c * c; - float gg = g * g; - float cc_minus_gg = cc - gg; - - float numerator = q * z * x * cc_minus_gg; - - float xx = x * x; - float zz = z * z; - float qq = q * q; - - float cczz = cc * zz; - float qqgg = qq * gg; - float ccgg = cc * gg; - - float denominator_squared = cc_minus_gg * mad(-xx, (cczz - qqgg), ccgg * (qq - zz)); - - return mad(numerator, rsqrt(denominator_squared), -m); -} - -float3 psycho11_NeutwoPerChannel(float3 color, float3 peak) { - return float3( - psycho11_Neutwo(color.r, peak.r), - psycho11_Neutwo(color.g, peak.g), - psycho11_Neutwo(color.b, peak.b)); -} - -float3 psycho11_NeutwoPerChannel(float3 color, float3 peak, float3 clip) { - return float3( - psycho11_Neutwo(color.r, peak.r, clip.r), - psycho11_Neutwo(color.g, peak.g, clip.g), - psycho11_Neutwo(color.b, peak.b, clip.b)); -} - -float3 psycho11_NeutwoPerChannelMin(float3 color, float3 peak, float3 clip, float gray_in, float gray_out, float minimum) { - return float3( - psycho11_NeutwoMin(color.r, peak.r, clip.r, gray_in, gray_out, minimum), - psycho11_NeutwoMin(color.g, peak.g, clip.g, gray_in, gray_out, minimum), - psycho11_NeutwoMin(color.b, peak.b, clip.b, gray_in, gray_out, minimum)); -} - -float3 psycho11_NakaRushton(float3 x, float3 peak, float3 gray, float cone_response_exponent) { - float3 n = cone_response_exponent * peak / (peak - gray); - float3 x_n = psycho11_SignPow(x, n); - float3 num = peak * x_n; - float3 den = mad(pow(gray, n - 1.f), (peak - gray), x_n); - return num / den; -} - -float3 psycho11_ComputeReinhardScale(float3 peak = 1.f, float minimum = 0.f, float3 gray_in = 0.18f, float3 gray_out = 0.18f) { - // s = (p * y - p * m) / (x * p - x * y) - - float3 num = peak * (gray_out - minimum); // p * (y - m) - float3 den = gray_in * (peak - gray_out); // x * (p - y) - - return num / den; -} - -float3 psycho11_ReinhardPiecewise(float3 x, float3 x_max = 1.f, float3 shoulder = 0.18f) { - const float x_min = 0.f; - float3 exposure = psycho11_ComputeReinhardScale(x_max, x_min, shoulder, shoulder); - float3 tonemapped = mad(x, exposure, x_min) / mad(x, exposure / x_max, 1.f - x_min); - - return lerp(x, tonemapped, step(shoulder, x)); -} - -float psycho11_MBYFromLMS(float3 lms) { - return PSYCHO11_CIE1702_MB_CIE_WEIGHTS.x * lms.x + PSYCHO11_CIE1702_MB_CIE_WEIGHTS.y * lms.y; -} - -float2 psycho11_MBFromLMS(float3 lms) { - float y_mb = psycho11_MBYFromLMS(lms); - if (y_mb <= 0.f) { - return float2(0.f, 0.f); - } - - return float2( - psycho11_DivideSafe(PSYCHO11_CIE1702_MB_CIE_WEIGHTS.x * lms.x, y_mb, 0.f), - psycho11_DivideSafe(PSYCHO11_CIE1702_MB_CIE_WEIGHTS.z * lms.z, y_mb, 0.f)); -} - -float2 psycho11_MBFromBT2020Primary(float3 primary_rgb) { - float3 xyz = mul(PSYCHO11_BT2020_TO_XYZ_MAT, primary_rgb); - float3 lms = mul(PSYCHO11_XYZ_TO_STOCKMAN_SHARP_LMS_MAT, xyz); - return psycho11_MBFromLMS(lms); -} - -float psycho11_Cross2(float2 a, float2 b) { - return a.x * b.y - a.y * b.x; -} - -bool psycho11_RaySegmentHit2D(float2 origin, float2 direction, float2 a, float2 b, out float t_hit) { - const float eps = 1e-20f; - - t_hit = 0.f; - float2 e = b - a; - float denom = psycho11_Cross2(direction, e); - if (abs(denom) <= eps) return false; - - float2 ao = a - origin; - float t = psycho11_Cross2(ao, e) / denom; - float u = psycho11_Cross2(ao, direction) / denom; - if (t < 0.f || u < 0.f || u > 1.f) return false; - - t_hit = t; - return true; -} - -float psycho11_RayMaxT_BT2020TriangleInMB(float2 origin, float2 direction, out bool has_solution) { - const float interval_max = 1e30f; - const float mb_near_white_epsilon = 1e-14f; - - has_solution = false; - if (dot(direction, direction) <= mb_near_white_epsilon) return 0.f; - - float2 r = psycho11_MBFromBT2020Primary(float3(1.f, 0.f, 0.f)); - float2 g = psycho11_MBFromBT2020Primary(float3(0.f, 1.f, 0.f)); - float2 b = psycho11_MBFromBT2020Primary(float3(0.f, 0.f, 1.f)); - - float t_best = interval_max; - float t; - bool hit_any = false; - - if (psycho11_RaySegmentHit2D(origin, direction, r, g, t)) { - t_best = min(t_best, t); - hit_any = true; - } - if (psycho11_RaySegmentHit2D(origin, direction, g, b, t)) { - t_best = min(t_best, t); - hit_any = true; - } - if (psycho11_RaySegmentHit2D(origin, direction, b, r, t)) { - t_best = min(t_best, t); - hit_any = true; - } - - has_solution = hit_any; - return hit_any ? max(t_best, 0.f) : 0.f; -} - -float3 psycho11_GamutCompressAddWhiteBT2020Bounded(float3 lms) { - const float mb_near_white_epsilon = 1e-14f; - - float y_mb = psycho11_MBYFromLMS(abs(lms)); - float2 white = psycho11_WhiteD65Chromaticity(); - - float2 mb0 = psycho11_MBFromLMS(lms); - float2 direction = mb0 - white; - if (dot(direction, direction) < mb_near_white_epsilon) { - return lms; - } - - bool has_solution; - float t_max = psycho11_RayMaxT_BT2020TriangleInMB(white, direction, has_solution); - if (!has_solution) { - return lms; - } - - float white_ratio = max(psycho11_DivideSafe(1.f - t_max, t_max, 0.f), 0.f); - float white_add = y_mb * white_ratio; - float3 white_unit_lms = psycho11_LMSFromMB2(float3(white, 1.f)); - return lms + white_unit_lms * white_add; -} - -float3 psycho11_RestoreHueMB2( - float3 lms_source_raw_d65, - float3 lms_target_raw_d65, - float amount, - float eps = 1e-7f) { - if (amount <= 0.f) return lms_target_raw_d65; - - float3 mb_source = psycho11_MB2FromLMS(lms_source_raw_d65); - float3 mb_target = psycho11_MB2FromLMS(lms_target_raw_d65); - float2 mb_white = psycho11_WhiteD65Chromaticity(); - - float2 source_offset = mb_source.xy - mb_white; - float2 target_offset = mb_target.xy - mb_white; - float src2 = dot(source_offset, source_offset); - float tgt2 = dot(target_offset, target_offset); - if (src2 <= eps || tgt2 <= eps) { - return lms_target_raw_d65; - } - - float2 source_dir = source_offset * rsqrt(src2); - float2 target_dir = target_offset * rsqrt(tgt2); - float2 blended_dir = lerp(target_dir, source_dir, amount); - float blended_len2 = dot(blended_dir, blended_dir); - if (blended_len2 <= eps) { - blended_dir = target_dir; - } else { - blended_dir *= rsqrt(blended_len2); - } - - float target_radius = sqrt(tgt2); - float2 mb_restored_xy = mb_white + blended_dir * target_radius; - float3 mb_restored = float3(mb_restored_xy, mb_target.z); - return psycho11_LMSFromMB2(mb_restored); -} - -float3 psycho11_RestoreHueBT2020( - float3 bt2020_source, - float3 bt2020_target, - float amount = 1.f, - float eps = 1e-7f) { - if (amount == 0.f) return bt2020_target; - - float3 lms_target_raw_d65 = psycho11_LMSFromBT2020(bt2020_target); - - float3 lms_source_raw_d65 = psycho11_LMSFromBT2020(bt2020_source); - float3 lms_out_raw_d65 = psycho11_RestoreHueMB2( - lms_source_raw_d65, - lms_target_raw_d65, - amount, - eps); - - // Keep final output inside a BT.2020-feasible region. - lms_out_raw_d65 = psycho11_GamutCompressAddWhiteBT2020Bounded(lms_out_raw_d65); - return psycho11_BT2020FromLMS(lms_out_raw_d65); -} - -float3 psycho11_ScalePurityMB2(float3 lms_raw_d65, float purity_scale, float eps = 1e-7f) { - if (abs(purity_scale - 1.f) <= eps) return lms_raw_d65; - - float3 mb = psycho11_MB2FromLMS(lms_raw_d65); - float2 mb_white = psycho11_WhiteD65Chromaticity(); - float2 mb_offset = mb.xy - mb_white; - float2 mb_scaled = mb_white + mb_offset * purity_scale; - return psycho11_LMSFromMB2(float3(mb_scaled, mb.z)); -} - -float3 psycho11_ApplyPurityFromLMS( - float3 lms_source_raw_d65, - float3 lms_target_raw_d65, - float amount = 1.f, - float clamp_purity_loss = 0.f, - float eps = 1e-7f) { - float3 mb_source = psycho11_MB2FromLMS(lms_source_raw_d65); - float3 mb_target = psycho11_MB2FromLMS(lms_target_raw_d65); - float2 mb_white = psycho11_WhiteD65Chromaticity(); - - float2 source_offset = mb_source.xy - mb_white; - float2 target_offset = mb_target.xy - mb_white; - float src_radius = length(source_offset); - float tgt_radius = length(target_offset); - if (tgt_radius <= eps) return lms_target_raw_d65; - - float transfer_scale = src_radius / max(tgt_radius, eps); - float no_purity_loss_scale = max(transfer_scale, 1.f); - transfer_scale = lerp(transfer_scale, no_purity_loss_scale, clamp_purity_loss); - float scale = lerp(1.f, transfer_scale, amount); - float2 mb_scaled = mb_white + target_offset * scale; - return psycho11_LMSFromMB2(float3(mb_scaled, mb_target.z)); -} - -float3 psycho11_ApplyPurityFromBT2020( - float3 bt2020_source, - float3 bt2020_target, - float amount = 1.f, - float clamp_purity_loss = 0.f, - float eps = 1e-7f) { - float3 lms_target_raw_d65 = psycho11_LMSFromBT2020(bt2020_target); - float blend = amount; - - if (blend <= 0.f) { - float3 lms_bounded_target = psycho11_GamutCompressAddWhiteBT2020Bounded(lms_target_raw_d65); - return psycho11_BT2020FromLMS(lms_bounded_target); - } - - float3 lms_source_raw_d65 = psycho11_LMSFromBT2020(bt2020_source); - - float3 lms_out_raw_d65 = psycho11_ApplyPurityFromLMS( - lms_source_raw_d65, - lms_target_raw_d65, - blend, - clamp_purity_loss, - eps); - - // Keep final output inside a BT.2020-feasible region. - lms_out_raw_d65 = psycho11_GamutCompressAddWhiteBT2020Bounded(lms_out_raw_d65); - return psycho11_BT2020FromLMS(lms_out_raw_d65); -} - -namespace config { - -struct Config { - bool apply_tonemap; - float peak_value; - float exposure; - float gamma; - float highlights; - float shadows; - float contrast; - float flare; - float contrast_highlights; - float contrast_shadows; - float purity_scale; - float purity_highlights; - float adaptation_contrast; - float hue_restore; - float bleaching_intensity; - float clip_point; - float mid_gray; - bool pre_gamut_compress; - bool post_gamut_compress; -}; - -Config Create( - bool apply_tonemap = true, - float peak_value = 1000.f / 203.f, - float exposure = 1.f, - float gamma = 1.f, - float highlights = 1.f, - float shadows = 1.f, - float contrast = 1.f, - float flare = 0.f, - float contrast_highlights = 1.f, - float contrast_shadows = 1.f, - float purity_scale = 1.f, - float purity_highlights = 1.f, - float adaptation_contrast = 1.f, - float hue_restore = 1.f, - float bleaching_intensity = 0.f, - float clip_point = 100.f, - float mid_gray = 0.18f, - bool pre_gamut_compress = true, - bool post_gamut_compress = true) { - const Config cg_config = { - apply_tonemap, - peak_value, - exposure, - gamma, - highlights, - shadows, - contrast, - flare, - contrast_highlights, - contrast_shadows, - purity_scale, - purity_highlights, - adaptation_contrast, - hue_restore, - bleaching_intensity, - clip_point, - mid_gray, - pre_gamut_compress, - post_gamut_compress - }; - return cg_config; -} -} // namespace config - -float3 ApplyBT2020(float3 color_bt2020, config::Config psycho_config) { - const float kEps = 1e-7f; - - const float3 midgray_lms = psycho11_LMSFromBT2020(psycho_config.mid_gray); - - float3 color_lms_raw = psycho11_LMSFromBT2020(color_bt2020); - if (psycho_config.pre_gamut_compress) { - color_lms_raw = psycho11_GamutCompressAddWhiteBT2020Bounded(color_lms_raw); - } - - float3 color_lms = color_lms_raw; - float lum_original = renodx_custom::tonemap::psycho::psycho11_StockmanLuminanceFromLMS(color_lms_raw); - - if (psycho_config.bleaching_intensity != 0.f) { - const float kHalfBleachTrolands = 20000.f; - - float adapted_lum = max( - lum_original, - 0.18f); - float3 adapted_bt2020 = adapted_lum.xxx; - float3 lms_adapted_unit = psycho11_LMSFromBT2020(adapted_bt2020); - float3 lms_signal_unit = color_lms; - - float3 stimulus_nits = max(lms_adapted_unit, 0.f) * 100.f; - float3 stimulus_trolands = stimulus_nits * 4.f; - float3 availability_raw = 1.f / (1.f + stimulus_trolands / max(kHalfBleachTrolands, kEps)); - float3 availability = lerp(1.f, availability_raw, psycho_config.bleaching_intensity); - color_lms = lms_signal_unit * max(availability, 0.f); - } - - if (psycho_config.apply_tonemap) { // apply hue shift and blowout - // tonemap - float3 lms_peak_unit = psycho11_LMSFromBT2020(psycho_config.peak_value.xxx); - - color_lms = psycho11_ReinhardPiecewise(color_lms, lms_peak_unit, midgray_lms); - - color_lms = psycho11_RestoreHueMB2( - color_lms_raw, - color_lms, - psycho_config.hue_restore, - kEps); - - // restore original luminance - color_lms *= psycho11_DivideSafe( - lum_original, - renodx_custom::tonemap::psycho::psycho11_StockmanLuminanceFromLMS(color_lms), - 1.f); - } - - if (psycho_config.adaptation_contrast != 1.f) { - float3 source_lms = color_lms; - float3 lms_sigma_unit = max(midgray_lms, kEps.xxx); - float exponent = max(psycho_config.adaptation_contrast, kEps); - - float3 ax = abs(color_lms); - float3 ax_n = pow(ax, exponent); - float3 s_n = pow(lms_sigma_unit, exponent); - float3 response_target = ax_n / max(ax_n + s_n, kEps.xxx); - float3 response_baseline = ax / max(ax + lms_sigma_unit, kEps.xxx); - float3 gain = response_target / max(response_baseline, kEps.xxx); - float3 sign_raw = float3( - color_lms.x < 0.f ? -1.f : 1.f, - color_lms.y < 0.f ? -1.f : 1.f, - color_lms.z < 0.f ? -1.f : 1.f); - color_lms = sign_raw * (ax * gain); - - color_lms = psycho11_RestoreHueMB2( - source_lms, - color_lms, - 1.f, - kEps); - } - - if (psycho_config.exposure != 1.f - || psycho_config.gamma != 1.f - || psycho_config.highlights != 1.f - || psycho_config.shadows != 1.f - || psycho_config.contrast != 1.f - || psycho_config.contrast_highlights != 1.f - || psycho_config.contrast_shadows != 1.f - || psycho_config.flare != 0.f - || psycho_config.purity_scale != 1.f - || psycho_config.purity_highlights != 0.f) { - const float midgray_lum = psycho11_StockmanLuminanceFromLMS(midgray_lms); - float lum_target = lum_original; - - lum_target *= psycho_config.exposure; - if (psycho_config.gamma != 1.f) { - lum_target = select(lum_target < 1.f, pow(lum_target, psycho_config.gamma), lum_target); - } - - if (psycho_config.highlights != 1.f) { - lum_target = psycho11_Highlights(lum_target, psycho_config.highlights, midgray_lum); - } - - if (psycho_config.shadows != 1.f) { - lum_target = psycho11_Shadows(lum_target, psycho_config.shadows, midgray_lum); - } - - if (psycho_config.contrast != 1.f - || psycho_config.contrast_highlights != 1.f - || psycho_config.contrast_shadows != 1.f - || psycho_config.flare != 0.f) { - lum_target = psycho11_ContrastAndFlare( - lum_target, - psycho_config.contrast, - psycho_config.contrast_highlights, - psycho_config.contrast_shadows, - psycho_config.flare, - midgray_lum); - } - - float lum_scale = psycho11_DivideSafe(lum_target, lum_original, 1.f); - psycho_config.clip_point *= lum_scale; - color_lms *= lum_scale; - - float purity_scale = psycho_config.purity_scale; - - if (psycho_config.purity_highlights != 0.f) { - float percent_max = saturate(lum_target * 100.f / 10000.f); - float blowout_change = pow(1.f - percent_max, 100.f * abs(psycho_config.purity_highlights)); - if (psycho_config.purity_highlights < 0.f) { - blowout_change = 2.f - blowout_change; - } - - purity_scale *= blowout_change; - } - - if (purity_scale != 1.f) { - color_lms = psycho11_ScalePurityMB2(color_lms, purity_scale, kEps); - } - } - - if (psycho_config.post_gamut_compress) { - color_lms = psycho11_GamutCompressAddWhiteBT2020Bounded(color_lms); - } - - color_bt2020 = psycho11_BT2020FromLMS(color_lms); - - if (psycho_config.apply_tonemap) { // apply maxch tonemap - color_bt2020 = max(0, color_bt2020); - float max_channel = max(max(color_bt2020.r, color_bt2020.g), color_bt2020.b); - float new_max = psycho11_Neutwo(max_channel, psycho_config.peak_value, psycho_config.clip_point); - color_bt2020 *= psycho11_DivideSafe(new_max, max_channel, 1.f); - } - - return color_bt2020; -} - -} // namespace psycho -} // namespace tonemap -} // namespace renodx - -#endif // RENODX_SHADERS_TONEMAP_PSYCHO_TEST11_HLSL_ diff --git a/src/games/deathstranding2/tonemap/psycho_test17_custom.hlsli b/src/games/deathstranding2/tonemap/psycho_test17_custom.hlsli new file mode 100644 index 000000000..bbbe8d2c7 --- /dev/null +++ b/src/games/deathstranding2/tonemap/psycho_test17_custom.hlsli @@ -0,0 +1,1129 @@ +#include "../shared.h" +#include "./macleod_boynton.hlsli" + +#ifndef RENODX_SHADERS_TONEMAP_PSYCHO_TEST17_HLSLI_ +#define RENODX_SHADERS_TONEMAP_PSYCHO_TEST17_HLSLI_ + +namespace renodx_custom { +namespace tonemap { +namespace psycho { + +float psycho17_RayExitTCIE1702(float2 origin, float2 direction) { + return renodx::color::gamut::RayExitTCIE1702(origin, direction); +} + +float psycho17_HueRelativePuritySignalFromTClip(float t_clip) { + return saturate(renodx::math::DivideSafe(1.f, t_clip, 0.f)); +} + +float psycho17_AdaptiveHueSensitivityFromTClip(float t_clip) { + static const float kMeanD65RayDistance = 0.20139844f; + static const float kMaxD65RayDistance = 1.02634534f; + static const float kMinSensitivity = 0.35f; + + float long_ray_weight = saturate(renodx::math::DivideSafe( + t_clip - kMeanD65RayDistance, + kMaxD65RayDistance - kMeanD65RayDistance, + 0.f)); + return lerp(1.f, kMinSensitivity, long_ray_weight); +} + +float psycho17_HueRelativePuritySignalFromMB(float2 mb_xy, float2 mb_anchor) { + float2 direction = mb_xy - mb_anchor; + if (dot(direction, direction) <= renodx::color::gamut::MB_NEAR_WHITE_EPSILON) { + return 0.f; + } + + return psycho17_HueRelativePuritySignalFromTClip( + psycho17_RayExitTCIE1702(mb_anchor, direction)); +} + +float psycho17_HueRelativePuritySignalFromMB(float3 mb, float2 mb_anchor) { + if (!(mb.z > renodx::color::gamut::EPSILON)) { + return 0.f; + } + + return psycho17_HueRelativePuritySignalFromMB(mb.xy, mb_anchor); +} + +float psycho17_HueRelativePuritySignal(float3 lms_input, float2 mb_anchor) { + float3 lms_weighted = renodx::color::macleod_boynton::WeighLMS(max(lms_input, 0.f)); + float3 mb = renodx::color::macleod_boynton::from::WeightedLMS(lms_weighted); + if (!(mb.z > renodx::color::gamut::EPSILON)) { + return 0.f; + } + + return psycho17_HueRelativePuritySignalFromMB(mb, mb_anchor); +} + +float psycho17_D65HueSensitivity(float2 mb_xy) { + float2 mb_white = renodx::color::macleod_boynton::from::D65XY(); + float2 direction = mb_xy - mb_white; + if (dot(direction, direction) <= renodx::color::gamut::MB_NEAR_WHITE_EPSILON) { + return 1.f; + } + + return psycho17_AdaptiveHueSensitivityFromTClip( + psycho17_RayExitTCIE1702(mb_white, direction)); +} + +float3 psycho17_ToAdaptiveRelativeLMS(float3 lms_input, float3 current_adaptive_state_lms) { + return renodx::math::DivideSafe(lms_input, current_adaptive_state_lms, 0.f.xxx); +} + +float3 psycho17_FromAdaptiveRelativeLMS(float3 lms_relative, float3 current_adaptive_state_lms) { + return lms_relative * max(current_adaptive_state_lms, 1e-6f.xxx); +} + +float3 psycho17_ToAdaptiveRelativeWeightedLMS(float3 lms_input, float3 current_adaptive_state_lms) { + return renodx::math::DivideSafe( + renodx::color::macleod_boynton::WeighLMS(lms_input), + current_adaptive_state_lms, + 0.f.xxx); +} + +float3 psycho17_FromAdaptiveRelativeWeightedLMS( + float3 lms_weighted_relative, + float3 current_adaptive_state_lms) { + return lms_weighted_relative * max(current_adaptive_state_lms, 1e-6f.xxx); +} + +float3 psycho17_GamutCompressLMSBoundAdaptive( + float3 lms_input, + float3 current_adaptive_state_lms, + float3x3 bound_rgb_to_lms_weighted_mat, + float strength) { + float3 lms_weighted_relative = + psycho17_ToAdaptiveRelativeWeightedLMS(lms_input, current_adaptive_state_lms); + float3 lms_weighted_relative_out = + renodx::color::gamut::GamutCompressWeightedLMSCoreRGBBoundFromAdaptiveWeightedInput( + lms_weighted_relative, + current_adaptive_state_lms, + bound_rgb_to_lms_weighted_mat, + strength); + return renodx::color::macleod_boynton::UnweighLMS( + psycho17_FromAdaptiveRelativeWeightedLMS( + lms_weighted_relative_out, + current_adaptive_state_lms)); +} + +float3 psycho17_GamutCompressAdaptiveRelativeWeightedLMSBound( + float3 lms_weighted_relative_input, + float3 current_adaptive_state_lms, + float3x3 bound_rgb_to_lms_weighted_mat, + float strength) { + return renodx::color::gamut::GamutCompressWeightedLMSCoreRGBBoundFromAdaptiveWeightedInput( + lms_weighted_relative_input, + current_adaptive_state_lms, + bound_rgb_to_lms_weighted_mat, + strength); +} + +float psycho17_AdaptiveHueSensitivity(float2 mb_xy, float2 mb_anchor) { + float2 direction = mb_xy - mb_anchor; + if (dot(direction, direction) <= renodx::color::gamut::MB_NEAR_WHITE_EPSILON) { + return 1.f; + } + + return psycho17_AdaptiveHueSensitivityFromTClip( + psycho17_RayExitTCIE1702(mb_anchor, direction)); +} + +float3 psycho17_ComputeReinhardScale(float3 peak = 1.f, float minimum = 0.f, float3 gray_in = 0.18f, float3 gray_out = 0.18f) { + // s = (p * y - p * m) / (x * p - x * y) + + float3 num = peak * (gray_out - minimum); // p * (y - m) + float3 den = gray_in * (peak - gray_out); // x * (p - y) + + return num / den; +} + +float3 psycho17_ReinhardPiecewise(float3 x, float3 x_max = 1.f, float3 shoulder = 0.18f) { + const float x_min = 0.f; + float3 exposure = psycho17_ComputeReinhardScale(x_max, x_min, shoulder, shoulder); + float3 tonemapped = mad(x, exposure, x_min) / mad(x, exposure / x_max, 1.f - x_min); + + return lerp(x, tonemapped, step(shoulder, x)); +} + +float3 psycho17_ScalePurityMBAdaptive( + float3 lms_input, + float purity_scale, + float3 lms_adaptive_state, + float eps = 1e-7f) { + if (abs(purity_scale - 1.f) <= eps) return lms_input; + + float3 lms_relative = psycho17_ToAdaptiveRelativeLMS(lms_input, lms_adaptive_state); + float3 mb = renodx::color::macleod_boynton::from::LMS(lms_relative); + float2 mb_white = renodx::color::macleod_boynton::from::LMS(1.f.xxx).xy; + float2 mb_scaled = mb_white + (mb.xy - mb_white) * purity_scale; + + return psycho17_FromAdaptiveRelativeLMS( + renodx::color::lms::from::MacLeodBoynton(float3(mb_scaled, mb.z)), + lms_adaptive_state); +} + +float3 psycho17_ApplyPurityFromLMS( + float3 lms_source, + float3 lms_target, + float amount = 1.f, + float clamp_purity_loss = 0.f, + float eps = 1e-7f) { + float3 mb_source = renodx::color::macleod_boynton::from::LMS(lms_source); + float3 mb_target = renodx::color::macleod_boynton::from::LMS(lms_target); + float2 mb_white = renodx::color::macleod_boynton::from::D65XY(); + + float2 source_offset = mb_source.xy - mb_white; + float2 target_offset = mb_target.xy - mb_white; + float src_radius = length(source_offset); + float tgt_radius = length(target_offset); + if (tgt_radius <= eps) return lms_target; + + float transfer_scale = src_radius / max(tgt_radius, eps); + float no_purity_loss_scale = max(transfer_scale, 1.f); + transfer_scale = lerp(transfer_scale, no_purity_loss_scale, clamp_purity_loss); + float scale = lerp(1.f, transfer_scale, amount); + float2 mb_scaled = mb_white + target_offset * scale; + return renodx::color::lms::from::MacLeodBoynton(float3(mb_scaled, mb_target.z)); +} + +float3 psycho17_ApplyPurityFromBT2020( + float3 bt2020_source, + float3 bt2020_target, + float amount = 1.f, + float clamp_purity_loss = 0.f, + float eps = 1e-7f, + bool compress_gamut = true) { + if (amount <= 0.f) return bt2020_source; + + float3 lms_target = renodx::color::lms::from::BT2020(bt2020_target); + float3 lms_source = renodx::color::lms::from::BT2020(bt2020_source); + float3 lms_out = psycho17_ApplyPurityFromLMS( + lms_source, + lms_target, + amount, + clamp_purity_loss, + eps); + + lms_out = psycho17_GamutCompressLMSBoundAdaptive( + lms_out, + 1.f.xxx, + renodx::color::macleod_boynton::BT2020_TO_LMS_WEIGHTED_MAT, + 1.f); + return renodx::color::bt2020::from::LMS(lms_out); +} + +float3 psycho17_RestoreHueAdaptive( + float3 lms_source, + float3 lms_target, + float3 lms_adaptive_state, + float amount, + bool weight_by_purity_loss = true, + float eps = 1e-7f) { + if (amount <= 0.f) return lms_target; + + float3 lms_source_relative_weighted = psycho17_ToAdaptiveRelativeWeightedLMS( + lms_source, + lms_adaptive_state); + float3 lms_target_relative_weighted = psycho17_ToAdaptiveRelativeWeightedLMS( + lms_target, + lms_adaptive_state); + + float3 mb_source = renodx::color::macleod_boynton::from::WeightedLMS(lms_source_relative_weighted); + float3 mb_target = renodx::color::macleod_boynton::from::WeightedLMS(lms_target_relative_weighted); + float3 mb_adapted_bg = renodx::color::macleod_boynton::from::LMS(1.f.xxx); + + float2 source_offset = mb_source.xy - mb_adapted_bg.xy; + float2 target_offset = mb_target.xy - mb_adapted_bg.xy; + float src2 = dot(source_offset, source_offset); + float tgt2 = dot(target_offset, target_offset); + if (src2 <= eps || tgt2 <= eps) return lms_target; + + float target_t_clip = psycho17_RayExitTCIE1702(mb_adapted_bg.xy, target_offset); + float hue_sensitivity = psycho17_AdaptiveHueSensitivityFromTClip(target_t_clip); + float purity_loss_weight = 1.f; + if (weight_by_purity_loss) { + float source_t_clip = psycho17_RayExitTCIE1702(mb_adapted_bg.xy, source_offset); + float source_purity_signal = psycho17_HueRelativePuritySignalFromTClip(source_t_clip); + float target_purity_signal = psycho17_HueRelativePuritySignalFromTClip(target_t_clip); + purity_loss_weight = source_purity_signal > eps ? saturate(target_purity_signal / source_purity_signal) : 1.f; + } + + float restore_weight = amount * hue_sensitivity * purity_loss_weight; + if (restore_weight <= 0.f) return lms_target; + + float inv_target_radius = rsqrt(tgt2); + float target_radius = tgt2 * inv_target_radius; + float inv_source_radius = rsqrt(src2); + float2 source_dir = source_offset * inv_source_radius; + float2 target_dir = target_offset * inv_target_radius; + float2 blended_dir = lerp(target_dir, source_dir, restore_weight); + float blended_len2 = dot(blended_dir, blended_dir); + if (blended_len2 > eps) { + blended_dir *= rsqrt(blended_len2); + } else { + blended_dir = target_dir; + } + + float2 mb_restored_xy = mb_adapted_bg.xy + blended_dir * target_radius; + float3 mb_restored = float3(mb_restored_xy, mb_target.z); + float3 lms_restored_relative_weighted = renodx::color::macleod_boynton::WeightedLMSFromMacleodBoynton(mb_restored); + + return renodx::color::macleod_boynton::UnweighLMS( + psycho17_FromAdaptiveRelativeWeightedLMS( + lms_restored_relative_weighted, + lms_adaptive_state)); +} +// psychov-14 +// +// Objective: +// psychov-14 first targets the observer-side bend of the scene: +// - what state the eye adapts to, +// - how the scene is converted to contrast around that adapted state, +// - how the response is shaped around that adapted state, +// - which nonlinear curve applies at each stage. +// The human observer is not a linear gain system, so the first job of this +// test is to model how a cone/adaptation/opponent/normalization cascade bends +// scene light before any device mapping is considered. +// +// psychov-14 therefore treats the problem as two coupled but distinct systems: +// - observer flow: approximate the ordered flow of the human cone visual +// pathway with a literature-backed cascade, so each stage in the code +// corresponds to a recognizable stage in human vision rather than an +// arbitrary tone curve, +// - device-hull mapping: tonemap the observer-domain result into the display's +// luminance / gamut hull as plausibly as possible. +// Tonemapping itself remains a device-hull problem, not an eye model, but the +// observer model decides which scene differences remain perceptually important +// enough to preserve when the device hull forces compression. +// +// Intended human-flow model and supporting references: +// 1) Receptor basis: +// Stockman-Sharpe LMS with CIE 170-2 physiological luminance Yf / weighted +// LMS bookkeeping, not CIE 1931 Y. +// Reference split: +// - Brainard, "Colorimetry" (chapter 10): the cone stage / color match +// foundation. Chapter 11 explicitly points back to this chapter when it +// says "The first stage of color vision is now well understood (see +// Chap. 10)." For psychov, this is the source for step 1: +// scene RGB/XYZ -> absolute cone excitations L, M, S. +// - Stockman & Brainard (chapter 11): builds on that receptor basis for +// first-site and second-site adaptation. +// Sources: +// https://color2.psych.upenn.edu/brainard/papers/Brainard_Stockman_Colorimetry.pdf +// https://color2.psych.upenn.edu/brainard/papers/Stockman_Brainard_ColorVision.pdf +// CVRL background notes that cone signals are formed only after +// prereceptoral filtering by the ocular media and macular pigment, both of +// which absorb mainly at short wavelengths and vary substantially across +// observers. The current repo plumbing should therefore be understood as an +// average-observer receptor basis unless those filters are modeled +// explicitly. +// Reference: CVRL background hub; "Macular and lens pigments" +// (http://www.cvrl.org/background.htm, +// http://www.cvrl.org/database/text/intros/intromaclens.htm). +// MacLeod-Boynton is important here: it is not itself the cortical flow, +// but a weighted cone-chromaticity representation in an equal-luminance +// plane with a separately carried achromatic scale term. In repo notation: +// l = Lw / (Lw + Mw) +// s = Sw / (Lw + Mw) +// y = Lw + Mw +// The weights here are fixed observer-transform coefficients used to form +// weighted LMS, Yf-like achromatic response, and MB coordinates from LMS. +// They are not adaptation, gain, or bleaching terms. CVRL describes the +// CIE physiological functions as linear transformations of the Stockman & +// Sharpe cone fundamentals, and Mantiuk et al. describe a practical LMS +// scaling "so that the sum of L and M cone responses corresponds to +// luminance". That is the math role of the weights in this stage. +// Reference: MacLeod & Boynton (1979, doi:10.1364/JOSA.69.001183); modern +// CIE 170-2 implementations replace ad hoc weights with standardized +// physiological cone-fundamental / luminance weights. +// Citation split for the weights used in this file: +// - Explicit CIE 170-2 / physiological-weight usage: +// CIE / CVRL physiological functions; Psychtoolbox LMSToMacBoyn; this +// repo's stockman_macleod_boynton.hlsl wiring. +// - Classic or modified MacLeod-Boynton without an explicit CIE 170-2 +// coefficient claim: +// MacLeod & Boynton (1979); Webster & Leonard (2008). +// - LMS scaled so the achromatic term is L+M, but without an explicit +// CIE 170-2 MacLeod-Boynton coefficient claim: +// Mantiuk et al. (2020). +// So classic MB, modified MB, and plain L+M-scaled LMS should not be cited +// as if they automatically justify the exact CIE 170-2 coefficients used +// here. +// Sources: +// http://www.cvrl.org/ciexyzpr.htm +// https://psychtoolbox.org/docs/LMSToMacBoyn +// https://pmc.ncbi.nlm.nih.gov/articles/PMC2657039/ +// https://www.cl.cam.ac.uk/~rkm38/pdfs/mantiuk2020practical_csf.pdf +// 2) Early cone adaptation: +// Maintain an adapting background state (L0, M0, S0, Yf0), then express the +// stimulus relative to that background before any postreceptoral transform. +// Chapter split: +// - chapter 10 gives the absolute cone excitations, +// - chapter 11 then defines how those cone excitations depend on the +// adapting background and are converted to a contrast representation. +// Source-backed first-site math is cone-specific contrast / gain control, +// not a rule that every adapted background is mapped to one fixed output +// level. Stockman & Brainard write the first-site cone contrast for the +// L-cone as: +// C_L = ΔL / (L_b + L_0) +// with analogous forms for M and S. Equivalently, a background-dependent +// gain g_L = 1 / (L_b + L_0) acts on the increment: +// g_L * (L - L_b) = ΔL / (L_b + L_0) +// Thus the observer is approximately normalizing cone signals by the +// adapted background, not forcing all backgrounds to one arbitrary response +// value. First-site adaptation is also not complete or instantaneous, and +// later second-site adaptation further reshapes postreceptoral signals. +// References: Stockman & Brainard (2010); Stockman et al. (JOV 2006, +// doi:10.1167/6.11.5). +// Webster & Leonard (2008) add an important structural point, but their +// terms need to stay separate. Their "response norm" is the adapting level +// that does not bias white judgments, while their "perceptual norm" is the +// stimulus that appears white. Those psychophysical norms tracked each +// other closely in their experiments, but they are not the same term as the +// background cone excitations L_b / M_b / S_b in Stockman & Brainard or +// the background responses L0 / M0 / S0 in Mantiuk et al. For psychov, the +// directly modeled early state is therefore best named the adapted +// background reference (L0, M0, S0, optional Yf0), while Webster's +// response-norm / perceptual-norm language remains useful as higher-level +// interpretation of why that adapted reference acts as the current neutral +// coding state. Webster & Leonard also argue that steady uniform-field +// chromatic adaptation appeared to arise largely at early stages affected +// by adaptation. +// Source: +// https://pmc.ncbi.nlm.nih.gov/articles/PMC2657039/ +// CVRL further notes that luminosity functions are strongly dependent on +// chromatic adaptation and observing conditions, whereas cone spectral +// sensitivities remain fixed until photopigment bleaching becomes +// significant. That is the reason to keep Yf / luminosity bookkeeping tied +// to the adapted observer state rather than treating a single photometric Y +// curve as condition-invariant. +// Reference: CVRL "Luminosity functions" +// (http://www.cvrl.org/database/text/intros/introvl.htm). +// 2a) Dim cone-noise regime: +// Before true rod-dominated vision, cone-mediated detection can already be +// limited by quantal / transduction noise. In this dim-but-still-cone +// regime, threshold cone contrast follows approximately De Vries-Rose +// behavior: in log-log space, threshold contrast decreases with retinal +// illuminance with slope near -0.5. At higher light levels the system moves +// toward Weber-like behavior, where threshold contrast is roughly constant +// relative to the adapted background. This matters for psychov because +// weak scene differences can disappear into a cone-noise-limited threshold +// floor before rod vision becomes dominant. +// Reference direction: +// - Stockman & Brainard (2010): cone-contrast space is most useful when +// first-site adaptation is in the Weber regime, and less useful when +// adaptation falls short of Weber's law at lower levels. +// - Angueyra & Rieke (2013): primate cone photoreceptors exhibit measurable +// phototransduction noise, giving a photoreceptor-level source for the +// dim-light threshold floor. +// Sources: +// https://color2.psych.upenn.edu/brainard/papers/Stockman_Brainard_ColorVision.pdf +// https://pmc.ncbi.nlm.nih.gov/articles/PMC3815624/ +// 2b) High-light bleaching: +// At sufficiently high retinal illuminance, reduce per-cone pigment +// availability with a Rushton-Henry-style law in trolands: +// p(I) = 1 / (1 + I / I0) +// This is the complementary "available pigment" form of the more commonly +// cited fraction-bleached law: +// p_bleached(I) = I / (I + I0) +// with I0 ~ 10^4.3 Td for cones. +// Then apply that availability to cone excursions around an adapted white +// anchor. In the current repo bleaching helper this is implemented as +// per-cone attenuation of LMS deltas around a white-at-achromatic-level +// anchor, so availability -> 0 drives the response toward equal white at the +// same carried achromatic level. That is the desired "intensely bright tends +// to bleach to white" behavior for this test. +// Source and attribution: +// - Stockman et al. (JOV 2006, doi:10.1167/6.11.5): high-light sensitivity +// regulation is maintained mainly by photopigment bleaching. +// - Stockman et al. (JOV 2018, 18(6):12): appendix states the steady-state +// bleaching law p = I / (I + I0), I0 = 10^4.3 Td, citing Rushton & Henry +// (1968). +// - CVRL "Bleaching": bleaching reduces effective pigment concentration and +// narrows spectral sensitivity without changing lambda_max; in cones this +// matters enough to affect chromatic adaptation and color matching, so a +// pure scalar availability model is only a first-order approximation. +// (http://www.cvrl.org/database/text/intros/introbleaches.htm) +// - The final white-relative application used here is the repo's rendering +// interpretation of that availability law for color signals; see +// color/bleaching.hlsl for the exact helper. +// Placement in the overall flow: +// - bleaching belongs inside the observer model, +// - after the adapting background state is defined, +// - before postreceptoral opponent encoding and pooled cortical gain, +// - and therefore before any device-hull tonemapping / gamut compression. +// 3) Background-normalized opponent drive: +// Convert cone-domain responses into ACC / DKL-style opponent coordinates +// using a background-referenced, weighted-LMS achromatic axis. +// Reference direction: derive postreceptoral opponent coordinates from the +// adapted cone-domain state and keep this stage clearly separated from the +// receptor / adaptation math above. +// Important distinction: MacLeod-Boynton describes chromaticity on the +// equal-luminance plane, while ACC / DKL are opponent combinations of cone +// increments around a background. MB is therefore the right place to carry +// hue / gamut geometry and achromatic Yf bookkeeping; ACC / DKL is the +// better place to describe postreceptoral opponent response and gain. +// 4) Saturating contrast response: +// Use a Michaelis-Menten / Naka-Rushton-like nonlinearity for receptor or +// early cortical contrast response. A supersaturating variant may be needed +// later for some cortical fits. +// Reference: Peirce (JOV 2007, doi:10.1167/7.6.13). +// 5) ON/OFF separation: +// Split increments and decrements with half-wave rectification before the +// pooled gain stage. +// Reference: Schiller (1992). +// 6) Pooled cortical gain: +// Apply divisive normalization, potentially with energy-like pooling across +// achromatic and chromatic channels. +// Reference: Heeger (1992); Carandini & Heeger (2012); Bun & Horwitz +// (2023); Li et al. (2022). +// 7) Device-hull tonemapping / gamut mapping: +// Map the observer-domain result into the display hull in a space that keeps +// enough achromatic and chromatic contrast / JND energy to preserve the +// scene plausibly on the target device. White is one valid attractor when +// bleaching or the achromatic optimum dominates, but it is not the only +// valid out-of-hull destination. +// Inference for RGB display hulls: +// - many device hulls can produce more total achromatic output by combining +// primaries than they can produce at the same brightness with a high-purity +// chromatic excursion, +// - therefore an out-of-hull observer response may need to trade chromatic +// shape / purity toward the achromatic axis if that is what the device +// hull allows, +// - the preferred mapping is not blind clipping to white, but the in-hull +// point that preserves the most plausible observer-domain contrast energy. +// Engineering direction inferred from the sources above: +// - use MB / weighted-LMS to carry achromatic Yf and hue geometry, +// - use ACC / opponent space to judge postreceptoral contrast structure, +// - construct or project to a display hull in that combined space rather +// than clipping in RGB. +// Coupling constraint: +// - hue preservation and device-hull compression are not independent steps, +// - a hue change applied after hull compression can push the result back out +// of the device hull, +// - therefore hue-preserving motion should either be solved inside the hull +// projection itself or followed by another explicit in-hull reprojection. +// Reference direction: MacLeod-Boynton / CIE 170-2 geometry; +// repo weighted-LMS / MB geometry plus the device-hull notes above. +// 7a) Optional hue model inside the device-hull solve: +// If gamut compression or display desaturation bends hue in a way that +// looks wrong, the hull solve can preserve hue by an "equivalent Gaussian +// peak" proxy rather than by preserving a raw opponent angle. The idea is +// that at short and medium wavelengths, perceived hue can behave more like a +// constant spectral peak of an equivalent Gaussian than a constant cone +// ratio when purity changes. +// Practical form: +// - offline, map weighted LMS / MB chromaticities to an equivalent Gaussian +// peak parameter mu_eq using a spectral forward model, +// - online, preserve mu_eq during gamut compression / display mapping while +// carrying Yf separately, +// - do not apply an unconstrained post-hoc hue shift after final hull +// compression unless the result is reprojected back into the device hull. +// This is not a separate chronological eye stage after stage 7. It is an +// optional hue objective used inside the device-hull mapping stage. +// Reference: Mizokami et al. (JOV 2006, doi:10.1167/6.9.12); +// O'Neil et al. (JOSAA 2012, doi:10.1364/JOSAA.29.00A165). +// +// Mermaid source map of planned psychov inputs, derived states, and outputs: +// ```mermaid +// flowchart TB +// classDef raw fill:#223041,stroke:#7aa2d2,color:#e8f0ff +// classDef func fill:#3c2a4d,stroke:#b48ef7,color:#f5ecff +// classDef state fill:#294436,stroke:#77c79a,color:#effff5 +// classDef out fill:#5a3a1f,stroke:#f2bc6b,color:#fff6e8 +// +// subgraph inputs["Raw inputs / assumptions"] +// direction TB +// rgb["Scene-linear R / G / B"]:::raw +// src_color["Source colorimetry\nprimaries + white + RGB->XYZ/LMS"]:::raw +// abs_scale["Absolute scene scale\nscene-linear -> nits"]:::raw +// local_bg["Adaptation drivers\nrolling average + local background"]:::raw +// scene_range["Late image context\nluminance range / percentile span"]:::raw +// retinal["Retinal context\npupil area + trolands"]:::raw +// observer_basis["Observer basis assumptions\nStockman/CVRL LMS + lens/macula"]:::raw +// display["Display/device context\nprimaries + white + peak + black + hull"]:::raw +// end +// +// subgraph pipeline["Observer pipeline"] +// direction TB +// src_to_lms["RGB -> receptor LMS"]:::func +// abs_lms["Absolute cone-energy state\nL, M, S"]:::state +// adapt_fn["Estimate adapted background reference"]:::func +// adapt["Adapted background reference\nL0, M0, S0, optional Yf0"]:::state +// cone_contrast_fn["Form per-cone background-relative signal"]:::func +// cone_contrast["Per-cone contrast state\nDeltaL/(Lb+L0), DeltaM/(Mb+M0), DeltaS/(Sb+S0)"]:::state +// bleach_fn["Apply per-cone bleaching availability"]:::func +// bleach["Bleaching availability state"]:::state +// cone_nl_fn["Apply per-cone Naka-Rushton"]:::func +// cone_nl["Per-cone nonlinear response"]:::state +// noise_fn["Apply dim cone-noise threshold"]:::func +// noise_floor["Visibility-limited cone response"]:::state +// weighted_basis_fn["Optional weighted LMS / Yf / MB transform"]:::func +// weighted_basis["Observer-summary basis state"]:::state +// opponent_fn["Recombine to opponent / achromatic channels"]:::func +// opponent["Opponent / achromatic response"]:::state +// onoff_fn["Split ON / OFF pathways"]:::func +// onoff["ON / OFF responses"]:::state +// late_gain_fn["Apply late polarity / range gain"]:::func +// late_gain["Late polarity / range-gated response"]:::state +// pool_fn["Apply pooling / divisive normalization"]:::func +// pooled["Pooled / normalized response"]:::state +// observer_out["Observer-domain response"]:::state +// end +// +// subgraph device_map["Device-hull mapping"] +// direction TB +// hue_obj_fn["Optional hue objective\nMB / ACC / mu_eq"]:::func +// hue_obj["Hue-preserving objective state"]:::state +// hull_fn["Solve device-hull tone + gamut mapping"]:::func +// hull["Display-hull output"]:::out +// end +// +// rgb --> src_to_lms +// src_color --> src_to_lms +// observer_basis --> src_to_lms +// src_to_lms --> abs_lms +// abs_scale --> abs_lms +// +// abs_lms --> adapt_fn --> adapt +// local_bg --> adapt_fn +// retinal --> adapt_fn +// +// abs_lms --> cone_contrast_fn --> cone_contrast +// adapt --> cone_contrast_fn +// +// abs_lms --> bleach_fn --> bleach +// adapt --> bleach_fn +// retinal --> bleach_fn +// +// cone_contrast --> cone_nl_fn --> cone_nl +// bleach --> cone_nl_fn +// +// cone_nl --> noise_fn --> noise_floor +// retinal --> noise_fn +// +// cone_nl --> weighted_basis_fn --> weighted_basis +// +// noise_floor --> opponent_fn --> opponent +// weighted_basis --> opponent_fn +// adapt --> opponent_fn +// +// opponent --> onoff_fn --> onoff +// onoff --> late_gain_fn --> late_gain +// scene_range --> late_gain_fn +// late_gain --> pool_fn --> pooled --> observer_out +// +// observer_out --> hue_obj_fn --> hue_obj +// observer_out --> hull_fn +// hue_obj --> hull_fn +// display --> hull_fn +// hull_fn --> hull +// ``` +// +// Current implementation status: +// - This file currently implements the stage-3 to stage-6 scaffold plus a +// first-pass receptor front end: +// absolute Stockman LMS -> explicit adapted background reference input -> +// per-cone bleaching availability -> local receptor Naka-Rushton -> +// cone-contrast coding -> weighted-LMS ACC placeholder. +// - The full planned early-cone model is still incomplete: +// rolling scene / local surround adaptation plumbing and dim-light noise +// thresholding are not wired into test14 yet. +// - The device-hull tonemapping stage is also not wired into test14 yet. +// - The intended receptor basis should be read as an average-observer, mainly +// foveal Stockman / CVRL basis with prereceptoral lens and macular filtering +// already folded into the standard functions, not a personalized observer +// model with explicit lens / macular / eccentricity variation. +// - The adapted background is now an explicit input with a default +// diffuse-gray proxy, but the caller still needs to supply a real rolling +// scene / local surround estimate before this can count as a complete +// adaptation model. +// - The scalar defaults below are unit-normalized test settings and are not +// yet fitted to a specific physiology dataset. +// - The optional Abney / equivalent-Gaussian hue stage is not implemented yet; +// if used later, it should be bounded because the Gaussian account works best +// at short and medium wavelengths and breaks down toward yellow / red. +// +// Secondary seminar notes (useful framing, not primary citation): +// - "Bright lights ... bleach the cones" and make them less sensitive, with +// slow recovery. This supports the placement of bleaching in the observer +// model before device mapping. +// - "Gamut ... is the technical container." This supports treating tonemapping +// as a device-hull problem distinct from the eye model. +// - Diffuse white and peak luminance were discussed separately, which supports +// keeping display white / diffuse white as explicit anchors in the hull solve. +// Source: "Mythbusting: Colour, Camera, Cinema" (Colorist Society, +// Camerimage 2024 panel with Andrew Stockman / Charles Poynton / Dirk Meier), +// YouTube transcript dated January 13, 2025. +// Ordered summary: +// scene RGB +// -> absolute Stockman LMS (chapter 10 receptor basis) +// -> early cone adaptation (chapter 11 first-site background L0/M0/S0/Yf0) +// -> high-light bleaching +// -> opponent drive +// -> saturating response / ON-OFF / pooled gain +// -> observer-domain result +// -> device-hull mapping +float3 psychotm_test17( + float3 bt709_linear_input, + float peak_value = 1000.f / 203.f, + float exposure = 1.f, + float highlights = 1.f, + float shadows = 1.f, + float contrast = 1.f, + float purity_scale = 1.f, + float bleaching_intensity = 1.f, + float clip_point = 100.f, + float hue_restore = 1.f, + float adaptation_contrast = 1.f, + int white_curve_mode = 0, + float cone_response_exponent = 1.f, + float3 current_adaptive_state_bt709 = 0.18f, + float3 current_background_state_bt709 = 0.18f, + float gamut_compression = 1.f, + int gamut_compression_mode = 1, + float adaptive_normalization = 1.f) { + float3 bt709_scene = bt709_linear_input * exposure; + + float3 lms_in = renodx::color::lms::from::BT709(bt709_scene); + float3 lms_peak = renodx::color::lms::from::BT709(float(peak_value).xxx); + float3 current_adaptive_state_lms = renodx::color::lms::from::BT709(current_adaptive_state_bt709); + float3 desired_background_state_lms = renodx::color::lms::from::BT709(current_background_state_bt709); + float3 lms_working = lms_in; + if (true) { + // noop + } else if (gamut_compression == 0) { + lms_working = psycho17_GamutCompressLMSBoundAdaptive( + lms_in, + current_adaptive_state_lms, + renodx::color::macleod_boynton::LMS_TO_LMS_WEIGHTED_MAT, + 1.f); + } else if (gamut_compression_mode == 0) { + lms_working = psycho17_GamutCompressLMSBoundAdaptive( + lms_in, + current_adaptive_state_lms, + renodx::color::macleod_boynton::BT709_TO_LMS_WEIGHTED_MAT, + 1.f); + } else { + lms_working = psycho17_GamutCompressLMSBoundAdaptive( + lms_in, + current_adaptive_state_lms, + renodx::color::macleod_boynton::BT2020_TO_LMS_WEIGHTED_MAT, + 1.f); + } + + float yf_input = renodx::color::yf::from::LMS(lms_working); + float yf_midgray = renodx::color::yf::from::BT709(0.18f); + float yf_target = yf_input; + + // Stage 1: apply UI highlight/shadow/contrast controls in luminosity space. + if (highlights != 1.f) { + yf_target = renodx::color::grade::Highlights(yf_target, highlights, yf_midgray); + } + if (shadows != 1.f) { + yf_target = renodx::color::grade::Shadows(yf_target, shadows, yf_midgray); + } + if (contrast != 1.f) { + yf_target = renodx::color::grade::ContrastSafe(yf_target, contrast, yf_midgray); + } + + float yf_scale = renodx::math::DivideSafe(yf_target, yf_input, 1.f); + + float3 lms_graded = lms_working * yf_scale; + if (purity_scale != 1.f) { + float3 lms_graded_relative = psycho17_ToAdaptiveRelativeLMS( + lms_graded, + current_adaptive_state_lms); + float3 mb = renodx::color::macleod_boynton::from::LMS(lms_graded_relative); + float2 mb_white = renodx::color::macleod_boynton::from::LMS(1.f.xxx).xy; + float2 mb_scaled = lerp(mb_white, mb.xy, purity_scale); + lms_graded = psycho17_FromAdaptiveRelativeLMS( + renodx::color::lms::from::MacLeodBoynton(float3(mb_scaled, mb.z)), + current_adaptive_state_lms); + } + + float3 lms_cones = lms_graded; + + // if (bleaching_intensity != 0.f) { + // float3 availability = 1.f.xxx / (1.f.xxx + (peak_value / current_adaptive_state_lms)); + // availability = lerp(1.f.xxx, availability, bleaching_intensity); + + // float input_energy = lms_cones.x + lms_cones.y + lms_cones.z; + // float white_y = current_adaptive_state_lms.x + current_adaptive_state_lms.y + current_adaptive_state_lms.z; + // float3 white_at_y = current_adaptive_state_lms * (input_energy / white_y); + // float3 delta = (lms_cones - white_at_y) * availability; + // lms_cones = max(0, white_at_y + delta); + // } + + // Naka-Rushton is scale-equivariant if input, peak, and anchors are all + // normalized by the same adaptive LMS state, so keep the absolute-LMS form. + float3 display_scaled = renodx::tonemap::NakaRushton( + lms_cones, + lms_peak, + current_adaptive_state_lms, + desired_background_state_lms, + cone_response_exponent); + float3 display_scaled_relative_weighted = psycho17_ToAdaptiveRelativeWeightedLMS( + display_scaled, + current_adaptive_state_lms); + + if (hue_restore > 0.f) { + float3 lms_cones_relative_weighted = psycho17_ToAdaptiveRelativeWeightedLMS( + lms_cones, + current_adaptive_state_lms); + float3 mb_source = + renodx::color::macleod_boynton::from::WeightedLMS(lms_cones_relative_weighted); + float3 mb_display_target = + renodx::color::macleod_boynton::from::WeightedLMS(display_scaled_relative_weighted); + float3 mb_adapted_bg = renodx::color::macleod_boynton::from::LMS(1.f.xxx); + + float2 source_offset = mb_source.xy - mb_adapted_bg.xy; + float2 display_target_offset = mb_display_target.xy - mb_adapted_bg.xy; + float src2 = dot(source_offset, source_offset); + float display_tgt2 = dot(display_target_offset, display_target_offset); + if (src2 > 1e-7 && display_tgt2 > 1e-7) { + float inv_target_radius = rsqrt(display_tgt2); + float target_radius = display_tgt2 * inv_target_radius; + float source_t_clip = psycho17_RayExitTCIE1702(mb_adapted_bg.xy, source_offset); + float display_t_clip = psycho17_RayExitTCIE1702(mb_adapted_bg.xy, display_target_offset); + // Scale hue restoration by purity loss relative to the adapted neutral anchor. + float source_purity_signal = psycho17_HueRelativePuritySignalFromTClip(source_t_clip); + float display_purity_signal = psycho17_HueRelativePuritySignalFromTClip(display_t_clip); + float purity_signal_loss = saturate(display_purity_signal / source_purity_signal); + float hue_sensitivity = psycho17_AdaptiveHueSensitivityFromTClip(display_t_clip); + float restore_weight = 1.f * hue_sensitivity * hue_restore * purity_signal_loss; + if (restore_weight > 0.f) { + float inv_source_radius = rsqrt(src2); + float2 source_dir = source_offset * inv_source_radius; + float2 display_target_dir = display_target_offset * inv_target_radius; + float2 blended_dir = lerp(display_target_dir, source_dir, restore_weight); + float blended_len2 = dot(blended_dir, blended_dir); + if (blended_len2 > 1e-7) { + blended_dir *= rsqrt(blended_len2); + } else { + blended_dir = display_target_dir; + } + + // Keep display-scaled chroma radius and y_MB; only replace hue direction. + float2 mb_restored_xy = mb_adapted_bg.xy + blended_dir * target_radius; + float3 mb_restored = float3(mb_restored_xy, mb_display_target.z); + display_scaled_relative_weighted = + renodx::color::macleod_boynton::WeightedLMSFromMacleodBoynton(mb_restored); + } + } + } + + if (gamut_compression != 0.f) { + if (gamut_compression_mode == 0) { + display_scaled_relative_weighted = psycho17_GamutCompressAdaptiveRelativeWeightedLMSBound( + display_scaled_relative_weighted, + current_adaptive_state_lms, + renodx::color::macleod_boynton::BT709_TO_LMS_WEIGHTED_MAT, + gamut_compression); + } else if (gamut_compression_mode == 1) { + display_scaled_relative_weighted = psycho17_GamutCompressAdaptiveRelativeWeightedLMSBound( + display_scaled_relative_weighted, + current_adaptive_state_lms, + renodx::color::macleod_boynton::BT2020_TO_LMS_WEIGHTED_MAT, + gamut_compression); + } + } + // Scale back from first-site adaptation; + float3 final_bt709 = renodx::color::bt709::from::LMS( + renodx::color::macleod_boynton::UnweighLMS( + psycho17_FromAdaptiveRelativeWeightedLMS( + display_scaled_relative_weighted, + current_adaptive_state_lms))); + return final_bt709; +} + +float psycho17_Highlights(float x, float highlights, float mid_gray) { + if (highlights == 1.f) return x; + + if (highlights > 1.f) { + return max(x, lerp(x, mid_gray * pow(x / mid_gray, highlights), min(x, 1.f))); + } else { // highlights < 1 + float b = mid_gray * pow(x / mid_gray, 2.f - highlights); + float t = min(x, 1.f); + return min(x, renodx::math::DivideSafe(x * x, lerp(x, b, t), x)); + } +} + +float psycho17_Shadows(float x, float shadows, float mid_gray) { + if (shadows == 1.f) return x; + + const float ratio = max(renodx::math::DivideSafe(x, mid_gray, 0.f), 0.f); + const float base_term = x * mid_gray; + const float base_scale = renodx::math::DivideSafe(base_term, ratio, 0.f); + + if (shadows > 1.f) { + float raised = x * (1.f + renodx::math::DivideSafe(base_term, pow(ratio, shadows), 0.f)); + float reference = x * (1.f + base_scale); + return max(x, x + (raised - reference)); + } else { // shadows < 1 + float lowered = x * (1.f - renodx::math::DivideSafe(base_term, pow(ratio, 2.f - shadows), 0.f)); + float reference = x * (1.f - base_scale); + return clamp(x + (lowered - reference), 0.f, x); + } +} + +float psycho17_ContrastAndFlare( + float x, + float contrast, + float contrast_highlights, + float contrast_shadows, + float flare, + float mid_gray = 0.18f) { + if (contrast == 1.f && flare == 0.f && contrast_highlights == 1.f && contrast_shadows == 1.f) return x; + + const float x_normalized = x / mid_gray; + const float split_contrast = (x < mid_gray) ? contrast_shadows : contrast_highlights; + float flare_ratio = renodx::math::DivideSafe(x_normalized + flare, x_normalized, 1.f); + float exponent = contrast * split_contrast * flare_ratio; + return pow(x_normalized, exponent) * mid_gray; +} + +namespace config17 { + +struct Config { + bool apply_tonemap; + float peak_value; + float exposure; + float gamma; + float highlights; + float shadows; + float contrast; + float flare; + float contrast_highlights; + float contrast_shadows; + float purity_scale; + float purity_highlights; + float dechroma; + float adaptation_contrast; + float bleaching_intensity; + float clip_point; + float mid_gray; + bool pre_gamut_compress; + bool post_gamut_compress; + float hue_emulation; +}; + +Config Create( + bool apply_tonemap = true, + float peak_value = 1000.f / 203.f, + float exposure = 1.f, + float gamma = 1.f, + float highlights = 1.f, + float shadows = 1.f, + float contrast = 1.f, + float flare = 0.f, + float contrast_highlights = 1.f, + float contrast_shadows = 1.f, + float purity_scale = 1.f, + float purity_highlights = 1.f, + float dechroma = 0.f, + float adaptation_contrast = 1.f, + float bleaching_intensity = 0.f, + float clip_point = 100.f, + float mid_gray = 0.18f, + bool pre_gamut_compress = true, + bool post_gamut_compress = true, + float hue_emulation = 0.f) { + const Config psycho17_config = { + apply_tonemap, + peak_value, + exposure, + gamma, + highlights, + shadows, + contrast, + flare, + contrast_highlights, + contrast_shadows, + purity_scale, + purity_highlights, + dechroma, + adaptation_contrast, + bleaching_intensity, + clip_point, + mid_gray, + pre_gamut_compress, + post_gamut_compress, + hue_emulation + }; + return psycho17_config; +} + +} // namespace config17 + +float3 ApplyTest17BT2020(float3 color_bt2020, float3 color_hue_shift_source_bt2020, config17::Config psycho_config) { + const float kEps = 1e-7f; + float clip_point = psycho_config.clip_point; + + float3 midgray_lms = renodx::color::lms::from::BT2020(psycho_config.mid_gray.xxx); + + float3 color_lms_raw = renodx::color::lms::from::BT2020(color_bt2020); + if (psycho_config.pre_gamut_compress) { + color_lms_raw = psycho17_GamutCompressLMSBoundAdaptive( + color_lms_raw, + midgray_lms, + renodx::color::macleod_boynton::BT2020_TO_LMS_WEIGHTED_MAT, + 1.f); + } + + float3 color_lms = color_lms_raw; + float lum_original = renodx::color::yf::from::LMS(color_lms_raw); + + if (psycho_config.bleaching_intensity != 0.f) { + const float kHalfBleachTrolands = 20000.f; + + float adapted_lum = max(lum_original, psycho_config.mid_gray); + float3 lms_adapted_unit = renodx::color::lms::from::BT2020(adapted_lum.xxx); + float3 lms_signal_unit = color_lms; + + float3 stimulus_nits = max(lms_adapted_unit, 0.f) * 100.f; + float3 stimulus_trolands = stimulus_nits * 4.f; + float3 availability_raw = 1.f / (1.f + stimulus_trolands / max(kHalfBleachTrolands, kEps)); + float3 availability = lerp(1.f, availability_raw, psycho_config.bleaching_intensity); + color_lms = lms_signal_unit * max(availability, 0.f); + } + + if (psycho_config.apply_tonemap) { + float3 lms_peak_unit = renodx::color::lms::from::BT2020(psycho_config.peak_value.xxx); + color_lms = psycho17_ReinhardPiecewise(color_lms, lms_peak_unit, midgray_lms); + + // adaptive hue restore not needed + // color_lms = psycho17_RestoreHueAdaptive( + // color_lms_raw, + // color_lms, + // midgray_lms, + // psycho_config.hue_restore, + // kEps); + + color_lms *= renodx::math::DivideSafe( + lum_original, + renodx::color::yf::from::LMS(color_lms), + 1.f); + } + + if (psycho_config.adaptation_contrast != 1.f || psycho_config.hue_emulation != 0.f) { + float3 source_lms = color_lms; + if (psycho_config.adaptation_contrast != 1.f) { + float3 lms_sigma_unit = max(midgray_lms, kEps.xxx); + float exponent = max(psycho_config.adaptation_contrast, kEps); + + float3 ax = abs(color_lms); + float3 ax_n = pow(ax, exponent); + float3 s_n = pow(lms_sigma_unit, exponent); + float3 response_target = ax_n / max(ax_n + s_n, kEps.xxx); + float3 response_baseline = ax / max(ax + lms_sigma_unit, kEps.xxx); + float3 gain = response_target / max(response_baseline, kEps.xxx); + float3 sign_raw = float3( + color_lms.x < 0.f ? -1.f : 1.f, + color_lms.y < 0.f ? -1.f : 1.f, + color_lms.z < 0.f ? -1.f : 1.f); + color_lms = sign_raw * (ax * gain); + } + + if (psycho_config.hue_emulation != 0.f) { + source_lms = lerp(source_lms, renodx::color::lms::from::BT2020(color_hue_shift_source_bt2020), psycho_config.hue_emulation); + } + + color_lms = psycho17_RestoreHueAdaptive( + source_lms, + color_lms, + midgray_lms, + 1.f, + false); + } + + if (psycho_config.exposure != 1.f + || psycho_config.gamma != 1.f + || psycho_config.highlights != 1.f + || psycho_config.shadows != 1.f + || psycho_config.contrast != 1.f + || psycho_config.contrast_highlights != 1.f + || psycho_config.contrast_shadows != 1.f + || psycho_config.flare != 0.f + || psycho_config.purity_scale != 1.f + || psycho_config.dechroma != 0.f + || psycho_config.purity_highlights != 0.f) { + float midgray_lum = renodx::color::yf::from::LMS(midgray_lms); + float lum_target = lum_original; + + lum_target *= psycho_config.exposure; + if (psycho_config.gamma != 1.f) { + lum_target = select(lum_target < 1.f, pow(lum_target, psycho_config.gamma), lum_target); + } + + if (psycho_config.highlights != 1.f) { + lum_target = psycho17_Highlights(lum_target, psycho_config.highlights, midgray_lum); + } + + if (psycho_config.shadows != 1.f) { + lum_target = psycho17_Shadows(lum_target, psycho_config.shadows, midgray_lum); + } + + if (psycho_config.contrast != 1.f + || psycho_config.contrast_highlights != 1.f + || psycho_config.contrast_shadows != 1.f + || psycho_config.flare != 0.f) { + lum_target = psycho17_ContrastAndFlare( + lum_target, + psycho_config.contrast, + psycho_config.contrast_highlights, + psycho_config.contrast_shadows, + psycho_config.flare, + midgray_lum); + } + + float lum_scale = renodx::math::DivideSafe(lum_target, lum_original, 1.f); + clip_point *= lum_scale; + color_lms *= lum_scale; + + float purity_scale = psycho_config.purity_scale; + + if (psycho_config.dechroma != 0.f) { + purity_scale *= lerp(1.f, 0.f, saturate(pow(lum_target / (10000.f / 100.f), (1.f - psycho_config.dechroma)))); + } + + if (psycho_config.purity_highlights != 0.f) { + float percent_max = saturate(lum_target * 100.f / 10000.f); + float blowout_change = pow(1.f - percent_max, 100.f * abs(psycho_config.purity_highlights)); + if (psycho_config.purity_highlights < 0.f) { + blowout_change = 2.f - blowout_change; + } + purity_scale *= blowout_change; + } + + if (purity_scale != 1.f) { + color_lms = psycho17_ScalePurityMBAdaptive(color_lms, purity_scale, midgray_lms, kEps); + } + } + + if (psycho_config.post_gamut_compress) { + color_lms = psycho17_GamutCompressLMSBoundAdaptive( + color_lms, + midgray_lms, + renodx::color::macleod_boynton::BT2020_TO_LMS_WEIGHTED_MAT, + 1.f); + } + + color_bt2020 = renodx::color::bt2020::from::LMS(color_lms); + + if (psycho_config.apply_tonemap) { + color_bt2020 = renodx::tonemap::neutwo::MaxChannel( + max(color_bt2020, 0.f.xxx), + psycho_config.peak_value, + clip_point); + } + + return color_bt2020; +} + +} // namespace psycho +} // namespace tonemap +} // namespace renodx + +#endif // RENODX_SHADERS_TONEMAP_PSYCHO_TEST17_HLSLI_ diff --git a/src/games/deathstranding2/tonemap/tonemap.hlsli b/src/games/deathstranding2/tonemap/tonemap.hlsli index adf642b6a..b0684bcaa 100644 --- a/src/games/deathstranding2/tonemap/tonemap.hlsli +++ b/src/games/deathstranding2/tonemap/tonemap.hlsli @@ -1,18 +1,18 @@ #include "../common.hlsli" -#include "./psycho_test11.hlsli" +#include "./psycho_test17_custom.hlsli" float3 ApplyGammaCorrectionForToneMap(float3 color_input) { float3 color_corrected; if (RENODX_GAMMA_CORRECTION == 1.f) { color_corrected = renodx::color::correct::GammaSafe(color_input); } else if (RENODX_GAMMA_CORRECTION == 2.f) { - float y_in = renodx_custom::tonemap::psycho::psycho11_StockmanLuminanceFromBT709(color_input); + float y_in = renodx::color::yf::from::BT709(color_input); float y_out = renodx::color::correct::Gamma(max(0, y_in)); float3 color_corrected_lum = renodx::color::correct::Luminance(color_input, y_in, y_out); float3 color_corrected_ch = renodx::color::correct::GammaSafe(color_input); - color_corrected = renodx::color::bt709::from::BT2020(renodx_custom::tonemap::psycho::psycho11_ApplyPurityFromBT2020( + color_corrected = renodx::color::bt709::from::BT2020(renodx_custom::tonemap::psycho::psycho17_ApplyPurityFromBT2020( renodx::color::bt2020::from::BT709(color_corrected_ch), renodx::color::bt2020::from::BT709(color_corrected_lum), 1.f, 1.f)); } else { color_corrected = color_input; @@ -71,7 +71,7 @@ float3 SampleGamma2LUTWithScaling( if (RENODX_COLOR_GRADE_SCALING > 0.f) { float3 lut_black = SampleGamma2LUT(0.f, _29, lut_sampler, _40_m0_10u_z, _40_m0_10u_w); - float lut_black_y = renodx_custom::tonemap::psycho::psycho11_StockmanLuminanceFromBT709(lut_black); + float lut_black_y = renodx::color::yf::from::BT709(lut_black); if (lut_black_y > 0.f) { float3 lut_mid = SampleGamma2LUT(lut_black_y, _29, lut_sampler, _40_m0_10u_z, _40_m0_10u_w); @@ -94,7 +94,7 @@ float3 SampleGamma2LUTWithScaling( unclamped_linear = renodx::color::correct::GammaSafe(unclamped_linear, true); } - color_output = color_output_original * lerp(1.f, renodx::math::DivideSafe(renodx_custom::tonemap::psycho::psycho11_StockmanLuminanceFromBT709(unclamped_linear), renodx_custom::tonemap::psycho::psycho11_StockmanLuminanceFromBT709(color_output_original), 1.f), RENODX_COLOR_GRADE_SCALING); + color_output = color_output_original * lerp(1.f, renodx::math::DivideSafe(renodx::color::yf::from::BT709(unclamped_linear), renodx::color::yf::from::BT709(color_output_original), 1.f), RENODX_COLOR_GRADE_SCALING); } } @@ -296,42 +296,33 @@ float3 ApplyUserGradingAndToneMapAndScale(float3 untonemapped_bt709, float peak_ratio = RENODX_PEAK_WHITE_NITS / RENODX_DIFFUSE_WHITE_NITS; -#if 1 - renodx_custom::tonemap::psycho::config::Config psycho_config = renodx_custom::tonemap::psycho::config::Create(); - psycho_config.peak_value = peak_ratio; - psycho_config.exposure = RENODX_TONE_MAP_EXPOSURE; - psycho_config.gamma = RENODX_TONE_MAP_GAMMA; - psycho_config.highlights = RENODX_TONE_MAP_HIGHLIGHTS; - psycho_config.shadows = RENODX_TONE_MAP_SHADOWS; - psycho_config.contrast = RENODX_TONE_MAP_CONTRAST; - psycho_config.flare = 0.10f * pow(RENODX_TONE_MAP_FLARE, 10.f); - psycho_config.contrast_highlights = RENODX_TONE_MAP_CONTRAST_HIGHLIGHTS; - psycho_config.contrast_shadows = RENODX_TONE_MAP_CONTRAST_SHADOWS; - psycho_config.purity_scale = RENODX_TONE_MAP_SATURATION; - psycho_config.purity_highlights = -1.f * (RENODX_TONE_MAP_HIGHLIGHT_SATURATION - 1.f); - psycho_config.adaptation_contrast = RENODX_TONE_MAP_ADAPTATION_CONTRAST; - psycho_config.bleaching_intensity = 0.f; - psycho_config.hue_restore = 0.f; - psycho_config.pre_gamut_compress = false; - psycho_config.post_gamut_compress = true; - - float3 tonemapped_bt2020; - if (RENODX_TONE_MAP_SCALING == 1.f) { // PsychoV - tonemapped_bt2020 = renodx_custom::tonemap::psycho::ApplyBT2020(untonemapped_bt2020, psycho_config); - } else { // Max Channel - float3 purity_and_hue_source = renodx::color::bt2020::from::BT709(renodx::tonemap::ReinhardPiecewise(untonemapped_bt709, 4.f, 0.5f)); - untonemapped_bt2020 = renodx::color::correct::Luminance( - purity_and_hue_source, - renodx_custom::tonemap::psycho::psycho11_StockmanLuminanceFromBT2020(purity_and_hue_source), - renodx_custom::tonemap::psycho::psycho11_StockmanLuminanceFromBT2020(untonemapped_bt2020)); - - psycho_config.apply_tonemap = false; - psycho_config.purity_highlights = 0.f; // increasing highlight saturation looks bad with maxch - untonemapped_bt2020 = renodx_custom::tonemap::psycho::ApplyBT2020(untonemapped_bt2020, psycho_config); - - tonemapped_bt2020 = renodx::tonemap::neutwo::MaxChannel(untonemapped_bt2020, peak_ratio); + renodx_custom::tonemap::psycho::config17::Config psycho17_config = + renodx_custom::tonemap::psycho::config17::Create(); + psycho17_config.peak_value = RENODX_PEAK_WHITE_NITS / RENODX_DIFFUSE_WHITE_NITS; + psycho17_config.clip_point = 100.f; + psycho17_config.exposure = RENODX_TONE_MAP_EXPOSURE; + psycho17_config.gamma = RENODX_TONE_MAP_GAMMA; + psycho17_config.highlights = RENODX_TONE_MAP_HIGHLIGHTS; + psycho17_config.shadows = RENODX_TONE_MAP_SHADOWS; + psycho17_config.contrast = RENODX_TONE_MAP_CONTRAST; + psycho17_config.flare = 0.10f * pow(RENODX_TONE_MAP_FLARE, 10.f); + psycho17_config.contrast_highlights = RENODX_TONE_MAP_CONTRAST_HIGHLIGHTS; + psycho17_config.contrast_shadows = RENODX_TONE_MAP_CONTRAST_SHADOWS; + psycho17_config.purity_scale = RENODX_TONE_MAP_SATURATION; + psycho17_config.purity_highlights = -1.f * (RENODX_TONE_MAP_HIGHLIGHT_SATURATION - 1.f); + psycho17_config.dechroma = 0.f; + psycho17_config.adaptation_contrast = RENODX_TONE_MAP_ADAPTATION_CONTRAST; + psycho17_config.bleaching_intensity = 0.f; + psycho17_config.hue_emulation = RENODX_TONE_MAP_HUE_EMULATION; + psycho17_config.pre_gamut_compress = false; + psycho17_config.post_gamut_compress = true; + psycho17_config.apply_tonemap = true; + + float3 hue_shift_source_bt2020 = untonemapped_bt2020; + if (psycho17_config.hue_emulation != 0.f) { + hue_shift_source_bt2020 = renodx::color::bt2020::from::BT709(renodx::tonemap::ReinhardPiecewise(untonemapped_bt709, 4.f, psycho17_config.mid_gray)); } -#endif + float3 tonemapped_bt2020 = renodx_custom::tonemap::psycho::ApplyTest17BT2020(untonemapped_bt2020, hue_shift_source_bt2020, psycho17_config); if (use_scaling) { tonemapped_bt2020 *= RENODX_DIFFUSE_WHITE_NITS / RENODX_GRAPHICS_WHITE_NITS; diff --git a/src/games/re7-2r-3r-village/tonemap/CBuffer_ToneMap.hlsli b/src/games/re7-2r-3r-village/tonemap/CBuffer_ToneMap.hlsli index a5dbbb81a..e5b0367e1 100644 --- a/src/games/re7-2r-3r-village/tonemap/CBuffer_ToneMap.hlsli +++ b/src/games/re7-2r-3r-village/tonemap/CBuffer_ToneMap.hlsli @@ -17,9 +17,9 @@ #define TONEMAP_PARAM_REGISTER b2 #elif SHADER_HASH == 0x30D8372F || SHADER_HASH == 0x16906EB5 // RE2/3 NoVignette LDR + RE8 NoVignette LDR #define TONEMAP_PARAM_REGISTER b1 -#elif SHADER_HASH == 0xAD20915B // RE7_LDRPostProcess_WithTonemap_0xAD20915B +#elif SHADER_HASH == 0xAD20915B || SHADER_HASH == 0x9E94200C // RE7_LDRPostProcess_WithTonemap #define TONEMAP_REGISTER b1 -#elif SHADER_HASH == 0xE4345E78 // RE7_PostToneMapC4L_PS_0xE4345E78 +#elif SHADER_HASH == 0xE4345E78 || SHADER_HASH == 0xB3FE7A3D // RE7_PostToneMapC4L_PS_0xE4345E78 + RE7_PostTonemap_PS_0xB3FE7A3D #define TONEMAP_REGISTER b0 #endif // SHADER_HASH diff --git a/src/games/re7-2r-3r-village/tonemap/PostProcess_WithTonemap/RE7_LDRPostProcess_WithTonemap_0x9E94200C.ps_6_5.hlsl b/src/games/re7-2r-3r-village/tonemap/PostProcess_WithTonemap/RE7_LDRPostProcess_WithTonemap_0x9E94200C.ps_6_5.hlsl new file mode 100644 index 000000000..e11773257 --- /dev/null +++ b/src/games/re7-2r-3r-village/tonemap/PostProcess_WithTonemap/RE7_LDRPostProcess_WithTonemap_0x9E94200C.ps_6_5.hlsl @@ -0,0 +1,819 @@ +#define SHADER_HASH 0x9E94200C +#include "../tonemap.hlsli" + +Texture2D RE_POSTPROCESS_Color : register(t0); + +struct RadialBlurComputeResult { + float computeAlpha; +}; +StructuredBuffer ComputeResultSRV : register(t1); + +Texture3D tTextureMap0 : register(t2); + +Texture3D tTextureMap1 : register(t3); + +Texture3D tTextureMap2 : register(t4); + +Texture2D ImagePlameBase : register(t5); + +Texture2D ImagePlameAlpha : register(t6); + +cbuffer SceneInfo : register(b0) { + float4 viewProjMat[4] : packoffset(c000.x); + float4 transposeViewMat[3] : packoffset(c004.x); + float4 transposeViewInvMat[3] : packoffset(c007.x); + float4 projElement[2] : packoffset(c010.x); + float4 projInvElements[2] : packoffset(c012.x); + float4 viewProjInvMat[4] : packoffset(c014.x); + float4 prevViewProjMat[4] : packoffset(c018.x); + float3 ZToLinear : packoffset(c022.x); + float subdivisionLevel : packoffset(c022.w); + float2 screenSize : packoffset(c023.x); + float2 screenInverseSize : packoffset(c023.z); + float2 cullingHelper : packoffset(c024.x); + float cameraNearPlane : packoffset(c024.z); + float cameraFarPlane : packoffset(c024.w); + float4 viewFrustum[6] : packoffset(c025.x); + float4 clipplane : packoffset(c031.x); + float2 vrsVelocityThreshold : packoffset(c032.x); + uint renderOutputId : packoffset(c032.z); + uint SceneInfo_Reserve : packoffset(c032.w); +}; + +// cbuffer Tonemap : register(b1) { +// float exposureAdjustment : packoffset(c000.x); +// float tonemapRange : packoffset(c000.y); +// float sharpness : packoffset(c000.z); +// float preTonemapRange : packoffset(c000.w); +// int useAutoExposure : packoffset(c001.x); +// float echoBlend : packoffset(c001.y); +// float AABlend : packoffset(c001.z); +// float AASubPixel : packoffset(c001.w); +// float ResponsiveAARate : packoffset(c002.x); +// }; + +cbuffer LensDistortionParam : register(b2) { + float fDistortionCoef : packoffset(c000.x); + float fRefraction : packoffset(c000.y); + uint aberrationEnable : packoffset(c000.z); + uint distortionType : packoffset(c000.w); + float fCorrectCoef : packoffset(c001.x); + uint reserve1 : packoffset(c001.y); + uint reserve2 : packoffset(c001.z); + uint reserve3 : packoffset(c001.w); +}; + +cbuffer PaniniProjectionParam : register(b3) { + float4 fOptimizedParam : packoffset(c000.x); +}; + +cbuffer RadialBlurRenderParam : register(b4) { + float4 cbRadialColor : packoffset(c000.x); + float2 cbRadialScreenPos : packoffset(c001.x); + float2 cbRadialMaskSmoothstep : packoffset(c001.z); + float2 cbRadialMaskRate : packoffset(c002.x); + float cbRadialBlurPower : packoffset(c002.z); + float cbRadialSharpRange : packoffset(c002.w); + uint cbRadialBlurFlags : packoffset(c003.x); + float cbRadialReserve0 : packoffset(c003.y); + float cbRadialReserve1 : packoffset(c003.z); + float cbRadialReserve2 : packoffset(c003.w); +}; + +cbuffer FilmGrainParam : register(b5) { + float2 fNoisePower : packoffset(c000.x); + float2 fNoiseUVOffset : packoffset(c000.z); + float fNoiseDensity : packoffset(c001.x); + float fNoiseContrast : packoffset(c001.y); + float fBlendRate : packoffset(c001.z); + float fReverseNoiseSize : packoffset(c001.w); +}; + +cbuffer ColorCorrectTexture : register(b6) { + float fTextureSize : packoffset(c000.x); + float fTextureBlendRate : packoffset(c000.y); + float fTextureBlendRate2 : packoffset(c000.z); + float fTextureInverseSize : packoffset(c000.w); + float4 fColorMatrix[4] : packoffset(c001.x); +}; + +cbuffer ColorDeficientTable : register(b7) { + float4 cvdR : packoffset(c000.x); + float4 cvdG : packoffset(c001.x); + float4 cvdB : packoffset(c002.x); +}; + +cbuffer ImagePlaneParam : register(b8) { + float4 ColorParam : packoffset(c000.x); + float Levels_Rate : packoffset(c001.x); + float Levels_Range : packoffset(c001.y); + uint Blend_Type : packoffset(c001.z); +}; + +cbuffer CBControl : register(b9) { + uint cPassEnabled : packoffset(c000.x); +}; + +SamplerState BilinearClamp : register(s5, space32); + +SamplerState BilinearBorder : register(s6, space32); + +SamplerState TrilinearClamp : register(s9, space32); + +float4 main( + noperspective float4 SV_Position: SV_Position, + linear float4 Kerare: Kerare, + linear float Exposure: Exposure) + : SV_Target { + float4 SV_Target; + bool _27 = ((cPassEnabled & 1) != 0); + bool _31 = _27 && (bool)(distortionType == 0); + bool _33 = _27 && (bool)(distortionType == 1); + float _100; + float _118; + float _209; + float _210; + float _211; + float _212; + float _213; + float _214; + float _215; + float _216; + float _217; + float _571; + float _572; + float _573; + float _870; + float _871; + float _872; + float _958; + float _959; + float _960; + float _971; + float _972; + float _973; + float _999; + float _1000; + float _1001; + float _1012; + float _1013; + float _1014; + float _1056; + float _1072; + float _1088; + float _1113; + float _1114; + float _1115; + float _1147; + float _1148; + float _1149; + float _1161; + float _1172; + float _1183; + float _1222; + float _1233; + float _1244; + float _1269; + float _1280; + float _1291; + float _1306; + float _1307; + float _1308; + float _1326; + float _1327; + float _1328; + float _1363; + float _1364; + float _1365; + float _1434; + float _1435; + float _1436; + if (_31) { + float _46 = (screenInverseSize.x * SV_Position.x) + -0.5f; + float _47 = (screenInverseSize.y * SV_Position.y) + -0.5f; + float _48 = dot(float2(_46, _47), float2(_46, _47)); + float _51 = ((_48 * fDistortionCoef) + 1.0f) * fCorrectCoef; + float4 _57 = RE_POSTPROCESS_Color.Sample(BilinearClamp, float2(((_51 * _46) + 0.5f), ((_51 * _47) + 0.5f))); + float _61 = _57.x * Exposure; + float _62 = _57.y * Exposure; + float _63 = _57.z * Exposure; + float _65 = max(max(_61, _62), _63); + bool _66 = isfinite(_65); + if (aberrationEnable == 0) { + if (_66) { + float _72 = (tonemapRange * _65) + 1.0f; + _209 = (_61 / _72); + _210 = (_62 / _72); + _211 = (_63 / _72); + _212 = fDistortionCoef; + _213 = 0.0f; + _214 = 0.0f; + _215 = 0.0f; + _216 = 0.0f; + _217 = fCorrectCoef; + } else { + _209 = 1.0f; + _210 = 1.0f; + _211 = 1.0f; + _212 = fDistortionCoef; + _213 = 0.0f; + _214 = 0.0f; + _215 = 0.0f; + _216 = 0.0f; + _217 = fCorrectCoef; + } + } else { + float _77 = _48 + fRefraction; + float _79 = (_77 * fDistortionCoef) + 1.0f; + float _80 = _46 * fCorrectCoef; + float _82 = _47 * fCorrectCoef; + float _88 = ((_77 + fRefraction) * fDistortionCoef) + 1.0f; + do { + if (_66) { + _100 = (_61 / ((tonemapRange * _65) + 1.0f)); + } else { + _100 = 1.0f; + } + float4 _101 = RE_POSTPROCESS_Color.Sample(BilinearClamp, float2(((_80 * _79) + 0.5f), ((_82 * _79) + 0.5f))); + float _106 = _101.y * Exposure; + float _109 = max(max((_101.x * Exposure), _106), (_101.z * Exposure)); + do { + if (isfinite(_109)) { + _118 = (_106 / ((tonemapRange * _109) + 1.0f)); + } else { + _118 = 1.0f; + } + float4 _119 = RE_POSTPROCESS_Color.Sample(BilinearClamp, float2(((_80 * _88) + 0.5f), ((_82 * _88) + 0.5f))); + float _125 = _119.z * Exposure; + float _127 = max(max((_119.x * Exposure), (_119.y * Exposure)), _125); + if (isfinite(_127)) { + _209 = _100; + _210 = _118; + _211 = (_125 / ((tonemapRange * _127) + 1.0f)); + _212 = fDistortionCoef; + _213 = 0.0f; + _214 = 0.0f; + _215 = 0.0f; + _216 = 0.0f; + _217 = fCorrectCoef; + } else { + _209 = _100; + _210 = _118; + _211 = 1.0f; + _212 = fDistortionCoef; + _213 = 0.0f; + _214 = 0.0f; + _215 = 0.0f; + _216 = 0.0f; + _217 = fCorrectCoef; + } + } while (false); + } while (false); + } + } else { + if (_33) { + float _149 = ((SV_Position.x * 2.0f) * screenInverseSize.x) + -1.0f; + float _153 = sqrt((_149 * _149) + 1.0f); + float _154 = 1.0f / _153; + float _157 = (_153 * fOptimizedParam.z) * (_154 + fOptimizedParam.x); + float _161 = fOptimizedParam.w * 0.5f; + float4 _169 = RE_POSTPROCESS_Color.Sample(BilinearBorder, float2((((_161 * _149) * _157) + 0.5f), ((((_161 * (((SV_Position.y * 2.0f) * screenInverseSize.y) + -1.0f)) * (((_154 + -1.0f) * fOptimizedParam.y) + 1.0f)) * _157) + 0.5f))); + float _173 = _169.x * Exposure; + float _174 = _169.y * Exposure; + float _175 = _169.z * Exposure; + float _177 = max(max(_173, _174), _175); + if (isfinite(_177)) { + float _183 = (tonemapRange * _177) + 1.0f; + _209 = (_173 / _183); + _210 = (_174 / _183); + _211 = (_175 / _183); + _212 = 0.0f; + _213 = fOptimizedParam.x; + _214 = fOptimizedParam.y; + _215 = fOptimizedParam.z; + _216 = fOptimizedParam.w; + _217 = 1.0f; + } else { + _209 = 1.0f; + _210 = 1.0f; + _211 = 1.0f; + _212 = 0.0f; + _213 = fOptimizedParam.x; + _214 = fOptimizedParam.y; + _215 = fOptimizedParam.z; + _216 = fOptimizedParam.w; + _217 = 1.0f; + } + } else { + float4 _190 = RE_POSTPROCESS_Color.Load(int3((uint)(uint(SV_Position.x)), (uint)(uint(SV_Position.y)), 0)); + float _194 = _190.x * Exposure; + float _195 = _190.y * Exposure; + float _196 = _190.z * Exposure; + float _198 = max(max(_194, _195), _196); + if (isfinite(_198)) { + float _204 = (tonemapRange * _198) + 1.0f; + _209 = (_194 / _204); + _210 = (_195 / _204); + _211 = (_196 / _204); + _212 = 0.0f; + _213 = 0.0f; + _214 = 0.0f; + _215 = 0.0f; + _216 = 0.0f; + _217 = 1.0f; + } else { + _209 = 1.0f; + _210 = 1.0f; + _211 = 1.0f; + _212 = 0.0f; + _213 = 0.0f; + _214 = 0.0f; + _215 = 0.0f; + _216 = 0.0f; + _217 = 1.0f; + } + } + } + if (!((cPassEnabled & 32) == 0)) { + float _239 = float((bool)(bool)((cbRadialBlurFlags & 2) != 0)); + float _242 = ComputeResultSRV[0].computeAlpha; + float _245 = ((1.0f - _239) + (_242 * _239)) * cbRadialColor.w; + if (!(_245 == 0.0f)) { + float _252 = screenInverseSize.x * SV_Position.x; + float _253 = screenInverseSize.y * SV_Position.y; + float _255 = (-0.5f - cbRadialScreenPos.x) + _252; + float _257 = (-0.5f - cbRadialScreenPos.y) + _253; + float _260 = select((_255 < 0.0f), (1.0f - _252), _252); + float _263 = select((_257 < 0.0f), (1.0f - _253), _253); + float _268 = rsqrt(dot(float2(_255, _257), float2(_255, _257))) * cbRadialSharpRange; + uint _275 = uint(abs(_268 * _257)) + uint(abs(_268 * _255)); + uint _279 = ((_275 ^ 61) ^ ((uint)(_275) >> 16)) * 9; + uint _282 = (((uint)(_279) >> 4) ^ _279) * 668265261; + float _287 = select(((cbRadialBlurFlags & 1) != 0), (float((uint)((int)(((uint)(_282) >> 15) ^ _282))) * 2.3283064365386963e-10f), 1.0f); + float _293 = 1.0f / max(1.0f, sqrt((_255 * _255) + (_257 * _257))); + float _294 = cbRadialBlurPower * -0.0011111111380159855f; + float _303 = ((((_294 * _260) * _287) * _293) + 1.0f) * _255; + float _304 = ((((_294 * _263) * _287) * _293) + 1.0f) * _257; + float _305 = cbRadialBlurPower * -0.002222222276031971f; + float _314 = ((((_305 * _260) * _287) * _293) + 1.0f) * _255; + float _315 = ((((_305 * _263) * _287) * _293) + 1.0f) * _257; + float _316 = cbRadialBlurPower * -0.0033333334140479565f; + float _325 = ((((_316 * _260) * _287) * _293) + 1.0f) * _255; + float _326 = ((((_316 * _263) * _287) * _293) + 1.0f) * _257; + float _327 = cbRadialBlurPower * -0.004444444552063942f; + float _336 = ((((_327 * _260) * _287) * _293) + 1.0f) * _255; + float _337 = ((((_327 * _263) * _287) * _293) + 1.0f) * _257; + float _338 = cbRadialBlurPower * -0.0055555556900799274f; + float _347 = ((((_338 * _260) * _287) * _293) + 1.0f) * _255; + float _348 = ((((_338 * _263) * _287) * _293) + 1.0f) * _257; + float _349 = cbRadialBlurPower * -0.006666666828095913f; + float _358 = ((((_349 * _260) * _287) * _293) + 1.0f) * _255; + float _359 = ((((_349 * _263) * _287) * _293) + 1.0f) * _257; + float _360 = cbRadialBlurPower * -0.007777777966111898f; + float _369 = ((((_360 * _260) * _287) * _293) + 1.0f) * _255; + float _370 = ((((_360 * _263) * _287) * _293) + 1.0f) * _257; + float _371 = cbRadialBlurPower * -0.008888889104127884f; + float _380 = ((((_371 * _260) * _287) * _293) + 1.0f) * _255; + float _381 = ((((_371 * _263) * _287) * _293) + 1.0f) * _257; + float _382 = cbRadialBlurPower * -0.009999999776482582f; + float _391 = ((((_382 * _260) * _287) * _293) + 1.0f) * _255; + float _392 = ((((_382 * _263) * _287) * _293) + 1.0f) * _257; + float _393 = Exposure * 0.10000000149011612f; + float _394 = _393 * cbRadialColor.x; + float _395 = _393 * cbRadialColor.y; + float _396 = _393 * cbRadialColor.z; + do { + if (_31) { + float _398 = _303 + cbRadialScreenPos.x; + float _399 = _304 + cbRadialScreenPos.y; + float _403 = ((dot(float2(_398, _399), float2(_398, _399)) * _212) + 1.0f) * _217; + float4 _408 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2(((_403 * _398) + 0.5f), ((_403 * _399) + 0.5f)), 0.0f); + float _412 = _314 + cbRadialScreenPos.x; + float _413 = _315 + cbRadialScreenPos.y; + float _416 = (dot(float2(_412, _413), float2(_412, _413)) * _212) + 1.0f; + float4 _423 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2((((_412 * _217) * _416) + 0.5f), (((_413 * _217) * _416) + 0.5f)), 0.0f); + float _430 = _325 + cbRadialScreenPos.x; + float _431 = _326 + cbRadialScreenPos.y; + float _434 = (dot(float2(_430, _431), float2(_430, _431)) * _212) + 1.0f; + float4 _441 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2((((_430 * _217) * _434) + 0.5f), (((_431 * _217) * _434) + 0.5f)), 0.0f); + float _448 = _336 + cbRadialScreenPos.x; + float _449 = _337 + cbRadialScreenPos.y; + float _452 = (dot(float2(_448, _449), float2(_448, _449)) * _212) + 1.0f; + float4 _459 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2((((_448 * _217) * _452) + 0.5f), (((_449 * _217) * _452) + 0.5f)), 0.0f); + float _466 = _347 + cbRadialScreenPos.x; + float _467 = _348 + cbRadialScreenPos.y; + float _470 = (dot(float2(_466, _467), float2(_466, _467)) * _212) + 1.0f; + float4 _477 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2((((_466 * _217) * _470) + 0.5f), (((_467 * _217) * _470) + 0.5f)), 0.0f); + float _484 = _358 + cbRadialScreenPos.x; + float _485 = _359 + cbRadialScreenPos.y; + float _488 = (dot(float2(_484, _485), float2(_484, _485)) * _212) + 1.0f; + float4 _495 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2((((_484 * _217) * _488) + 0.5f), (((_485 * _217) * _488) + 0.5f)), 0.0f); + float _502 = _369 + cbRadialScreenPos.x; + float _503 = _370 + cbRadialScreenPos.y; + float _506 = (dot(float2(_502, _503), float2(_502, _503)) * _212) + 1.0f; + float4 _513 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2((((_502 * _217) * _506) + 0.5f), (((_503 * _217) * _506) + 0.5f)), 0.0f); + float _520 = _380 + cbRadialScreenPos.x; + float _521 = _381 + cbRadialScreenPos.y; + float _524 = (dot(float2(_520, _521), float2(_520, _521)) * _212) + 1.0f; + float4 _531 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2((((_520 * _217) * _524) + 0.5f), (((_521 * _217) * _524) + 0.5f)), 0.0f); + float _538 = _391 + cbRadialScreenPos.x; + float _539 = _392 + cbRadialScreenPos.y; + float _542 = (dot(float2(_538, _539), float2(_538, _539)) * _212) + 1.0f; + float4 _549 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2((((_538 * _217) * _542) + 0.5f), (((_539 * _217) * _542) + 0.5f)), 0.0f); + float _556 = _394 * ((((((((_423.x + _408.x) + _441.x) + _459.x) + _477.x) + _495.x) + _513.x) + _531.x) + _549.x); + float _557 = _395 * ((((((((_423.y + _408.y) + _441.y) + _459.y) + _477.y) + _495.y) + _513.y) + _531.y) + _549.y); + float _558 = _396 * ((((((((_423.z + _408.z) + _441.z) + _459.z) + _477.z) + _495.z) + _513.z) + _531.z) + _549.z); + float _560 = max(max(_556, _557), _558); + do { + if (isfinite(_560)) { + float _566 = (tonemapRange * _560) + 1.0f; + _571 = (_556 / _566); + _572 = (_557 / _566); + _573 = (_558 / _566); + } else { + _571 = 1.0f; + _572 = 1.0f; + _573 = 1.0f; + } + _971 = (_571 + ((_209 * 0.10000000149011612f) * cbRadialColor.x)); + _972 = (_572 + ((_210 * 0.10000000149011612f) * cbRadialColor.y)); + _973 = (_573 + ((_211 * 0.10000000149011612f) * cbRadialColor.z)); + } while (false); + } else { + float _584 = cbRadialScreenPos.x + 0.5f; + float _585 = _584 + _303; + float _586 = cbRadialScreenPos.y + 0.5f; + float _587 = _586 + _304; + float _588 = _584 + _314; + float _589 = _586 + _315; + float _590 = _584 + _325; + float _591 = _586 + _326; + float _592 = _584 + _336; + float _593 = _586 + _337; + float _594 = _584 + _347; + float _595 = _586 + _348; + float _596 = _584 + _358; + float _597 = _586 + _359; + float _598 = _584 + _369; + float _599 = _586 + _370; + float _600 = _584 + _380; + float _601 = _586 + _381; + float _602 = _584 + _391; + float _603 = _586 + _392; + if (_33) { + float _607 = (_585 * 2.0f) + -1.0f; + float _611 = sqrt((_607 * _607) + 1.0f); + float _612 = 1.0f / _611; + float _615 = (_611 * _215) * (_612 + _213); + float _619 = _216 * 0.5f; + float4 _627 = RE_POSTPROCESS_Color.SampleLevel(BilinearBorder, float2((((_619 * _615) * _607) + 0.5f), ((((_619 * (((_612 + -1.0f) * _214) + 1.0f)) * _615) * ((_587 * 2.0f) + -1.0f)) + 0.5f)), 0.0f); + float _633 = (_588 * 2.0f) + -1.0f; + float _637 = sqrt((_633 * _633) + 1.0f); + float _638 = 1.0f / _637; + float _641 = (_637 * _215) * (_638 + _213); + float4 _652 = RE_POSTPROCESS_Color.SampleLevel(BilinearBorder, float2((((_619 * _633) * _641) + 0.5f), ((((_619 * ((_589 * 2.0f) + -1.0f)) * (((_638 + -1.0f) * _214) + 1.0f)) * _641) + 0.5f)), 0.0f); + float _661 = (_590 * 2.0f) + -1.0f; + float _665 = sqrt((_661 * _661) + 1.0f); + float _666 = 1.0f / _665; + float _669 = (_665 * _215) * (_666 + _213); + float4 _680 = RE_POSTPROCESS_Color.SampleLevel(BilinearBorder, float2((((_619 * _661) * _669) + 0.5f), ((((_619 * ((_591 * 2.0f) + -1.0f)) * (((_666 + -1.0f) * _214) + 1.0f)) * _669) + 0.5f)), 0.0f); + float _689 = (_592 * 2.0f) + -1.0f; + float _693 = sqrt((_689 * _689) + 1.0f); + float _694 = 1.0f / _693; + float _697 = (_693 * _215) * (_694 + _213); + float4 _708 = RE_POSTPROCESS_Color.SampleLevel(BilinearBorder, float2((((_619 * _689) * _697) + 0.5f), ((((_619 * ((_593 * 2.0f) + -1.0f)) * (((_694 + -1.0f) * _214) + 1.0f)) * _697) + 0.5f)), 0.0f); + float _717 = (_594 * 2.0f) + -1.0f; + float _721 = sqrt((_717 * _717) + 1.0f); + float _722 = 1.0f / _721; + float _725 = (_721 * _215) * (_722 + _213); + float4 _736 = RE_POSTPROCESS_Color.SampleLevel(BilinearBorder, float2((((_619 * _717) * _725) + 0.5f), ((((_619 * ((_595 * 2.0f) + -1.0f)) * (((_722 + -1.0f) * _214) + 1.0f)) * _725) + 0.5f)), 0.0f); + float _745 = (_596 * 2.0f) + -1.0f; + float _749 = sqrt((_745 * _745) + 1.0f); + float _750 = 1.0f / _749; + float _753 = (_749 * _215) * (_750 + _213); + float4 _764 = RE_POSTPROCESS_Color.SampleLevel(BilinearBorder, float2((((_619 * _745) * _753) + 0.5f), ((((_619 * ((_597 * 2.0f) + -1.0f)) * (((_750 + -1.0f) * _214) + 1.0f)) * _753) + 0.5f)), 0.0f); + float _773 = (_598 * 2.0f) + -1.0f; + float _777 = sqrt((_773 * _773) + 1.0f); + float _778 = 1.0f / _777; + float _781 = (_777 * _215) * (_778 + _213); + float4 _792 = RE_POSTPROCESS_Color.SampleLevel(BilinearBorder, float2((((_619 * _773) * _781) + 0.5f), ((((_619 * ((_599 * 2.0f) + -1.0f)) * (((_778 + -1.0f) * _214) + 1.0f)) * _781) + 0.5f)), 0.0f); + float _801 = (_600 * 2.0f) + -1.0f; + float _805 = sqrt((_801 * _801) + 1.0f); + float _806 = 1.0f / _805; + float _809 = (_805 * _215) * (_806 + _213); + float4 _820 = RE_POSTPROCESS_Color.SampleLevel(BilinearBorder, float2((((_619 * _801) * _809) + 0.5f), ((((_619 * ((_601 * 2.0f) + -1.0f)) * (((_806 + -1.0f) * _214) + 1.0f)) * _809) + 0.5f)), 0.0f); + float _829 = (_602 * 2.0f) + -1.0f; + float _833 = sqrt((_829 * _829) + 1.0f); + float _834 = 1.0f / _833; + float _837 = (_833 * _215) * (_834 + _213); + float4 _848 = RE_POSTPROCESS_Color.SampleLevel(BilinearBorder, float2((((_619 * _829) * _837) + 0.5f), ((((_619 * ((_603 * 2.0f) + -1.0f)) * (((_834 + -1.0f) * _214) + 1.0f)) * _837) + 0.5f)), 0.0f); + float _855 = _394 * ((((((((_652.x + _627.x) + _680.x) + _708.x) + _736.x) + _764.x) + _792.x) + _820.x) + _848.x); + float _856 = _395 * ((((((((_652.y + _627.y) + _680.y) + _708.y) + _736.y) + _764.y) + _792.y) + _820.y) + _848.y); + float _857 = _396 * ((((((((_652.z + _627.z) + _680.z) + _708.z) + _736.z) + _764.z) + _792.z) + _820.z) + _848.z); + float _859 = max(max(_855, _856), _857); + do { + if (isfinite(_859)) { + float _865 = (tonemapRange * _859) + 1.0f; + _870 = (_855 / _865); + _871 = (_856 / _865); + _872 = (_857 / _865); + } else { + _870 = 1.0f; + _871 = 1.0f; + _872 = 1.0f; + } + _971 = (_870 + ((_209 * 0.10000000149011612f) * cbRadialColor.x)); + _972 = (_871 + ((_210 * 0.10000000149011612f) * cbRadialColor.y)); + _973 = (_872 + ((_211 * 0.10000000149011612f) * cbRadialColor.z)); + } while (false); + } else { + float4 _883 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2(_585, _587), 0.0f); + float4 _887 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2(_588, _589), 0.0f); + float4 _894 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2(_590, _591), 0.0f); + float4 _901 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2(_592, _593), 0.0f); + float4 _908 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2(_594, _595), 0.0f); + float4 _915 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2(_596, _597), 0.0f); + float4 _922 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2(_598, _599), 0.0f); + float4 _929 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2(_600, _601), 0.0f); + float4 _936 = RE_POSTPROCESS_Color.SampleLevel(BilinearClamp, float2(_602, _603), 0.0f); + float _943 = _394 * ((((((((_887.x + _883.x) + _894.x) + _901.x) + _908.x) + _915.x) + _922.x) + _929.x) + _936.x); + float _944 = _395 * ((((((((_887.y + _883.y) + _894.y) + _901.y) + _908.y) + _915.y) + _922.y) + _929.y) + _936.y); + float _945 = _396 * ((((((((_887.z + _883.z) + _894.z) + _901.z) + _908.z) + _915.z) + _922.z) + _929.z) + _936.z); + float _947 = max(max(_943, _944), _945); + do { + if (isfinite(_947)) { + float _953 = (tonemapRange * _947) + 1.0f; + _958 = (_943 / _953); + _959 = (_944 / _953); + _960 = (_945 / _953); + } else { + _958 = 1.0f; + _959 = 1.0f; + _960 = 1.0f; + } + _971 = (_958 + ((_209 * 0.10000000149011612f) * cbRadialColor.x)); + _972 = (_959 + ((_210 * 0.10000000149011612f) * cbRadialColor.y)); + _973 = (_960 + ((_211 * 0.10000000149011612f) * cbRadialColor.z)); + } while (false); + } + } + do { + if (cbRadialMaskRate.x > 0.0f) { + float _982 = saturate((sqrt((_255 * _255) + (_257 * _257)) * cbRadialMaskSmoothstep.x) + cbRadialMaskSmoothstep.y); + float _988 = (((_982 * _982) * cbRadialMaskRate.x) * (3.0f - (_982 * 2.0f))) + cbRadialMaskRate.y; + _999 = ((_988 * (_971 - _209)) + _209); + _1000 = ((_988 * (_972 - _210)) + _210); + _1001 = ((_988 * (_973 - _211)) + _211); + } else { + _999 = _971; + _1000 = _972; + _1001 = _973; + } + _1012 = (lerp(_209, _999, _245)); + _1013 = (lerp(_210, _1000, _245)); + _1014 = (lerp(_211, _1001, _245)); + } while (false); + } while (false); + } else { + _1012 = _209; + _1013 = _210; + _1014 = _211; + } + } else { + _1012 = _209; + _1013 = _210; + _1014 = _211; + } + if (!((cPassEnabled & 2) == 0)) { + float _1036 = floor(((screenSize.x * fNoiseUVOffset.x) + SV_Position.x) * fReverseNoiseSize); + float _1038 = floor(((screenSize.y * fNoiseUVOffset.y) + SV_Position.y) * fReverseNoiseSize); + float _1042 = frac(frac(dot(float2(_1036, _1038), float2(0.0671105608344078f, 0.005837149918079376f))) * 52.98291778564453f); + do { + if (_1042 < fNoiseDensity) { + int _1047 = (uint)(uint(_1038 * _1036)) ^ 12345391; + uint _1048 = _1047 * 3635641; + _1056 = (float((uint)((int)((((uint)(_1048) >> 26) | ((uint)(_1047 * 232681024))) ^ _1048))) * 2.3283064365386963e-10f); + } else { + _1056 = 0.0f; + } + float _1058 = frac(_1042 * 757.4846801757812f); + do { + if (_1058 < fNoiseDensity) { + int _1062 = asint(_1058) ^ 12345391; + uint _1063 = _1062 * 3635641; + _1072 = ((float((uint)((int)((((uint)(_1063) >> 26) | ((uint)(_1062 * 232681024))) ^ _1063))) * 2.3283064365386963e-10f) + -0.5f); + } else { + _1072 = 0.0f; + } + float _1074 = frac(_1058 * 757.4846801757812f); + do { + if (_1074 < fNoiseDensity) { + int _1078 = asint(_1074) ^ 12345391; + uint _1079 = _1078 * 3635641; + _1088 = ((float((uint)((int)((((uint)(_1079) >> 26) | ((uint)(_1078 * 232681024))) ^ _1079))) * 2.3283064365386963e-10f) + -0.5f); + } else { + _1088 = 0.0f; + } + float _1089 = _1056 * CUSTOM_NOISE * fNoisePower.x; + float _1090 = _1088 * CUSTOM_NOISE * fNoisePower.y; + float _1091 = _1072 * CUSTOM_NOISE * fNoisePower.y; + float _1102 = exp2(log2(1.0f - saturate(dot(float3(_1012, _1013, _1014), float3(0.29899999499320984f, -0.16899999976158142f, 0.5f)))) * fNoiseContrast) * fBlendRate; + _1113 = ((_1102 * (mad(_1091, 1.4019999504089355f, _1089) - _1012)) + _1012); + _1114 = ((_1102 * (mad(_1091, -0.7139999866485596f, mad(_1090, -0.3440000116825104f, _1089)) - _1013)) + _1013); + _1115 = ((_1102 * (mad(_1090, 1.7719999551773071f, _1089) - _1014)) + _1014); + } while (false); + } while (false); + } while (false); + } else { + _1113 = _1012; + _1114 = _1013; + _1115 = _1014; + } +#if 1 + ApplyColorGrading( + _1113, _1114, _1115, // input color (pre-grade) + _1326, _1327, _1328, // output color (post-grade) + cPassEnabled, + fTextureSize, + fTextureBlendRate, + fTextureBlendRate2, + fTextureInverseSize, + fColorMatrix, + tTextureMap0, + tTextureMap1, + tTextureMap2, + TrilinearClamp); +#else + + if (!((cPassEnabled & 4) == 0)) { + float _1140 = max(max(_1113, _1114), _1115); + bool _1141 = (_1140 > 1.0f); + do { + if (_1141) { + _1147 = (_1113 / _1140); + _1148 = (_1114 / _1140); + _1149 = (_1115 / _1140); + } else { + _1147 = _1113; + _1148 = _1114; + _1149 = _1115; + } + float _1150 = fTextureInverseSize * 0.5f; + do { + [branch] + if (!(!(_1147 <= 0.0031308000907301903f))) { + _1161 = (_1147 * 12.920000076293945f); + } else { + _1161 = (((pow(_1147, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + do { + [branch] + if (!(!(_1148 <= 0.0031308000907301903f))) { + _1172 = (_1148 * 12.920000076293945f); + } else { + _1172 = (((pow(_1148, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + do { + [branch] + if (!(!(_1149 <= 0.0031308000907301903f))) { + _1183 = (_1149 * 12.920000076293945f); + } else { + _1183 = (((pow(_1149, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + float _1184 = 1.0f - fTextureInverseSize; + float _1188 = (_1161 * _1184) + _1150; + float _1189 = (_1172 * _1184) + _1150; + float _1190 = (_1183 * _1184) + _1150; + float4 _1191 = tTextureMap0.SampleLevel(TrilinearClamp, float3(_1188, _1189, _1190), 0.0f); + do { + [branch] + if (fTextureBlendRate > 0.0f) { + float4 _1197 = tTextureMap1.SampleLevel(TrilinearClamp, float3(_1188, _1189, _1190), 0.0f); + float _1207 = ((_1197.x - _1191.x) * fTextureBlendRate) + _1191.x; + float _1208 = ((_1197.y - _1191.y) * fTextureBlendRate) + _1191.y; + float _1209 = ((_1197.z - _1191.z) * fTextureBlendRate) + _1191.z; + if (fTextureBlendRate2 > 0.0f) { + do { + [branch] + if (!(!(_1207 <= 0.0031308000907301903f))) { + _1222 = (_1207 * 12.920000076293945f); + } else { + _1222 = (((pow(_1207, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + do { + [branch] + if (!(!(_1208 <= 0.0031308000907301903f))) { + _1233 = (_1208 * 12.920000076293945f); + } else { + _1233 = (((pow(_1208, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + do { + [branch] + if (!(!(_1209 <= 0.0031308000907301903f))) { + _1244 = (_1209 * 12.920000076293945f); + } else { + _1244 = (((pow(_1209, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + float4 _1245 = tTextureMap2.SampleLevel(TrilinearClamp, float3(_1222, _1233, _1244), 0.0f); + _1306 = (lerp(_1207, _1245.x, fTextureBlendRate2)); + _1307 = (lerp(_1208, _1245.y, fTextureBlendRate2)); + _1308 = (lerp(_1209, _1245.z, fTextureBlendRate2)); + } while (false); + } while (false); + } while (false); + } else { + _1306 = _1207; + _1307 = _1208; + _1308 = _1209; + } + } else { + do { + [branch] + if (!(!(_1191.x <= 0.0031308000907301903f))) { + _1269 = (_1191.x * 12.920000076293945f); + } else { + _1269 = (((pow(_1191.x, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + do { + [branch] + if (!(!(_1191.y <= 0.0031308000907301903f))) { + _1280 = (_1191.y * 12.920000076293945f); + } else { + _1280 = (((pow(_1191.y, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + do { + [branch] + if (!(!(_1191.z <= 0.0031308000907301903f))) { + _1291 = (_1191.z * 12.920000076293945f); + } else { + _1291 = (((pow(_1191.z, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + float4 _1292 = tTextureMap2.SampleLevel(TrilinearClamp, float3(_1269, _1280, _1291), 0.0f); + _1306 = (lerp(_1191.x, _1292.x, fTextureBlendRate2)); + _1307 = (lerp(_1191.y, _1292.y, fTextureBlendRate2)); + _1308 = (lerp(_1191.z, _1292.z, fTextureBlendRate2)); + } while (false); + } while (false); + } while (false); + } + float _1312 = mad(_1308, (fColorMatrix[2].x), mad(_1307, (fColorMatrix[1].x), (_1306 * (fColorMatrix[0].x)))) + (fColorMatrix[3].x); + float _1316 = mad(_1308, (fColorMatrix[2].y), mad(_1307, (fColorMatrix[1].y), (_1306 * (fColorMatrix[0].y)))) + (fColorMatrix[3].y); + float _1320 = mad(_1308, (fColorMatrix[2].z), mad(_1307, (fColorMatrix[1].z), (_1306 * (fColorMatrix[0].z)))) + (fColorMatrix[3].z); + if (_1141) { + _1326 = (_1312 * _1140); + _1327 = (_1316 * _1140); + _1328 = (_1320 * _1140); + } else { + _1326 = _1312; + _1327 = _1316; + _1328 = _1320; + } + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } else { + _1326 = _1113; + _1327 = _1114; + _1328 = _1115; + } +#endif + if (!((cPassEnabled & 8) == 0)) { + _1363 = saturate(((cvdR.x * _1326) + (cvdR.y * _1327)) + (cvdR.z * _1328)); + _1364 = saturate(((cvdG.x * _1326) + (cvdG.y * _1327)) + (cvdG.z * _1328)); + _1365 = saturate(((cvdB.x * _1326) + (cvdB.y * _1327)) + (cvdB.z * _1328)); + } else { + _1363 = _1326; + _1364 = _1327; + _1365 = _1328; + } + if (!((cPassEnabled & 16) == 0)) { + float _1380 = screenInverseSize.x * SV_Position.x; + float _1381 = screenInverseSize.y * SV_Position.y; + float4 _1382 = ImagePlameBase.SampleLevel(BilinearClamp, float2(_1380, _1381), 0.0f); + float _1387 = _1382.x * ColorParam.x; + float _1388 = _1382.y * ColorParam.y; + float _1389 = _1382.z * ColorParam.z; + float _1391 = ImagePlameAlpha.SampleLevel(BilinearClamp, float2(_1380, _1381), 0.0f); + float _1396 = (_1382.w * ColorParam.w) * saturate((_1391.x * Levels_Rate) + Levels_Range); + _1434 = (((select((_1387 < 0.5f), ((_1363 * 2.0f) * _1387), (1.0f - (((1.0f - _1363) * 2.0f) * (1.0f - _1387)))) - _1363) * _1396) + _1363); + _1435 = (((select((_1388 < 0.5f), ((_1364 * 2.0f) * _1388), (1.0f - (((1.0f - _1364) * 2.0f) * (1.0f - _1388)))) - _1364) * _1396) + _1364); + _1436 = (((select((_1389 < 0.5f), ((_1365 * 2.0f) * _1389), (1.0f - (((1.0f - _1365) * 2.0f) * (1.0f - _1389)))) - _1365) * _1396) + _1365); + } else { + _1434 = _1363; + _1435 = _1364; + _1436 = _1365; + } + SV_Target.x = _1434; + SV_Target.y = _1435; + SV_Target.z = _1436; + SV_Target.w = 0.0f; + +#if 1 + float2 grain_uv = SV_Position.xy * screenInverseSize; + SV_Target.rgb = ApplyUserGradingAndToneMap(SV_Target.rgb, grain_uv); +#endif + + return SV_Target; +} diff --git a/src/games/re7-2r-3r-village/tonemap/PostToneMap/RE7_PostTonemap_PS_0xB3FE7A3D.ps_6_5.hlsl b/src/games/re7-2r-3r-village/tonemap/PostToneMap/RE7_PostTonemap_PS_0xB3FE7A3D.ps_6_5.hlsl new file mode 100644 index 000000000..e0a60e5f9 --- /dev/null +++ b/src/games/re7-2r-3r-village/tonemap/PostToneMap/RE7_PostTonemap_PS_0xB3FE7A3D.ps_6_5.hlsl @@ -0,0 +1,53 @@ +#define SHADER_HASH 0xB3FE7A3D +#include "../tonemap.hlsli" + +Texture2D HDRImage : register(t0); + +// cbuffer Tonemap : register(b0) { +// float exposureAdjustment : packoffset(c000.x); +// float tonemapRange : packoffset(c000.y); +// float sharpness : packoffset(c000.z); +// float preTonemapRange : packoffset(c000.w); +// int useAutoExposure : packoffset(c001.x); +// float echoBlend : packoffset(c001.y); +// float AABlend : packoffset(c001.z); +// float AASubPixel : packoffset(c001.w); +// float ResponsiveAARate : packoffset(c002.x); +// }; + +float4 main( + noperspective float4 SV_Position : SV_Position, + linear float4 Kerare : Kerare, + linear float Exposure : Exposure +) : SV_Target { + float4 SV_Target; + float4 _8 = HDRImage.Load(int3((uint)(uint(SV_Position.x)), (uint)(uint(SV_Position.y)), 0)); + float _12 = _8.x * Exposure; + float _13 = _8.y * Exposure; + float _14 = _8.z * Exposure; + float _16 = max(max(_12, _13), _14); + float _27; + float _28; + float _29; + if (isfinite(_16)) { + float _22 = (tonemapRange * _16) + 1.0f; + _27 = (_12 / _22); + _28 = (_13 / _22); + _29 = (_14 / _22); + } else { + _27 = 1.0f; + _28 = 1.0f; + _29 = 1.0f; + } + SV_Target.x = _27; + SV_Target.y = _28; + SV_Target.z = _29; + SV_Target.w = 1.0f; + +#if 1 + float2 grain_uv = SV_Position.xy; + SV_Target.rgb = ApplyUserGradingAndToneMap(SV_Target.rgb, grain_uv); +#endif + + return SV_Target; +} diff --git a/src/games/unrealengine/lutbuilders/sm6/lutbuilder_0xCF03A26C.cs_6_6.hlsl b/src/games/unrealengine/lutbuilders/sm6/lutbuilder_0xCF03A26C.cs_6_6.hlsl new file mode 100644 index 000000000..0d5bf181f --- /dev/null +++ b/src/games/unrealengine/lutbuilders/sm6/lutbuilder_0xCF03A26C.cs_6_6.hlsl @@ -0,0 +1,2120 @@ +// Found in Samson +#include "../../common.hlsl" + +struct FWorkingColorSpaceConstants { + float4 FWorkingColorSpaceConstants_000[4]; + float4 FWorkingColorSpaceConstants_064[4]; + float4 FWorkingColorSpaceConstants_128[4]; + float4 FWorkingColorSpaceConstants_192[4]; + float4 FWorkingColorSpaceConstants_256[4]; + float4 FWorkingColorSpaceConstants_320[4]; + int FWorkingColorSpaceConstants_384; +}; + +RWTexture3D u0 : register(u0); + +cbuffer cb0 : register(b0) { + float cb0_008x : packoffset(c008.x); + float cb0_008y : packoffset(c008.y); + float cb0_008z : packoffset(c008.z); + float cb0_008w : packoffset(c008.w); + float cb0_009x : packoffset(c009.x); + float cb0_010x : packoffset(c010.x); + float cb0_010y : packoffset(c010.y); + float cb0_010z : packoffset(c010.z); + float cb0_010w : packoffset(c010.w); + float cb0_011x : packoffset(c011.x); + float cb0_011y : packoffset(c011.y); + float cb0_011z : packoffset(c011.z); + float cb0_011w : packoffset(c011.w); + float cb0_012x : packoffset(c012.x); + float cb0_012y : packoffset(c012.y); + float cb0_012z : packoffset(c012.z); + float cb0_012w : packoffset(c012.w); + float cb0_015x : packoffset(c015.x); + float cb0_015y : packoffset(c015.y); + float cb0_015z : packoffset(c015.z); + float cb0_015w : packoffset(c015.w); + float cb0_016x : packoffset(c016.x); + float cb0_016y : packoffset(c016.y); + float cb0_016z : packoffset(c016.z); + float cb0_017x : packoffset(c017.x); + float cb0_017y : packoffset(c017.y); + float cb0_017z : packoffset(c017.z); + float cb0_017w : packoffset(c017.w); + float cb0_018x : packoffset(c018.x); + float cb0_018y : packoffset(c018.y); + float cb0_018z : packoffset(c018.z); + float cb0_018w : packoffset(c018.w); + float cb0_019x : packoffset(c019.x); + float cb0_019y : packoffset(c019.y); + float cb0_019z : packoffset(c019.z); + float cb0_019w : packoffset(c019.w); + float cb0_020x : packoffset(c020.x); + float cb0_020y : packoffset(c020.y); + float cb0_020z : packoffset(c020.z); + float cb0_020w : packoffset(c020.w); + float cb0_021x : packoffset(c021.x); + float cb0_021y : packoffset(c021.y); + float cb0_021z : packoffset(c021.z); + float cb0_021w : packoffset(c021.w); + float cb0_022x : packoffset(c022.x); + float cb0_022y : packoffset(c022.y); + float cb0_022z : packoffset(c022.z); + float cb0_022w : packoffset(c022.w); + float cb0_023x : packoffset(c023.x); + float cb0_023y : packoffset(c023.y); + float cb0_023z : packoffset(c023.z); + float cb0_023w : packoffset(c023.w); + float cb0_024x : packoffset(c024.x); + float cb0_024y : packoffset(c024.y); + float cb0_024z : packoffset(c024.z); + float cb0_024w : packoffset(c024.w); + float cb0_025x : packoffset(c025.x); + float cb0_025y : packoffset(c025.y); + float cb0_025z : packoffset(c025.z); + float cb0_025w : packoffset(c025.w); + float cb0_026x : packoffset(c026.x); + float cb0_026y : packoffset(c026.y); + float cb0_026z : packoffset(c026.z); + float cb0_026w : packoffset(c026.w); + float cb0_027x : packoffset(c027.x); + float cb0_027y : packoffset(c027.y); + float cb0_027z : packoffset(c027.z); + float cb0_027w : packoffset(c027.w); + float cb0_028x : packoffset(c028.x); + float cb0_028y : packoffset(c028.y); + float cb0_028z : packoffset(c028.z); + float cb0_028w : packoffset(c028.w); + float cb0_029x : packoffset(c029.x); + float cb0_029y : packoffset(c029.y); + float cb0_029z : packoffset(c029.z); + float cb0_029w : packoffset(c029.w); + float cb0_030x : packoffset(c030.x); + float cb0_030y : packoffset(c030.y); + float cb0_030z : packoffset(c030.z); + float cb0_030w : packoffset(c030.w); + float cb0_031x : packoffset(c031.x); + float cb0_031y : packoffset(c031.y); + float cb0_031z : packoffset(c031.z); + float cb0_031w : packoffset(c031.w); + float cb0_032x : packoffset(c032.x); + float cb0_032y : packoffset(c032.y); + float cb0_032z : packoffset(c032.z); + float cb0_032w : packoffset(c032.w); + float cb0_033x : packoffset(c033.x); + float cb0_033y : packoffset(c033.y); + float cb0_033z : packoffset(c033.z); + float cb0_033w : packoffset(c033.w); + float cb0_034x : packoffset(c034.x); + float cb0_034y : packoffset(c034.y); + float cb0_034z : packoffset(c034.z); + float cb0_034w : packoffset(c034.w); + float cb0_035x : packoffset(c035.x); + float cb0_035y : packoffset(c035.y); + float cb0_035z : packoffset(c035.z); + float cb0_035w : packoffset(c035.w); + float cb0_036x : packoffset(c036.x); + float cb0_036y : packoffset(c036.y); + float cb0_036z : packoffset(c036.z); + float cb0_036w : packoffset(c036.w); + float cb0_037x : packoffset(c037.x); + float cb0_037y : packoffset(c037.y); + float cb0_037z : packoffset(c037.z); + float cb0_037w : packoffset(c037.w); + float cb0_038x : packoffset(c038.x); + float cb0_038y : packoffset(c038.y); + float cb0_038z : packoffset(c038.z); + float cb0_038w : packoffset(c038.w); + float cb0_039x : packoffset(c039.x); + float cb0_039y : packoffset(c039.y); + float cb0_039z : packoffset(c039.z); + float cb0_039w : packoffset(c039.w); + float cb0_040x : packoffset(c040.x); + float cb0_040y : packoffset(c040.y); + int cb0_040w : packoffset(c040.w); + float cb0_041x : packoffset(c041.x); + float cb0_041y : packoffset(c041.y); + float cb0_041z : packoffset(c041.z); + float cb0_042y : packoffset(c042.y); + float cb0_042z : packoffset(c042.z); + int cb0_042w : packoffset(c042.w); + int cb0_043x : packoffset(c043.x); + float cb0_044x : packoffset(c044.x); + float cb0_044y : packoffset(c044.y); +}; + +cbuffer cb1 : register(b1) { + FWorkingColorSpaceConstants WorkingColorSpace_000 : packoffset(c000.x); +}; + +[numthreads(4, 4, 4)] +void main( + uint3 SV_DispatchThreadID: SV_DispatchThreadID, + uint3 SV_GroupID: SV_GroupID, + uint3 SV_GroupThreadID: SV_GroupThreadID, + uint SV_GroupIndex: SV_GroupIndex) { + float _9[6]; + float _10[6]; + float _11[6]; + float _12[6]; + float _13[6]; + float _14[6]; + float _15[6]; + float _16[6]; + float _17[6]; + float _18[6]; + float _19[6]; + float _20[6]; + float _32 = 0.5f / cb0_037x; + float _37 = cb0_037x + -1.0f; + float _38 = (cb0_037x * ((cb0_044x * (float((uint)SV_DispatchThreadID.x) + 0.5f)) - _32)) / _37; + float _39 = (cb0_037x * ((cb0_044y * (float((uint)SV_DispatchThreadID.y) + 0.5f)) - _32)) / _37; + float _41 = float((uint)SV_DispatchThreadID.z) / _37; + float _61; + float _62; + float _63; + float _64; + float _65; + float _66; + float _67; + float _68; + float _69; + float _127; + float _128; + float _129; + float _184; + float _391; + float _392; + float _393; + float _916; + float _949; + float _963; + float _1027; + float _1295; + float _1296; + float _1297; + float _1308; + float _1319; + float _1482; + float _1497; + float _1512; + float _1520; + float _1521; + float _1522; + float _1589; + float _1622; + float _1636; + float _1675; + float _1797; + float _1877; + float _1963; + float _2168; + float _2183; + float _2198; + float _2206; + float _2207; + float _2208; + float _2275; + float _2308; + float _2322; + float _2361; + float _2483; + float _2569; + float _2655; + float _2870; + float _2871; + float _2872; + if (!(cb0_043x == 1)) { + if (!(cb0_043x == 2)) { + if (!(cb0_043x == 3)) { + bool _50 = (cb0_043x == 4); + _61 = select(_50, 1.0f, 1.705051064491272f); + _62 = select(_50, 0.0f, -0.6217921376228333f); + _63 = select(_50, 0.0f, -0.0832589864730835f); + _64 = select(_50, 0.0f, -0.13025647401809692f); + _65 = select(_50, 1.0f, 1.140804648399353f); + _66 = select(_50, 0.0f, -0.010548308491706848f); + _67 = select(_50, 0.0f, -0.024003351107239723f); + _68 = select(_50, 0.0f, -0.1289689838886261f); + _69 = select(_50, 1.0f, 1.1529725790023804f); + } else { + _61 = 0.6954522132873535f; + _62 = 0.14067870378494263f; + _63 = 0.16386906802654266f; + _64 = 0.044794563204050064f; + _65 = 0.8596711158752441f; + _66 = 0.0955343171954155f; + _67 = -0.005525882821530104f; + _68 = 0.004025210160762072f; + _69 = 1.0015007257461548f; + } + } else { + _61 = 1.0258246660232544f; + _62 = -0.020053181797266006f; + _63 = -0.005771636962890625f; + _64 = -0.002234415616840124f; + _65 = 1.0045864582061768f; + _66 = -0.002352118492126465f; + _67 = -0.005013350863009691f; + _68 = -0.025290070101618767f; + _69 = 1.0303035974502563f; + } + } else { + _61 = 1.3792141675949097f; + _62 = -0.30886411666870117f; + _63 = -0.0703500509262085f; + _64 = -0.06933490186929703f; + _65 = 1.08229660987854f; + _66 = -0.012961871922016144f; + _67 = -0.0021590073592960835f; + _68 = -0.0454593189060688f; + _69 = 1.0476183891296387f; + } + [branch] + if ((uint)cb0_042w > (uint)2) { + float _80 = (pow(_38, 0.012683313339948654f)); + float _81 = (pow(_39, 0.012683313339948654f)); + float _82 = (pow(_41, 0.012683313339948654f)); + _127 = (exp2(log2(max(0.0f, (_80 + -0.8359375f)) / (18.8515625f - (_80 * 18.6875f))) * 6.277394771575928f) * 100.0f); + _128 = (exp2(log2(max(0.0f, (_81 + -0.8359375f)) / (18.8515625f - (_81 * 18.6875f))) * 6.277394771575928f) * 100.0f); + _129 = (exp2(log2(max(0.0f, (_82 + -0.8359375f)) / (18.8515625f - (_82 * 18.6875f))) * 6.277394771575928f) * 100.0f); + } else { + _127 = ((exp2((_38 + -0.4340175986289978f) * 14.0f) * 0.18000000715255737f) + -0.002667719265446067f); + _128 = ((exp2((_39 + -0.4340175986289978f) * 14.0f) * 0.18000000715255737f) + -0.002667719265446067f); + _129 = ((exp2((_41 + -0.4340175986289978f) * 14.0f) * 0.18000000715255737f) + -0.002667719265446067f); + } + if (!(abs(cb0_037y + -6500.0f) > 9.99999993922529e-09f)) { + [branch] + if (!(abs(cb0_037z) > 9.99999993922529e-09f)) { + _391 = _127; + _392 = _128; + _393 = _129; + float _408 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _393, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _392, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _391))); + float _411 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _393, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _392, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _391))); + float _414 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _393, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _392, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _391))); + + SetUngradedAP1(float3(_408, _411, _414)); + + float _415 = dot(float3(_408, _411, _414), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + float _419 = (_408 / _415) + -1.0f; + float _420 = (_411 / _415) + -1.0f; + float _421 = (_414 / _415) + -1.0f; + float _433 = (1.0f - exp2(((_415 * _415) * -4.0f) * cb0_038w)) * (1.0f - exp2(dot(float3(_419, _420, _421), float3(_419, _420, _421)) * -4.0f)); + float _449 = ((mad(-0.06368321925401688f, _414, mad(-0.3292922377586365f, _411, (_408 * 1.3704125881195068f))) - _408) * _433) + _408; + float _450 = ((mad(-0.010861365124583244f, _414, mad(1.0970927476882935f, _411, (_408 * -0.08343357592821121f))) - _411) * _433) + _411; + float _451 = ((mad(1.2036951780319214f, _414, mad(-0.09862580895423889f, _411, (_408 * -0.02579331398010254f))) - _414) * _433) + _414; + float _452 = dot(float3(_449, _450, _451), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + float _466 = cb0_021w + cb0_026w; + float _480 = cb0_020w * cb0_025w; + float _494 = cb0_019w * cb0_024w; + float _508 = cb0_018w * cb0_023w; + float _522 = cb0_017w * cb0_022w; + float _526 = _449 - _452; + float _527 = _450 - _452; + float _528 = _451 - _452; + float _585 = saturate(_452 / cb0_037w); + float _589 = (_585 * _585) * (3.0f - (_585 * 2.0f)); + float _590 = 1.0f - _589; + float _599 = cb0_021w + cb0_036w; + float _608 = cb0_020w * cb0_035w; + float _617 = cb0_019w * cb0_034w; + float _626 = cb0_018w * cb0_033w; + float _635 = cb0_017w * cb0_032w; + float _698 = saturate((_452 - cb0_038x) / (cb0_038y - cb0_038x)); + float _702 = (_698 * _698) * (3.0f - (_698 * 2.0f)); + float _711 = cb0_021w + cb0_031w; + float _720 = cb0_020w * cb0_030w; + float _729 = cb0_019w * cb0_029w; + float _738 = cb0_018w * cb0_028w; + float _747 = cb0_017w * cb0_027w; + float _805 = _589 - _702; + float _816 = ((_702 * (((cb0_021x + cb0_036x) + _599) + (((cb0_020x * cb0_035x) * _608) * exp2(log2(exp2(((cb0_018x * cb0_033x) * _626) * log2(max(0.0f, ((((cb0_017x * cb0_032x) * _635) * _526) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019x * cb0_034x) * _617)))))) + (_590 * (((cb0_021x + cb0_026x) + _466) + (((cb0_020x * cb0_025x) * _480) * exp2(log2(exp2(((cb0_018x * cb0_023x) * _508) * log2(max(0.0f, ((((cb0_017x * cb0_022x) * _522) * _526) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019x * cb0_024x) * _494))))))) + ((((cb0_021x + cb0_031x) + _711) + (((cb0_020x * cb0_030x) * _720) * exp2(log2(exp2(((cb0_018x * cb0_028x) * _738) * log2(max(0.0f, ((((cb0_017x * cb0_027x) * _747) * _526) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019x * cb0_029x) * _729))))) * _805); + float _818 = ((_702 * (((cb0_021y + cb0_036y) + _599) + (((cb0_020y * cb0_035y) * _608) * exp2(log2(exp2(((cb0_018y * cb0_033y) * _626) * log2(max(0.0f, ((((cb0_017y * cb0_032y) * _635) * _527) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019y * cb0_034y) * _617)))))) + (_590 * (((cb0_021y + cb0_026y) + _466) + (((cb0_020y * cb0_025y) * _480) * exp2(log2(exp2(((cb0_018y * cb0_023y) * _508) * log2(max(0.0f, ((((cb0_017y * cb0_022y) * _522) * _527) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019y * cb0_024y) * _494))))))) + ((((cb0_021y + cb0_031y) + _711) + (((cb0_020y * cb0_030y) * _720) * exp2(log2(exp2(((cb0_018y * cb0_028y) * _738) * log2(max(0.0f, ((((cb0_017y * cb0_027y) * _747) * _527) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019y * cb0_029y) * _729))))) * _805); + float _820 = ((_702 * (((cb0_021z + cb0_036z) + _599) + (((cb0_020z * cb0_035z) * _608) * exp2(log2(exp2(((cb0_018z * cb0_033z) * _626) * log2(max(0.0f, ((((cb0_017z * cb0_032z) * _635) * _528) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019z * cb0_034z) * _617)))))) + (_590 * (((cb0_021z + cb0_026z) + _466) + (((cb0_020z * cb0_025z) * _480) * exp2(log2(exp2(((cb0_018z * cb0_023z) * _508) * log2(max(0.0f, ((((cb0_017z * cb0_022z) * _522) * _528) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019z * cb0_024z) * _494))))))) + ((((cb0_021z + cb0_031z) + _711) + (((cb0_020z * cb0_030z) * _720) * exp2(log2(exp2(((cb0_018z * cb0_028z) * _738) * log2(max(0.0f, ((((cb0_017z * cb0_027z) * _747) * _528) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019z * cb0_029z) * _729))))) * _805); + + SetUntonemappedAP1(float3(_816, _818, _820)); + + float _856 = ((mad(0.061360642313957214f, _820, mad(-4.540197551250458e-09f, _818, (_816 * 0.9386394023895264f))) - _816) * cb0_038z) + _816; + float _857 = ((mad(0.169205904006958f, _820, mad(0.8307942152023315f, _818, (_816 * 6.775371730327606e-08f))) - _818) * cb0_038z) + _818; + float _858 = (mad(-2.3283064365386963e-10f, _818, (_816 * -9.313225746154785e-10f)) * cb0_038z) + _820; + float _861 = mad(0.16386905312538147f, _858, mad(0.14067868888378143f, _857, (_856 * 0.6954522132873535f))); + float _864 = mad(0.0955343246459961f, _858, mad(0.8596711158752441f, _857, (_856 * 0.044794581830501556f))); + float _867 = mad(1.0015007257461548f, _858, mad(0.004025210160762072f, _857, (_856 * -0.005525882821530104f))); + float _871 = max(max(_861, _864), _867); + float _876 = (max(_871, 1.000000013351432e-10f) - max(min(min(_861, _864), _867), 1.000000013351432e-10f)) / max(_871, 0.009999999776482582f); + float _889 = ((_864 + _861) + _867) + (sqrt((((_867 - _864) * _867) + ((_864 - _861) * _864)) + ((_861 - _867) * _861)) * 1.75f); + float _890 = _889 * 0.3333333432674408f; + float _891 = _876 + -0.4000000059604645f; + float _892 = _891 * 5.0f; + float _896 = max((1.0f - abs(_891 * 2.5f)), 0.0f); + float _907 = ((float((int)(((int)(uint)((bool)(_892 > 0.0f))) - ((int)(uint)((bool)(_892 < 0.0f))))) * (1.0f - (_896 * _896))) + 1.0f) * 0.02500000037252903f; + do { + if (!(_890 <= 0.0533333346247673f)) { + if (!(_890 >= 0.1599999964237213f)) { + _916 = (((0.23999999463558197f / _889) + -0.5f) * _907); + } else { + _916 = 0.0f; + } + } else { + _916 = _907; + } + float _917 = _916 + 1.0f; + float _918 = _917 * _861; + float _919 = _917 * _864; + float _920 = _917 * _867; + do { + if (!((bool)(_918 == _919) && (bool)(_919 == _920))) { + float _927 = ((_918 * 2.0f) - _919) - _920; + float _930 = ((_864 - _867) * 1.7320507764816284f) * _917; + float _932 = atan(_930 / _927); + bool _935 = (_927 < 0.0f); + bool _936 = (_927 == 0.0f); + bool _937 = (_930 >= 0.0f); + bool _938 = (_930 < 0.0f); + _949 = select((_937 && _936), 90.0f, select((_938 && _936), -90.0f, (select((_938 && _935), (_932 + -3.1415927410125732f), select((_937 && _935), (_932 + 3.1415927410125732f), _932)) * 57.2957763671875f))); + } else { + _949 = 0.0f; + } + float _954 = min(max(select((_949 < 0.0f), (_949 + 360.0f), _949), 0.0f), 360.0f); + do { + if (_954 < -180.0f) { + _963 = (_954 + 360.0f); + } else { + if (_954 > 180.0f) { + _963 = (_954 + -360.0f); + } else { + _963 = _954; + } + } + float _967 = saturate(1.0f - abs(_963 * 0.014814814552664757f)); + float _971 = (_967 * _967) * (3.0f - (_967 * 2.0f)); + float _977 = ((_971 * _971) * ((_876 * 0.18000000715255737f) * (0.029999999329447746f - _918))) + _918; + float _987 = max(0.0f, mad(-0.21492856740951538f, _920, mad(-0.2365107536315918f, _919, (_977 * 1.4514392614364624f)))); + float _988 = max(0.0f, mad(-0.09967592358589172f, _920, mad(1.17622971534729f, _919, (_977 * -0.07655377686023712f)))); + float _989 = max(0.0f, mad(0.9977163076400757f, _920, mad(-0.006032449658960104f, _919, (_977 * 0.008316148072481155f)))); + float _990 = dot(float3(_987, _988, _989), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + float _1005 = (cb0_040x + 1.0f) - cb0_039z; + float _1007 = cb0_040y + 1.0f; + float _1009 = _1007 - cb0_039w; + do { + if (cb0_039z > 0.800000011920929f) { + _1027 = (((0.8199999928474426f - cb0_039z) / cb0_039y) + -0.7447274923324585f); + } else { + float _1018 = (cb0_040x + 0.18000000715255737f) / _1005; + _1027 = (-0.7447274923324585f - ((log2(_1018 / (2.0f - _1018)) * 0.3465735912322998f) * (_1005 / cb0_039y))); + } + float _1030 = ((1.0f - cb0_039z) / cb0_039y) - _1027; + float _1032 = (cb0_039w / cb0_039y) - _1030; + float _1036 = log2(lerp(_990, _987, 0.9599999785423279f)) * 0.3010300099849701f; + float _1037 = log2(lerp(_990, _988, 0.9599999785423279f)) * 0.3010300099849701f; + float _1038 = log2(lerp(_990, _989, 0.9599999785423279f)) * 0.3010300099849701f; + float _1042 = cb0_039y * (_1036 + _1030); + float _1043 = cb0_039y * (_1037 + _1030); + float _1044 = cb0_039y * (_1038 + _1030); + float _1045 = _1005 * 2.0f; + float _1047 = (cb0_039y * -2.0f) / _1005; + float _1048 = _1036 - _1027; + float _1049 = _1037 - _1027; + float _1050 = _1038 - _1027; + float _1069 = _1009 * 2.0f; + float _1071 = (cb0_039y * 2.0f) / _1009; + float _1096 = select((_1036 < _1027), ((_1045 / (exp2((_1048 * 1.4426950216293335f) * _1047) + 1.0f)) - cb0_040x), _1042); + float _1097 = select((_1037 < _1027), ((_1045 / (exp2((_1049 * 1.4426950216293335f) * _1047) + 1.0f)) - cb0_040x), _1043); + float _1098 = select((_1038 < _1027), ((_1045 / (exp2((_1050 * 1.4426950216293335f) * _1047) + 1.0f)) - cb0_040x), _1044); + float _1105 = _1032 - _1027; + float _1109 = saturate(_1048 / _1105); + float _1110 = saturate(_1049 / _1105); + float _1111 = saturate(_1050 / _1105); + bool _1112 = (_1032 < _1027); + float _1116 = select(_1112, (1.0f - _1109), _1109); + float _1117 = select(_1112, (1.0f - _1110), _1110); + float _1118 = select(_1112, (1.0f - _1111), _1111); + float _1137 = (((_1116 * _1116) * (select((_1036 > _1032), (_1007 - (_1069 / (exp2(((_1036 - _1032) * 1.4426950216293335f) * _1071) + 1.0f))), _1042) - _1096)) * (3.0f - (_1116 * 2.0f))) + _1096; + float _1138 = (((_1117 * _1117) * (select((_1037 > _1032), (_1007 - (_1069 / (exp2(((_1037 - _1032) * 1.4426950216293335f) * _1071) + 1.0f))), _1043) - _1097)) * (3.0f - (_1117 * 2.0f))) + _1097; + float _1139 = (((_1118 * _1118) * (select((_1038 > _1032), (_1007 - (_1069 / (exp2(((_1038 - _1032) * 1.4426950216293335f) * _1071) + 1.0f))), _1044) - _1098)) * (3.0f - (_1118 * 2.0f))) + _1098; + float _1140 = dot(float3(_1137, _1138, _1139), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + float _1160 = (cb0_039x * (max(0.0f, (lerp(_1140, _1137, 0.9300000071525574f))) - _856)) + _856; + float _1161 = (cb0_039x * (max(0.0f, (lerp(_1140, _1138, 0.9300000071525574f))) - _857)) + _857; + float _1162 = (cb0_039x * (max(0.0f, (lerp(_1140, _1139, 0.9300000071525574f))) - _858)) + _858; + float _1178 = ((mad(-0.06537103652954102f, _1162, mad(1.451815478503704e-06f, _1161, (_1160 * 1.065374732017517f))) - _1160) * cb0_038z) + _1160; + float _1179 = ((mad(-0.20366770029067993f, _1162, mad(1.2036634683609009f, _1161, (_1160 * -2.57161445915699e-07f))) - _1161) * cb0_038z) + _1161; + float _1180 = ((mad(0.9999996423721313f, _1162, mad(2.0954757928848267e-08f, _1161, (_1160 * 1.862645149230957e-08f))) - _1162) * cb0_038z) + _1162; + + SetTonemappedAP1(_1178, _1179, _1180); + + float _1190 = max(0.0f, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].z), _1180, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].y), _1179, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].x) * _1178)))); + float _1191 = max(0.0f, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].z), _1180, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].y), _1179, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].x) * _1178)))); + float _1192 = max(0.0f, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].z), _1180, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].y), _1179, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].x) * _1178)))); + float _1218 = cb0_016x * (((cb0_041y + (cb0_041x * _1190)) * _1190) + cb0_041z); + float _1219 = cb0_016y * (((cb0_041y + (cb0_041x * _1191)) * _1191) + cb0_041z); + float _1220 = cb0_016z * (((cb0_041y + (cb0_041x * _1192)) * _1192) + cb0_041z); + float _1227 = ((cb0_015x - _1218) * cb0_015w) + _1218; + float _1228 = ((cb0_015y - _1219) * cb0_015w) + _1219; + float _1229 = ((cb0_015z - _1220) * cb0_015w) + _1220; + float _1230 = cb0_016x * mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].z), _820, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].y), _818, (_816 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].x)))); + float _1231 = cb0_016y * mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].z), _820, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].y), _818, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].x) * _816))); + float _1232 = cb0_016z * mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].z), _820, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].y), _818, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].x) * _816))); + float _1239 = ((cb0_015x - _1230) * cb0_015w) + _1230; + float _1240 = ((cb0_015y - _1231) * cb0_015w) + _1231; + float _1241 = ((cb0_015z - _1232) * cb0_015w) + _1232; + float _1253 = exp2(log2(max(0.0f, _1227)) * cb0_042y); + float _1254 = exp2(log2(max(0.0f, _1228)) * cb0_042y); + float _1255 = exp2(log2(max(0.0f, _1229)) * cb0_042y); + + if (RENODX_TONE_MAP_TYPE != 0) { + u0[SV_DispatchThreadID] = GenerateOutput(float3(_1253, _1254, _1255), cb0_042w); + return; + } + + do { + [branch] + if (cb0_042w == 0) { + do { + if (WorkingColorSpace_000.FWorkingColorSpaceConstants_384 == 0) { + float _1278 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _1253))); + float _1281 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _1253))); + float _1284 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _1253))); + _1295 = mad(_63, _1284, mad(_62, _1281, (_1278 * _61))); + _1296 = mad(_66, _1284, mad(_65, _1281, (_1278 * _64))); + _1297 = mad(_69, _1284, mad(_68, _1281, (_1278 * _67))); + } else { + _1295 = _1253; + _1296 = _1254; + _1297 = _1255; + } + do { + if (_1295 < 0.0031306699384003878f) { + _1308 = (_1295 * 12.920000076293945f); + } else { + _1308 = (((pow(_1295, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + do { + if (_1296 < 0.0031306699384003878f) { + _1319 = (_1296 * 12.920000076293945f); + } else { + _1319 = (((pow(_1296, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + if (_1297 < 0.0031306699384003878f) { + _2870 = _1308; + _2871 = _1319; + _2872 = (_1297 * 12.920000076293945f); + } else { + _2870 = _1308; + _2871 = _1319; + _2872 = (((pow(_1297, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + } while (false); + } while (false); + } while (false); + } else { + if (cb0_042w == 1) { + float _1346 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _1253))); + float _1349 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _1253))); + float _1352 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _1253))); + float _1355 = mad(_63, _1352, mad(_62, _1349, (_1346 * _61))); + float _1358 = mad(_66, _1352, mad(_65, _1349, (_1346 * _64))); + float _1361 = mad(_69, _1352, mad(_68, _1349, (_1346 * _67))); + _2870 = min((_1355 * 4.5f), ((exp2(log2(max(_1355, 0.017999999225139618f)) * 0.44999998807907104f) * 1.0989999771118164f) + -0.0989999994635582f)); + _2871 = min((_1358 * 4.5f), ((exp2(log2(max(_1358, 0.017999999225139618f)) * 0.44999998807907104f) * 1.0989999771118164f) + -0.0989999994635582f)); + _2872 = min((_1361 * 4.5f), ((exp2(log2(max(_1361, 0.017999999225139618f)) * 0.44999998807907104f) * 1.0989999771118164f) + -0.0989999994635582f)); + } else { + if ((uint)((uint)((int)(cb0_042w) + -3u)) < (uint)2) { + _9[0] = cb0_010x; + _9[1] = cb0_010y; + _9[2] = cb0_010z; + _9[3] = cb0_010w; + _9[4] = cb0_012x; + _9[5] = cb0_012x; + float _1430 = cb0_012z * _1239; + float _1431 = cb0_012z * _1240; + float _1432 = cb0_012z * _1241; + float _1435 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].z), _1432, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].y), _1431, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].x) * _1430))); + float _1438 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].z), _1432, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].y), _1431, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].x) * _1430))); + float _1441 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].z), _1432, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].y), _1431, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].x) * _1430))); + float _1444 = mad(-0.21492856740951538f, _1441, mad(-0.2365107536315918f, _1438, (_1435 * 1.4514392614364624f))); + float _1447 = mad(-0.09967592358589172f, _1441, mad(1.17622971534729f, _1438, (_1435 * -0.07655377686023712f))); + float _1450 = mad(0.9977163076400757f, _1441, mad(-0.006032449658960104f, _1438, (_1435 * 0.008316148072481155f))); + float _1452 = max(_1444, max(_1447, _1450)); + do { + if (!(_1452 < 1.000000013351432e-10f)) { + if (!(((bool)((bool)(_1435 < 0.0f) || (bool)(_1438 < 0.0f))) || (bool)(_1441 < 0.0f))) { + float _1462 = abs(_1452); + float _1463 = (_1452 - _1444) / _1462; + float _1465 = (_1452 - _1447) / _1462; + float _1467 = (_1452 - _1450) / _1462; + do { + if (!(_1463 < 0.8149999976158142f)) { + float _1470 = _1463 + -0.8149999976158142f; + _1482 = ((_1470 / exp2(log2(exp2(log2(_1470 * 3.0552830696105957f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8149999976158142f); + } else { + _1482 = _1463; + } + do { + if (!(_1465 < 0.8029999732971191f)) { + float _1485 = _1465 + -0.8029999732971191f; + _1497 = ((_1485 / exp2(log2(exp2(log2(_1485 * 3.4972610473632812f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8029999732971191f); + } else { + _1497 = _1465; + } + do { + if (!(_1467 < 0.8799999952316284f)) { + float _1500 = _1467 + -0.8799999952316284f; + _1512 = ((_1500 / exp2(log2(exp2(log2(_1500 * 6.810994625091553f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8799999952316284f); + } else { + _1512 = _1467; + } + _1520 = (_1452 - (_1462 * _1482)); + _1521 = (_1452 - (_1462 * _1497)); + _1522 = (_1452 - (_1462 * _1512)); + } while (false); + } while (false); + } while (false); + } else { + _1520 = _1444; + _1521 = _1447; + _1522 = _1450; + } + } else { + _1520 = _1444; + _1521 = _1447; + _1522 = _1450; + } + float _1538 = ((mad(0.16386906802654266f, _1522, mad(0.14067870378494263f, _1521, (_1520 * 0.6954522132873535f))) - _1435) * cb0_012w) + _1435; + float _1539 = ((mad(0.0955343171954155f, _1522, mad(0.8596711158752441f, _1521, (_1520 * 0.044794563204050064f))) - _1438) * cb0_012w) + _1438; + float _1540 = ((mad(1.0015007257461548f, _1522, mad(0.004025210160762072f, _1521, (_1520 * -0.005525882821530104f))) - _1441) * cb0_012w) + _1441; + float _1544 = max(max(_1538, _1539), _1540); + float _1549 = (max(_1544, 1.000000013351432e-10f) - max(min(min(_1538, _1539), _1540), 1.000000013351432e-10f)) / max(_1544, 0.009999999776482582f); + float _1562 = ((_1539 + _1538) + _1540) + (sqrt((((_1540 - _1539) * _1540) + ((_1539 - _1538) * _1539)) + ((_1538 - _1540) * _1538)) * 1.75f); + float _1563 = _1562 * 0.3333333432674408f; + float _1564 = _1549 + -0.4000000059604645f; + float _1565 = _1564 * 5.0f; + float _1569 = max((1.0f - abs(_1564 * 2.5f)), 0.0f); + float _1580 = ((float((int)(((int)(uint)((bool)(_1565 > 0.0f))) - ((int)(uint)((bool)(_1565 < 0.0f))))) * (1.0f - (_1569 * _1569))) + 1.0f) * 0.02500000037252903f; + do { + if (!(_1563 <= 0.0533333346247673f)) { + if (!(_1563 >= 0.1599999964237213f)) { + _1589 = (((0.23999999463558197f / _1562) + -0.5f) * _1580); + } else { + _1589 = 0.0f; + } + } else { + _1589 = _1580; + } + float _1590 = _1589 + 1.0f; + float _1591 = _1590 * _1538; + float _1592 = _1590 * _1539; + float _1593 = _1590 * _1540; + do { + if (!((bool)(_1591 == _1592) && (bool)(_1592 == _1593))) { + float _1600 = ((_1591 * 2.0f) - _1592) - _1593; + float _1603 = ((_1539 - _1540) * 1.7320507764816284f) * _1590; + float _1605 = atan(_1603 / _1600); + bool _1608 = (_1600 < 0.0f); + bool _1609 = (_1600 == 0.0f); + bool _1610 = (_1603 >= 0.0f); + bool _1611 = (_1603 < 0.0f); + _1622 = select((_1610 && _1609), 90.0f, select((_1611 && _1609), -90.0f, (select((_1611 && _1608), (_1605 + -3.1415927410125732f), select((_1610 && _1608), (_1605 + 3.1415927410125732f), _1605)) * 57.2957763671875f))); + } else { + _1622 = 0.0f; + } + float _1627 = min(max(select((_1622 < 0.0f), (_1622 + 360.0f), _1622), 0.0f), 360.0f); + do { + if (_1627 < -180.0f) { + _1636 = (_1627 + 360.0f); + } else { + if (_1627 > 180.0f) { + _1636 = (_1627 + -360.0f); + } else { + _1636 = _1627; + } + } + do { + if ((bool)(_1636 > -67.5f) && (bool)(_1636 < 67.5f)) { + float _1642 = (_1636 + 67.5f) * 0.029629629105329514f; + int _1643 = int(_1642); + float _1645 = _1642 - float((int)(_1643)); + float _1646 = _1645 * _1645; + float _1647 = _1646 * _1645; + if (_1643 == 3) { + _1675 = (((0.1666666716337204f - (_1645 * 0.5f)) + (_1646 * 0.5f)) - (_1647 * 0.1666666716337204f)); + } else { + if (_1643 == 2) { + _1675 = ((0.6666666865348816f - _1646) + (_1647 * 0.5f)); + } else { + if (_1643 == 1) { + _1675 = (((_1647 * -0.5f) + 0.1666666716337204f) + ((_1646 + _1645) * 0.5f)); + } else { + _1675 = select((_1643 == 0), (_1647 * 0.1666666716337204f), 0.0f); + } + } + } + } else { + _1675 = 0.0f; + } + float _1684 = min(max(((((_1549 * 0.27000001072883606f) * (0.029999999329447746f - _1591)) * _1675) + _1591), 0.0f), 65535.0f); + float _1685 = min(max(_1592, 0.0f), 65535.0f); + float _1686 = min(max(_1593, 0.0f), 65535.0f); + float _1699 = min(max(mad(-0.21492856740951538f, _1686, mad(-0.2365107536315918f, _1685, (_1684 * 1.4514392614364624f))), 0.0f), 65504.0f); + float _1700 = min(max(mad(-0.09967592358589172f, _1686, mad(1.17622971534729f, _1685, (_1684 * -0.07655377686023712f))), 0.0f), 65504.0f); + float _1701 = min(max(mad(0.9977163076400757f, _1686, mad(-0.006032449658960104f, _1685, (_1684 * 0.008316148072481155f))), 0.0f), 65504.0f); + float _1702 = dot(float3(_1699, _1700, _1701), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + _16[0] = cb0_010x; + _16[1] = cb0_010y; + _16[2] = cb0_010z; + _16[3] = cb0_010w; + _16[4] = cb0_012x; + _16[5] = cb0_012x; + _17[0] = cb0_011x; + _17[1] = cb0_011y; + _17[2] = cb0_011z; + _17[3] = cb0_011w; + _17[4] = cb0_012y; + _17[5] = cb0_012y; + float _1725 = log2(max((lerp(_1702, _1699, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _1726 = _1725 * 0.3010300099849701f; + float _1727 = log2(cb0_008x); + float _1728 = _1727 * 0.3010300099849701f; + do { + if (!(!(_1726 <= _1728))) { + _1797 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _1735 = log2(cb0_009x); + float _1736 = _1735 * 0.3010300099849701f; + if ((bool)(_1726 > _1728) && (bool)(_1726 < _1736)) { + float _1744 = ((_1725 - _1727) * 0.9030900001525879f) / ((_1735 - _1727) * 0.3010300099849701f); + int _1745 = int(_1744); + float _1747 = _1744 - float((int)(_1745)); + float _1749 = _16[_1745]; + float _1752 = _16[(_1745 + 1)]; + float _1757 = _1749 * 0.5f; + _1797 = dot(float3((_1747 * _1747), _1747, 1.0f), float3(mad((_16[(_1745 + 2)]), 0.5f, mad(_1752, -1.0f, _1757)), (_1752 - _1749), mad(_1752, 0.5f, _1757))); + } else { + do { + if (!(!(_1726 >= _1736))) { + float _1766 = log2(cb0_008z); + if (_1726 < (_1766 * 0.3010300099849701f)) { + float _1774 = ((_1725 - _1735) * 0.9030900001525879f) / ((_1766 - _1735) * 0.3010300099849701f); + int _1775 = int(_1774); + float _1777 = _1774 - float((int)(_1775)); + float _1779 = _17[_1775]; + float _1782 = _17[(_1775 + 1)]; + float _1787 = _1779 * 0.5f; + _1797 = dot(float3((_1777 * _1777), _1777, 1.0f), float3(mad((_17[(_1775 + 2)]), 0.5f, mad(_1782, -1.0f, _1787)), (_1782 - _1779), mad(_1782, 0.5f, _1787))); + break; + } + } + _1797 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + _18[0] = cb0_011x; + _18[1] = cb0_011y; + _18[2] = cb0_011z; + _18[3] = cb0_011w; + _18[4] = cb0_012y; + _18[5] = cb0_012y; + float _1807 = log2(max((lerp(_1702, _1700, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _1808 = _1807 * 0.3010300099849701f; + do { + if (!(!(_1808 <= _1728))) { + _1877 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _1815 = log2(cb0_009x); + float _1816 = _1815 * 0.3010300099849701f; + if ((bool)(_1808 > _1728) && (bool)(_1808 < _1816)) { + float _1824 = ((_1807 - _1727) * 0.9030900001525879f) / ((_1815 - _1727) * 0.3010300099849701f); + int _1825 = int(_1824); + float _1827 = _1824 - float((int)(_1825)); + float _1829 = _9[_1825]; + float _1832 = _9[(_1825 + 1)]; + float _1837 = _1829 * 0.5f; + _1877 = dot(float3((_1827 * _1827), _1827, 1.0f), float3(mad((_9[(_1825 + 2)]), 0.5f, mad(_1832, -1.0f, _1837)), (_1832 - _1829), mad(_1832, 0.5f, _1837))); + } else { + do { + if (!(!(_1808 >= _1816))) { + float _1846 = log2(cb0_008z); + if (_1808 < (_1846 * 0.3010300099849701f)) { + float _1854 = ((_1807 - _1815) * 0.9030900001525879f) / ((_1846 - _1815) * 0.3010300099849701f); + int _1855 = int(_1854); + float _1857 = _1854 - float((int)(_1855)); + float _1859 = _18[_1855]; + float _1862 = _18[(_1855 + 1)]; + float _1867 = _1859 * 0.5f; + _1877 = dot(float3((_1857 * _1857), _1857, 1.0f), float3(mad((_18[(_1855 + 2)]), 0.5f, mad(_1862, -1.0f, _1867)), (_1862 - _1859), mad(_1862, 0.5f, _1867))); + break; + } + } + _1877 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + _19[0] = cb0_010x; + _19[1] = cb0_010y; + _19[2] = cb0_010z; + _19[3] = cb0_010w; + _19[4] = cb0_012x; + _19[5] = cb0_012x; + _20[0] = cb0_011x; + _20[1] = cb0_011y; + _20[2] = cb0_011z; + _20[3] = cb0_011w; + _20[4] = cb0_012y; + _20[5] = cb0_012y; + float _1893 = log2(max((lerp(_1702, _1701, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _1894 = _1893 * 0.3010300099849701f; + do { + if (!(!(_1894 <= _1728))) { + _1963 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _1901 = log2(cb0_009x); + float _1902 = _1901 * 0.3010300099849701f; + if ((bool)(_1894 > _1728) && (bool)(_1894 < _1902)) { + float _1910 = ((_1893 - _1727) * 0.9030900001525879f) / ((_1901 - _1727) * 0.3010300099849701f); + int _1911 = int(_1910); + float _1913 = _1910 - float((int)(_1911)); + float _1915 = _19[_1911]; + float _1918 = _19[(_1911 + 1)]; + float _1923 = _1915 * 0.5f; + _1963 = dot(float3((_1913 * _1913), _1913, 1.0f), float3(mad((_19[(_1911 + 2)]), 0.5f, mad(_1918, -1.0f, _1923)), (_1918 - _1915), mad(_1918, 0.5f, _1923))); + } else { + do { + if (!(!(_1894 >= _1902))) { + float _1932 = log2(cb0_008z); + if (_1894 < (_1932 * 0.3010300099849701f)) { + float _1940 = ((_1893 - _1901) * 0.9030900001525879f) / ((_1932 - _1901) * 0.3010300099849701f); + int _1941 = int(_1940); + float _1943 = _1940 - float((int)(_1941)); + float _1945 = _20[_1941]; + float _1948 = _20[(_1941 + 1)]; + float _1953 = _1945 * 0.5f; + _1963 = dot(float3((_1943 * _1943), _1943, 1.0f), float3(mad((_20[(_1941 + 2)]), 0.5f, mad(_1948, -1.0f, _1953)), (_1948 - _1945), mad(_1948, 0.5f, _1953))); + break; + } + } + _1963 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + float _1967 = cb0_008w - cb0_008y; + float _1968 = (exp2(_1797 * 3.321928024291992f) - cb0_008y) / _1967; + float _1970 = (exp2(_1877 * 3.321928024291992f) - cb0_008y) / _1967; + float _1972 = (exp2(_1963 * 3.321928024291992f) - cb0_008y) / _1967; + float _1975 = mad(0.15618768334388733f, _1972, mad(0.13400420546531677f, _1970, (_1968 * 0.6624541878700256f))); + float _1978 = mad(0.053689517080783844f, _1972, mad(0.6740817427635193f, _1970, (_1968 * 0.2722287178039551f))); + float _1981 = mad(1.0103391408920288f, _1972, mad(0.00406073359772563f, _1970, (_1968 * -0.005574649665504694f))); + float _1994 = min(max(mad(-0.23642469942569733f, _1981, mad(-0.32480329275131226f, _1978, (_1975 * 1.6410233974456787f))), 0.0f), 1.0f); + float _1995 = min(max(mad(0.016756348311901093f, _1981, mad(1.6153316497802734f, _1978, (_1975 * -0.663662850856781f))), 0.0f), 1.0f); + float _1996 = min(max(mad(0.9883948564529419f, _1981, mad(-0.008284442126750946f, _1978, (_1975 * 0.011721894145011902f))), 0.0f), 1.0f); + float _1999 = mad(0.15618768334388733f, _1996, mad(0.13400420546531677f, _1995, (_1994 * 0.6624541878700256f))); + float _2002 = mad(0.053689517080783844f, _1996, mad(0.6740817427635193f, _1995, (_1994 * 0.2722287178039551f))); + float _2005 = mad(1.0103391408920288f, _1996, mad(0.00406073359772563f, _1995, (_1994 * -0.005574649665504694f))); + float _2027 = min(max((min(max(mad(-0.23642469942569733f, _2005, mad(-0.32480329275131226f, _2002, (_1999 * 1.6410233974456787f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f); + float _2028 = min(max((min(max(mad(0.016756348311901093f, _2005, mad(1.6153316497802734f, _2002, (_1999 * -0.663662850856781f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f); + float _2029 = min(max((min(max(mad(0.9883948564529419f, _2005, mad(-0.008284442126750946f, _2002, (_1999 * 0.011721894145011902f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f); + float _2048 = exp2(log2(mad(_63, _2029, mad(_62, _2028, (_2027 * _61))) * 9.999999747378752e-05f) * 0.1593017578125f); + float _2049 = exp2(log2(mad(_66, _2029, mad(_65, _2028, (_2027 * _64))) * 9.999999747378752e-05f) * 0.1593017578125f); + float _2050 = exp2(log2(mad(_69, _2029, mad(_68, _2028, (_2027 * _67))) * 9.999999747378752e-05f) * 0.1593017578125f); + _2870 = exp2(log2((1.0f / ((_2048 * 18.6875f) + 1.0f)) * ((_2048 * 18.8515625f) + 0.8359375f)) * 78.84375f); + _2871 = exp2(log2((1.0f / ((_2049 * 18.6875f) + 1.0f)) * ((_2049 * 18.8515625f) + 0.8359375f)) * 78.84375f); + _2872 = exp2(log2((1.0f / ((_2050 * 18.6875f) + 1.0f)) * ((_2050 * 18.8515625f) + 0.8359375f)) * 78.84375f); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } else { + if ((uint)((uint)((int)(cb0_042w) + -5u)) < (uint)2) { + float _2116 = cb0_012z * _1239; + float _2117 = cb0_012z * _1240; + float _2118 = cb0_012z * _1241; + float _2121 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].z), _2118, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].y), _2117, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].x) * _2116))); + float _2124 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].z), _2118, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].y), _2117, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].x) * _2116))); + float _2127 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].z), _2118, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].y), _2117, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].x) * _2116))); + float _2130 = mad(-0.21492856740951538f, _2127, mad(-0.2365107536315918f, _2124, (_2121 * 1.4514392614364624f))); + float _2133 = mad(-0.09967592358589172f, _2127, mad(1.17622971534729f, _2124, (_2121 * -0.07655377686023712f))); + float _2136 = mad(0.9977163076400757f, _2127, mad(-0.006032449658960104f, _2124, (_2121 * 0.008316148072481155f))); + float _2138 = max(_2130, max(_2133, _2136)); + do { + if (!(_2138 < 1.000000013351432e-10f)) { + if (!(((bool)((bool)(_2121 < 0.0f) || (bool)(_2124 < 0.0f))) || (bool)(_2127 < 0.0f))) { + float _2148 = abs(_2138); + float _2149 = (_2138 - _2130) / _2148; + float _2151 = (_2138 - _2133) / _2148; + float _2153 = (_2138 - _2136) / _2148; + do { + if (!(_2149 < 0.8149999976158142f)) { + float _2156 = _2149 + -0.8149999976158142f; + _2168 = ((_2156 / exp2(log2(exp2(log2(_2156 * 3.0552830696105957f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8149999976158142f); + } else { + _2168 = _2149; + } + do { + if (!(_2151 < 0.8029999732971191f)) { + float _2171 = _2151 + -0.8029999732971191f; + _2183 = ((_2171 / exp2(log2(exp2(log2(_2171 * 3.4972610473632812f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8029999732971191f); + } else { + _2183 = _2151; + } + do { + if (!(_2153 < 0.8799999952316284f)) { + float _2186 = _2153 + -0.8799999952316284f; + _2198 = ((_2186 / exp2(log2(exp2(log2(_2186 * 6.810994625091553f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8799999952316284f); + } else { + _2198 = _2153; + } + _2206 = (_2138 - (_2148 * _2168)); + _2207 = (_2138 - (_2148 * _2183)); + _2208 = (_2138 - (_2148 * _2198)); + } while (false); + } while (false); + } while (false); + } else { + _2206 = _2130; + _2207 = _2133; + _2208 = _2136; + } + } else { + _2206 = _2130; + _2207 = _2133; + _2208 = _2136; + } + float _2224 = ((mad(0.16386906802654266f, _2208, mad(0.14067870378494263f, _2207, (_2206 * 0.6954522132873535f))) - _2121) * cb0_012w) + _2121; + float _2225 = ((mad(0.0955343171954155f, _2208, mad(0.8596711158752441f, _2207, (_2206 * 0.044794563204050064f))) - _2124) * cb0_012w) + _2124; + float _2226 = ((mad(1.0015007257461548f, _2208, mad(0.004025210160762072f, _2207, (_2206 * -0.005525882821530104f))) - _2127) * cb0_012w) + _2127; + float _2230 = max(max(_2224, _2225), _2226); + float _2235 = (max(_2230, 1.000000013351432e-10f) - max(min(min(_2224, _2225), _2226), 1.000000013351432e-10f)) / max(_2230, 0.009999999776482582f); + float _2248 = ((_2225 + _2224) + _2226) + (sqrt((((_2226 - _2225) * _2226) + ((_2225 - _2224) * _2225)) + ((_2224 - _2226) * _2224)) * 1.75f); + float _2249 = _2248 * 0.3333333432674408f; + float _2250 = _2235 + -0.4000000059604645f; + float _2251 = _2250 * 5.0f; + float _2255 = max((1.0f - abs(_2250 * 2.5f)), 0.0f); + float _2266 = ((float((int)(((int)(uint)((bool)(_2251 > 0.0f))) - ((int)(uint)((bool)(_2251 < 0.0f))))) * (1.0f - (_2255 * _2255))) + 1.0f) * 0.02500000037252903f; + do { + if (!(_2249 <= 0.0533333346247673f)) { + if (!(_2249 >= 0.1599999964237213f)) { + _2275 = (((0.23999999463558197f / _2248) + -0.5f) * _2266); + } else { + _2275 = 0.0f; + } + } else { + _2275 = _2266; + } + float _2276 = _2275 + 1.0f; + float _2277 = _2276 * _2224; + float _2278 = _2276 * _2225; + float _2279 = _2276 * _2226; + do { + if (!((bool)(_2277 == _2278) && (bool)(_2278 == _2279))) { + float _2286 = ((_2277 * 2.0f) - _2278) - _2279; + float _2289 = ((_2225 - _2226) * 1.7320507764816284f) * _2276; + float _2291 = atan(_2289 / _2286); + bool _2294 = (_2286 < 0.0f); + bool _2295 = (_2286 == 0.0f); + bool _2296 = (_2289 >= 0.0f); + bool _2297 = (_2289 < 0.0f); + _2308 = select((_2296 && _2295), 90.0f, select((_2297 && _2295), -90.0f, (select((_2297 && _2294), (_2291 + -3.1415927410125732f), select((_2296 && _2294), (_2291 + 3.1415927410125732f), _2291)) * 57.2957763671875f))); + } else { + _2308 = 0.0f; + } + float _2313 = min(max(select((_2308 < 0.0f), (_2308 + 360.0f), _2308), 0.0f), 360.0f); + do { + if (_2313 < -180.0f) { + _2322 = (_2313 + 360.0f); + } else { + if (_2313 > 180.0f) { + _2322 = (_2313 + -360.0f); + } else { + _2322 = _2313; + } + } + do { + if ((bool)(_2322 > -67.5f) && (bool)(_2322 < 67.5f)) { + float _2328 = (_2322 + 67.5f) * 0.029629629105329514f; + int _2329 = int(_2328); + float _2331 = _2328 - float((int)(_2329)); + float _2332 = _2331 * _2331; + float _2333 = _2332 * _2331; + if (_2329 == 3) { + _2361 = (((0.1666666716337204f - (_2331 * 0.5f)) + (_2332 * 0.5f)) - (_2333 * 0.1666666716337204f)); + } else { + if (_2329 == 2) { + _2361 = ((0.6666666865348816f - _2332) + (_2333 * 0.5f)); + } else { + if (_2329 == 1) { + _2361 = (((_2333 * -0.5f) + 0.1666666716337204f) + ((_2332 + _2331) * 0.5f)); + } else { + _2361 = select((_2329 == 0), (_2333 * 0.1666666716337204f), 0.0f); + } + } + } + } else { + _2361 = 0.0f; + } + float _2370 = min(max(((((_2235 * 0.27000001072883606f) * (0.029999999329447746f - _2277)) * _2361) + _2277), 0.0f), 65535.0f); + float _2371 = min(max(_2278, 0.0f), 65535.0f); + float _2372 = min(max(_2279, 0.0f), 65535.0f); + float _2385 = min(max(mad(-0.21492856740951538f, _2372, mad(-0.2365107536315918f, _2371, (_2370 * 1.4514392614364624f))), 0.0f), 65504.0f); + float _2386 = min(max(mad(-0.09967592358589172f, _2372, mad(1.17622971534729f, _2371, (_2370 * -0.07655377686023712f))), 0.0f), 65504.0f); + float _2387 = min(max(mad(0.9977163076400757f, _2372, mad(-0.006032449658960104f, _2371, (_2370 * 0.008316148072481155f))), 0.0f), 65504.0f); + float _2388 = dot(float3(_2385, _2386, _2387), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + _10[0] = cb0_010x; + _10[1] = cb0_010y; + _10[2] = cb0_010z; + _10[3] = cb0_010w; + _10[4] = cb0_012x; + _10[5] = cb0_012x; + _11[0] = cb0_011x; + _11[1] = cb0_011y; + _11[2] = cb0_011z; + _11[3] = cb0_011w; + _11[4] = cb0_012y; + _11[5] = cb0_012y; + float _2411 = log2(max((lerp(_2388, _2385, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _2412 = _2411 * 0.3010300099849701f; + float _2413 = log2(cb0_008x); + float _2414 = _2413 * 0.3010300099849701f; + do { + if (!(!(_2412 <= _2414))) { + _2483 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _2421 = log2(cb0_009x); + float _2422 = _2421 * 0.3010300099849701f; + if ((bool)(_2412 > _2414) && (bool)(_2412 < _2422)) { + float _2430 = ((_2411 - _2413) * 0.9030900001525879f) / ((_2421 - _2413) * 0.3010300099849701f); + int _2431 = int(_2430); + float _2433 = _2430 - float((int)(_2431)); + float _2435 = _10[_2431]; + float _2438 = _10[(_2431 + 1)]; + float _2443 = _2435 * 0.5f; + _2483 = dot(float3((_2433 * _2433), _2433, 1.0f), float3(mad((_10[(_2431 + 2)]), 0.5f, mad(_2438, -1.0f, _2443)), (_2438 - _2435), mad(_2438, 0.5f, _2443))); + } else { + do { + if (!(!(_2412 >= _2422))) { + float _2452 = log2(cb0_008z); + if (_2412 < (_2452 * 0.3010300099849701f)) { + float _2460 = ((_2411 - _2421) * 0.9030900001525879f) / ((_2452 - _2421) * 0.3010300099849701f); + int _2461 = int(_2460); + float _2463 = _2460 - float((int)(_2461)); + float _2465 = _11[_2461]; + float _2468 = _11[(_2461 + 1)]; + float _2473 = _2465 * 0.5f; + _2483 = dot(float3((_2463 * _2463), _2463, 1.0f), float3(mad((_11[(_2461 + 2)]), 0.5f, mad(_2468, -1.0f, _2473)), (_2468 - _2465), mad(_2468, 0.5f, _2473))); + break; + } + } + _2483 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + _12[0] = cb0_010x; + _12[1] = cb0_010y; + _12[2] = cb0_010z; + _12[3] = cb0_010w; + _12[4] = cb0_012x; + _12[5] = cb0_012x; + _13[0] = cb0_011x; + _13[1] = cb0_011y; + _13[2] = cb0_011z; + _13[3] = cb0_011w; + _13[4] = cb0_012y; + _13[5] = cb0_012y; + float _2499 = log2(max((lerp(_2388, _2386, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _2500 = _2499 * 0.3010300099849701f; + do { + if (!(!(_2500 <= _2414))) { + _2569 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _2507 = log2(cb0_009x); + float _2508 = _2507 * 0.3010300099849701f; + if ((bool)(_2500 > _2414) && (bool)(_2500 < _2508)) { + float _2516 = ((_2499 - _2413) * 0.9030900001525879f) / ((_2507 - _2413) * 0.3010300099849701f); + int _2517 = int(_2516); + float _2519 = _2516 - float((int)(_2517)); + float _2521 = _12[_2517]; + float _2524 = _12[(_2517 + 1)]; + float _2529 = _2521 * 0.5f; + _2569 = dot(float3((_2519 * _2519), _2519, 1.0f), float3(mad((_12[(_2517 + 2)]), 0.5f, mad(_2524, -1.0f, _2529)), (_2524 - _2521), mad(_2524, 0.5f, _2529))); + } else { + do { + if (!(!(_2500 >= _2508))) { + float _2538 = log2(cb0_008z); + if (_2500 < (_2538 * 0.3010300099849701f)) { + float _2546 = ((_2499 - _2507) * 0.9030900001525879f) / ((_2538 - _2507) * 0.3010300099849701f); + int _2547 = int(_2546); + float _2549 = _2546 - float((int)(_2547)); + float _2551 = _13[_2547]; + float _2554 = _13[(_2547 + 1)]; + float _2559 = _2551 * 0.5f; + _2569 = dot(float3((_2549 * _2549), _2549, 1.0f), float3(mad((_13[(_2547 + 2)]), 0.5f, mad(_2554, -1.0f, _2559)), (_2554 - _2551), mad(_2554, 0.5f, _2559))); + break; + } + } + _2569 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + _14[0] = cb0_010x; + _14[1] = cb0_010y; + _14[2] = cb0_010z; + _14[3] = cb0_010w; + _14[4] = cb0_012x; + _14[5] = cb0_012x; + _15[0] = cb0_011x; + _15[1] = cb0_011y; + _15[2] = cb0_011z; + _15[3] = cb0_011w; + _15[4] = cb0_012y; + _15[5] = cb0_012y; + float _2585 = log2(max((lerp(_2388, _2387, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _2586 = _2585 * 0.3010300099849701f; + do { + if (!(!(_2586 <= _2414))) { + _2655 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _2593 = log2(cb0_009x); + float _2594 = _2593 * 0.3010300099849701f; + if ((bool)(_2586 > _2414) && (bool)(_2586 < _2594)) { + float _2602 = ((_2585 - _2413) * 0.9030900001525879f) / ((_2593 - _2413) * 0.3010300099849701f); + int _2603 = int(_2602); + float _2605 = _2602 - float((int)(_2603)); + float _2607 = _14[_2603]; + float _2610 = _14[(_2603 + 1)]; + float _2615 = _2607 * 0.5f; + _2655 = dot(float3((_2605 * _2605), _2605, 1.0f), float3(mad((_14[(_2603 + 2)]), 0.5f, mad(_2610, -1.0f, _2615)), (_2610 - _2607), mad(_2610, 0.5f, _2615))); + } else { + do { + if (!(!(_2586 >= _2594))) { + float _2624 = log2(cb0_008z); + if (_2586 < (_2624 * 0.3010300099849701f)) { + float _2632 = ((_2585 - _2593) * 0.9030900001525879f) / ((_2624 - _2593) * 0.3010300099849701f); + int _2633 = int(_2632); + float _2635 = _2632 - float((int)(_2633)); + float _2637 = _15[_2633]; + float _2640 = _15[(_2633 + 1)]; + float _2645 = _2637 * 0.5f; + _2655 = dot(float3((_2635 * _2635), _2635, 1.0f), float3(mad((_15[(_2633 + 2)]), 0.5f, mad(_2640, -1.0f, _2645)), (_2640 - _2637), mad(_2640, 0.5f, _2645))); + break; + } + } + _2655 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + float _2659 = cb0_008w - cb0_008y; + float _2660 = (exp2(_2483 * 3.321928024291992f) - cb0_008y) / _2659; + float _2662 = (exp2(_2569 * 3.321928024291992f) - cb0_008y) / _2659; + float _2664 = (exp2(_2655 * 3.321928024291992f) - cb0_008y) / _2659; + float _2667 = mad(0.15618768334388733f, _2664, mad(0.13400420546531677f, _2662, (_2660 * 0.6624541878700256f))); + float _2670 = mad(0.053689517080783844f, _2664, mad(0.6740817427635193f, _2662, (_2660 * 0.2722287178039551f))); + float _2673 = mad(1.0103391408920288f, _2664, mad(0.00406073359772563f, _2662, (_2660 * -0.005574649665504694f))); + float _2686 = min(max(mad(-0.23642469942569733f, _2673, mad(-0.32480329275131226f, _2670, (_2667 * 1.6410233974456787f))), 0.0f), 1.0f); + float _2687 = min(max(mad(0.016756348311901093f, _2673, mad(1.6153316497802734f, _2670, (_2667 * -0.663662850856781f))), 0.0f), 1.0f); + float _2688 = min(max(mad(0.9883948564529419f, _2673, mad(-0.008284442126750946f, _2670, (_2667 * 0.011721894145011902f))), 0.0f), 1.0f); + float _2691 = mad(0.15618768334388733f, _2688, mad(0.13400420546531677f, _2687, (_2686 * 0.6624541878700256f))); + float _2694 = mad(0.053689517080783844f, _2688, mad(0.6740817427635193f, _2687, (_2686 * 0.2722287178039551f))); + float _2697 = mad(1.0103391408920288f, _2688, mad(0.00406073359772563f, _2687, (_2686 * -0.005574649665504694f))); + float _2719 = min(max((min(max(mad(-0.23642469942569733f, _2697, mad(-0.32480329275131226f, _2694, (_2691 * 1.6410233974456787f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f); + float _2722 = min(max((min(max(mad(0.016756348311901093f, _2697, mad(1.6153316497802734f, _2694, (_2691 * -0.663662850856781f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f) * 0.012500000186264515f; + float _2723 = min(max((min(max(mad(0.9883948564529419f, _2697, mad(-0.008284442126750946f, _2694, (_2691 * 0.011721894145011902f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f) * 0.012500000186264515f; + _2870 = mad(-0.0832589864730835f, _2723, mad(-0.6217921376228333f, _2722, (_2719 * 0.0213131383061409f))); + _2871 = mad(-0.010548308491706848f, _2723, mad(1.140804648399353f, _2722, (_2719 * -0.0016282059950754046f))); + _2872 = mad(1.1529725790023804f, _2723, mad(-0.1289689838886261f, _2722, (_2719 * -0.00030004189466126263f))); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } else { + if (cb0_042w == 7) { + float _2750 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _1241, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _1240, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _1239))); + float _2753 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _1241, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _1240, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _1239))); + float _2756 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _1241, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _1240, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _1239))); + float _2775 = exp2(log2(mad(_63, _2756, mad(_62, _2753, (_2750 * _61))) * 9.999999747378752e-05f) * 0.1593017578125f); + float _2776 = exp2(log2(mad(_66, _2756, mad(_65, _2753, (_2750 * _64))) * 9.999999747378752e-05f) * 0.1593017578125f); + float _2777 = exp2(log2(mad(_69, _2756, mad(_68, _2753, (_2750 * _67))) * 9.999999747378752e-05f) * 0.1593017578125f); + _2870 = exp2(log2((1.0f / ((_2775 * 18.6875f) + 1.0f)) * ((_2775 * 18.8515625f) + 0.8359375f)) * 78.84375f); + _2871 = exp2(log2((1.0f / ((_2776 * 18.6875f) + 1.0f)) * ((_2776 * 18.8515625f) + 0.8359375f)) * 78.84375f); + _2872 = exp2(log2((1.0f / ((_2777 * 18.6875f) + 1.0f)) * ((_2777 * 18.8515625f) + 0.8359375f)) * 78.84375f); + } else { + if (!(cb0_042w == 8)) { + if (cb0_042w == 9) { + float _2824 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _1229, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _1228, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _1227))); + float _2827 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _1229, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _1228, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _1227))); + float _2830 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _1229, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _1228, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _1227))); + _2870 = mad(_63, _2830, mad(_62, _2827, (_2824 * _61))); + _2871 = mad(_66, _2830, mad(_65, _2827, (_2824 * _64))); + _2872 = mad(_69, _2830, mad(_68, _2827, (_2824 * _67))); + } else { + float _2843 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _1253))); + float _2846 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _1253))); + float _2849 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _1253))); + _2870 = exp2(log2(mad(_63, _2849, mad(_62, _2846, (_2843 * _61)))) * cb0_042z); + _2871 = exp2(log2(mad(_66, _2849, mad(_65, _2846, (_2843 * _64)))) * cb0_042z); + _2872 = exp2(log2(mad(_69, _2849, mad(_68, _2846, (_2843 * _67)))) * cb0_042z); + } + } else { + _2870 = _1239; + _2871 = _1240; + _2872 = _1241; + } + } + } + } + } + } + u0[int3((uint)(SV_DispatchThreadID.x), (uint)(SV_DispatchThreadID.y), (uint)(SV_DispatchThreadID.z))] = float4((_2870 * 0.9523810148239136f), (_2871 * 0.9523810148239136f), (_2872 * 0.9523810148239136f), 0.0f); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } + } + bool _165 = (cb0_040w != 0); + float _167 = 0.9994439482688904f / cb0_037y; + if (!(!((cb0_037y * 1.0005563497543335f) <= 7000.0f))) { + _184 = (((((2967800.0f - (_167 * 4607000064.0f)) * _167) + 99.11000061035156f) * _167) + 0.24406300485134125f); + } else { + _184 = (((((1901800.0f - (_167 * 2006400000.0f)) * _167) + 247.47999572753906f) * _167) + 0.23703999817371368f); + } + float _198 = ((((cb0_037y * 1.2864121856637212e-07f) + 0.00015411825734190643f) * cb0_037y) + 0.8601177334785461f) / ((((cb0_037y * 7.081451371959702e-07f) + 0.0008424202096648514f) * cb0_037y) + 1.0f); + float _205 = cb0_037y * cb0_037y; + float _208 = ((((cb0_037y * 4.204816761443908e-08f) + 4.228062607580796e-05f) * cb0_037y) + 0.31739872694015503f) / ((1.0f - (cb0_037y * 2.8974181986995973e-05f)) + (_205 * 1.6145605741257896e-07f)); + float _213 = ((_198 * 2.0f) + 4.0f) - (_208 * 8.0f); + float _214 = (_198 * 3.0f) / _213; + float _216 = (_208 * 2.0f) / _213; + bool _217 = (cb0_037y < 4000.0f); + float _226 = ((cb0_037y + 1189.6199951171875f) * cb0_037y) + 1412139.875f; + float _228 = ((-1137581184.0f - (cb0_037y * 1916156.25f)) - (_205 * 1.5317699909210205f)) / (_226 * _226); + float _235 = (6193636.0f - (cb0_037y * 179.45599365234375f)) + _205; + float _237 = ((1974715392.0f - (cb0_037y * 705674.0f)) - (_205 * 308.60699462890625f)) / (_235 * _235); + float _239 = rsqrt(dot(float2(_228, _237), float2(_228, _237))); + float _240 = cb0_037z * 0.05000000074505806f; + float _243 = ((_240 * _237) * _239) + _198; + float _246 = _208 - ((_240 * _228) * _239); + float _251 = (4.0f - (_246 * 8.0f)) + (_243 * 2.0f); + float _257 = (((_243 * 3.0f) / _251) - _214) + select(_217, _214, _184); + float _258 = (((_246 * 2.0f) / _251) - _216) + select(_217, _216, (((_184 * 2.869999885559082f) + -0.2750000059604645f) - ((_184 * _184) * 3.0f))); + float _259 = select(_165, _257, 0.3127000033855438f); + float _260 = select(_165, _258, 0.32899999618530273f); + float _261 = select(_165, 0.3127000033855438f, _257); + float _262 = select(_165, 0.32899999618530273f, _258); + float _263 = max(_260, 1.000000013351432e-10f); + float _264 = _259 / _263; + float _267 = ((1.0f - _259) - _260) / _263; + float _268 = max(_262, 1.000000013351432e-10f); + float _269 = _261 / _268; + float _272 = ((1.0f - _261) - _262) / _268; + float _291 = mad(-0.16140000522136688f, _272, ((_269 * 0.8950999975204468f) + 0.266400009393692f)) / mad(-0.16140000522136688f, _267, ((_264 * 0.8950999975204468f) + 0.266400009393692f)); + float _292 = mad(0.03669999912381172f, _272, (1.7135000228881836f - (_269 * 0.7501999735832214f))) / mad(0.03669999912381172f, _267, (1.7135000228881836f - (_264 * 0.7501999735832214f))); + float _293 = mad(1.0296000242233276f, _272, ((_269 * 0.03889999911189079f) + -0.06849999725818634f)) / mad(1.0296000242233276f, _267, ((_264 * 0.03889999911189079f) + -0.06849999725818634f)); + float _294 = mad(_292, -0.7501999735832214f, 0.0f); + float _295 = mad(_292, 1.7135000228881836f, 0.0f); + float _296 = mad(_292, 0.03669999912381172f, -0.0f); + float _297 = mad(_293, 0.03889999911189079f, 0.0f); + float _298 = mad(_293, -0.06849999725818634f, 0.0f); + float _299 = mad(_293, 1.0296000242233276f, 0.0f); + float _302 = mad(0.1599626988172531f, _297, mad(-0.1470542997121811f, _294, (_291 * 0.883457362651825f))); + float _305 = mad(0.1599626988172531f, _298, mad(-0.1470542997121811f, _295, (_291 * 0.26293492317199707f))); + float _308 = mad(0.1599626988172531f, _299, mad(-0.1470542997121811f, _296, (_291 * -0.15930065512657166f))); + float _311 = mad(0.04929120093584061f, _297, mad(0.5183603167533875f, _294, (_291 * 0.38695648312568665f))); + float _314 = mad(0.04929120093584061f, _298, mad(0.5183603167533875f, _295, (_291 * 0.11516613513231277f))); + float _317 = mad(0.04929120093584061f, _299, mad(0.5183603167533875f, _296, (_291 * -0.0697740763425827f))); + float _320 = mad(0.9684867262840271f, _297, mad(0.04004279896616936f, _294, (_291 * -0.007634039502590895f))); + float _323 = mad(0.9684867262840271f, _298, mad(0.04004279896616936f, _295, (_291 * -0.0022720457054674625f))); + float _326 = mad(0.9684867262840271f, _299, mad(0.04004279896616936f, _296, (_291 * 0.0013765322510153055f))); + float _329 = mad(_308, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[2].x), mad(_305, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[1].x), (_302 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[0].x)))); + float _332 = mad(_308, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[2].y), mad(_305, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[1].y), (_302 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[0].y)))); + float _335 = mad(_308, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[2].z), mad(_305, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[1].z), (_302 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[0].z)))); + float _338 = mad(_317, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[2].x), mad(_314, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[1].x), (_311 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[0].x)))); + float _341 = mad(_317, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[2].y), mad(_314, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[1].y), (_311 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[0].y)))); + float _344 = mad(_317, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[2].z), mad(_314, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[1].z), (_311 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[0].z)))); + float _347 = mad(_326, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[2].x), mad(_323, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[1].x), (_320 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[0].x)))); + float _350 = mad(_326, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[2].y), mad(_323, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[1].y), (_320 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[0].y)))); + float _353 = mad(_326, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[2].z), mad(_323, (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[1].z), (_320 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_000[0].z)))); + _391 = mad(mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[0].z), _353, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[0].y), _344, (_335 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_064[0].x)))), _129, mad(mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[0].z), _350, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[0].y), _341, (_332 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_064[0].x)))), _128, (mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[0].z), _347, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[0].y), _338, (_329 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_064[0].x)))) * _127))); + _392 = mad(mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[1].z), _353, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[1].y), _344, (_335 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_064[1].x)))), _129, mad(mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[1].z), _350, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[1].y), _341, (_332 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_064[1].x)))), _128, (mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[1].z), _347, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[1].y), _338, (_329 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_064[1].x)))) * _127))); + _393 = mad(mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[2].z), _353, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[2].y), _344, (_335 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_064[2].x)))), _129, mad(mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[2].z), _350, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[2].y), _341, (_332 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_064[2].x)))), _128, (mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[2].z), _347, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_064[2].y), _338, (_329 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_064[2].x)))) * _127))); + float _408 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _393, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _392, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _391))); + float _411 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _393, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _392, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _391))); + float _414 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _393, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _392, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _391))); + + SetUngradedAP1(float3(_408, _411, _414)); + + float _415 = dot(float3(_408, _411, _414), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + float _419 = (_408 / _415) + -1.0f; + float _420 = (_411 / _415) + -1.0f; + float _421 = (_414 / _415) + -1.0f; + float _433 = (1.0f - exp2(((_415 * _415) * -4.0f) * cb0_038w)) * (1.0f - exp2(dot(float3(_419, _420, _421), float3(_419, _420, _421)) * -4.0f)); + float _449 = ((mad(-0.06368321925401688f, _414, mad(-0.3292922377586365f, _411, (_408 * 1.3704125881195068f))) - _408) * _433) + _408; + float _450 = ((mad(-0.010861365124583244f, _414, mad(1.0970927476882935f, _411, (_408 * -0.08343357592821121f))) - _411) * _433) + _411; + float _451 = ((mad(1.2036951780319214f, _414, mad(-0.09862580895423889f, _411, (_408 * -0.02579331398010254f))) - _414) * _433) + _414; + float _452 = dot(float3(_449, _450, _451), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + float _466 = cb0_021w + cb0_026w; + float _480 = cb0_020w * cb0_025w; + float _494 = cb0_019w * cb0_024w; + float _508 = cb0_018w * cb0_023w; + float _522 = cb0_017w * cb0_022w; + float _526 = _449 - _452; + float _527 = _450 - _452; + float _528 = _451 - _452; + float _585 = saturate(_452 / cb0_037w); + float _589 = (_585 * _585) * (3.0f - (_585 * 2.0f)); + float _590 = 1.0f - _589; + float _599 = cb0_021w + cb0_036w; + float _608 = cb0_020w * cb0_035w; + float _617 = cb0_019w * cb0_034w; + float _626 = cb0_018w * cb0_033w; + float _635 = cb0_017w * cb0_032w; + float _698 = saturate((_452 - cb0_038x) / (cb0_038y - cb0_038x)); + float _702 = (_698 * _698) * (3.0f - (_698 * 2.0f)); + float _711 = cb0_021w + cb0_031w; + float _720 = cb0_020w * cb0_030w; + float _729 = cb0_019w * cb0_029w; + float _738 = cb0_018w * cb0_028w; + float _747 = cb0_017w * cb0_027w; + float _805 = _589 - _702; + float _816 = ((_702 * (((cb0_021x + cb0_036x) + _599) + (((cb0_020x * cb0_035x) * _608) * exp2(log2(exp2(((cb0_018x * cb0_033x) * _626) * log2(max(0.0f, ((((cb0_017x * cb0_032x) * _635) * _526) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019x * cb0_034x) * _617)))))) + (_590 * (((cb0_021x + cb0_026x) + _466) + (((cb0_020x * cb0_025x) * _480) * exp2(log2(exp2(((cb0_018x * cb0_023x) * _508) * log2(max(0.0f, ((((cb0_017x * cb0_022x) * _522) * _526) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019x * cb0_024x) * _494))))))) + ((((cb0_021x + cb0_031x) + _711) + (((cb0_020x * cb0_030x) * _720) * exp2(log2(exp2(((cb0_018x * cb0_028x) * _738) * log2(max(0.0f, ((((cb0_017x * cb0_027x) * _747) * _526) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019x * cb0_029x) * _729))))) * _805); + float _818 = ((_702 * (((cb0_021y + cb0_036y) + _599) + (((cb0_020y * cb0_035y) * _608) * exp2(log2(exp2(((cb0_018y * cb0_033y) * _626) * log2(max(0.0f, ((((cb0_017y * cb0_032y) * _635) * _527) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019y * cb0_034y) * _617)))))) + (_590 * (((cb0_021y + cb0_026y) + _466) + (((cb0_020y * cb0_025y) * _480) * exp2(log2(exp2(((cb0_018y * cb0_023y) * _508) * log2(max(0.0f, ((((cb0_017y * cb0_022y) * _522) * _527) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019y * cb0_024y) * _494))))))) + ((((cb0_021y + cb0_031y) + _711) + (((cb0_020y * cb0_030y) * _720) * exp2(log2(exp2(((cb0_018y * cb0_028y) * _738) * log2(max(0.0f, ((((cb0_017y * cb0_027y) * _747) * _527) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019y * cb0_029y) * _729))))) * _805); + float _820 = ((_702 * (((cb0_021z + cb0_036z) + _599) + (((cb0_020z * cb0_035z) * _608) * exp2(log2(exp2(((cb0_018z * cb0_033z) * _626) * log2(max(0.0f, ((((cb0_017z * cb0_032z) * _635) * _528) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019z * cb0_034z) * _617)))))) + (_590 * (((cb0_021z + cb0_026z) + _466) + (((cb0_020z * cb0_025z) * _480) * exp2(log2(exp2(((cb0_018z * cb0_023z) * _508) * log2(max(0.0f, ((((cb0_017z * cb0_022z) * _522) * _528) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019z * cb0_024z) * _494))))))) + ((((cb0_021z + cb0_031z) + _711) + (((cb0_020z * cb0_030z) * _720) * exp2(log2(exp2(((cb0_018z * cb0_028z) * _738) * log2(max(0.0f, ((((cb0_017z * cb0_027z) * _747) * _528) + _452)) * 5.55555534362793f)) * 0.18000000715255737f) * (1.0f / ((cb0_019z * cb0_029z) * _729))))) * _805); + + SetUntonemappedAP1(float3(_816, _818, _820)); + + float _856 = ((mad(0.061360642313957214f, _820, mad(-4.540197551250458e-09f, _818, (_816 * 0.9386394023895264f))) - _816) * cb0_038z) + _816; + float _857 = ((mad(0.169205904006958f, _820, mad(0.8307942152023315f, _818, (_816 * 6.775371730327606e-08f))) - _818) * cb0_038z) + _818; + float _858 = (mad(-2.3283064365386963e-10f, _818, (_816 * -9.313225746154785e-10f)) * cb0_038z) + _820; + float _861 = mad(0.16386905312538147f, _858, mad(0.14067868888378143f, _857, (_856 * 0.6954522132873535f))); + float _864 = mad(0.0955343246459961f, _858, mad(0.8596711158752441f, _857, (_856 * 0.044794581830501556f))); + float _867 = mad(1.0015007257461548f, _858, mad(0.004025210160762072f, _857, (_856 * -0.005525882821530104f))); + float _871 = max(max(_861, _864), _867); + float _876 = (max(_871, 1.000000013351432e-10f) - max(min(min(_861, _864), _867), 1.000000013351432e-10f)) / max(_871, 0.009999999776482582f); + float _889 = ((_864 + _861) + _867) + (sqrt((((_867 - _864) * _867) + ((_864 - _861) * _864)) + ((_861 - _867) * _861)) * 1.75f); + float _890 = _889 * 0.3333333432674408f; + float _891 = _876 + -0.4000000059604645f; + float _892 = _891 * 5.0f; + float _896 = max((1.0f - abs(_891 * 2.5f)), 0.0f); + float _907 = ((float((int)(((int)(uint)((bool)(_892 > 0.0f))) - ((int)(uint)((bool)(_892 < 0.0f))))) * (1.0f - (_896 * _896))) + 1.0f) * 0.02500000037252903f; + if (!(_890 <= 0.0533333346247673f)) { + if (!(_890 >= 0.1599999964237213f)) { + _916 = (((0.23999999463558197f / _889) + -0.5f) * _907); + } else { + _916 = 0.0f; + } + } else { + _916 = _907; + } + float _917 = _916 + 1.0f; + float _918 = _917 * _861; + float _919 = _917 * _864; + float _920 = _917 * _867; + if (!((bool)(_918 == _919) && (bool)(_919 == _920))) { + float _927 = ((_918 * 2.0f) - _919) - _920; + float _930 = ((_864 - _867) * 1.7320507764816284f) * _917; + float _932 = atan(_930 / _927); + bool _935 = (_927 < 0.0f); + bool _936 = (_927 == 0.0f); + bool _937 = (_930 >= 0.0f); + bool _938 = (_930 < 0.0f); + _949 = select((_937 && _936), 90.0f, select((_938 && _936), -90.0f, (select((_938 && _935), (_932 + -3.1415927410125732f), select((_937 && _935), (_932 + 3.1415927410125732f), _932)) * 57.2957763671875f))); + } else { + _949 = 0.0f; + } + float _954 = min(max(select((_949 < 0.0f), (_949 + 360.0f), _949), 0.0f), 360.0f); + if (_954 < -180.0f) { + _963 = (_954 + 360.0f); + } else { + if (_954 > 180.0f) { + _963 = (_954 + -360.0f); + } else { + _963 = _954; + } + } + float _967 = saturate(1.0f - abs(_963 * 0.014814814552664757f)); + float _971 = (_967 * _967) * (3.0f - (_967 * 2.0f)); + float _977 = ((_971 * _971) * ((_876 * 0.18000000715255737f) * (0.029999999329447746f - _918))) + _918; + float _987 = max(0.0f, mad(-0.21492856740951538f, _920, mad(-0.2365107536315918f, _919, (_977 * 1.4514392614364624f)))); + float _988 = max(0.0f, mad(-0.09967592358589172f, _920, mad(1.17622971534729f, _919, (_977 * -0.07655377686023712f)))); + float _989 = max(0.0f, mad(0.9977163076400757f, _920, mad(-0.006032449658960104f, _919, (_977 * 0.008316148072481155f)))); + float _990 = dot(float3(_987, _988, _989), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + float _1005 = (cb0_040x + 1.0f) - cb0_039z; + float _1007 = cb0_040y + 1.0f; + float _1009 = _1007 - cb0_039w; + if (cb0_039z > 0.800000011920929f) { + _1027 = (((0.8199999928474426f - cb0_039z) / cb0_039y) + -0.7447274923324585f); + } else { + float _1018 = (cb0_040x + 0.18000000715255737f) / _1005; + _1027 = (-0.7447274923324585f - ((log2(_1018 / (2.0f - _1018)) * 0.3465735912322998f) * (_1005 / cb0_039y))); + } + float _1030 = ((1.0f - cb0_039z) / cb0_039y) - _1027; + float _1032 = (cb0_039w / cb0_039y) - _1030; + float _1036 = log2(lerp(_990, _987, 0.9599999785423279f)) * 0.3010300099849701f; + float _1037 = log2(lerp(_990, _988, 0.9599999785423279f)) * 0.3010300099849701f; + float _1038 = log2(lerp(_990, _989, 0.9599999785423279f)) * 0.3010300099849701f; + float _1042 = cb0_039y * (_1036 + _1030); + float _1043 = cb0_039y * (_1037 + _1030); + float _1044 = cb0_039y * (_1038 + _1030); + float _1045 = _1005 * 2.0f; + float _1047 = (cb0_039y * -2.0f) / _1005; + float _1048 = _1036 - _1027; + float _1049 = _1037 - _1027; + float _1050 = _1038 - _1027; + float _1069 = _1009 * 2.0f; + float _1071 = (cb0_039y * 2.0f) / _1009; + float _1096 = select((_1036 < _1027), ((_1045 / (exp2((_1048 * 1.4426950216293335f) * _1047) + 1.0f)) - cb0_040x), _1042); + float _1097 = select((_1037 < _1027), ((_1045 / (exp2((_1049 * 1.4426950216293335f) * _1047) + 1.0f)) - cb0_040x), _1043); + float _1098 = select((_1038 < _1027), ((_1045 / (exp2((_1050 * 1.4426950216293335f) * _1047) + 1.0f)) - cb0_040x), _1044); + float _1105 = _1032 - _1027; + float _1109 = saturate(_1048 / _1105); + float _1110 = saturate(_1049 / _1105); + float _1111 = saturate(_1050 / _1105); + bool _1112 = (_1032 < _1027); + float _1116 = select(_1112, (1.0f - _1109), _1109); + float _1117 = select(_1112, (1.0f - _1110), _1110); + float _1118 = select(_1112, (1.0f - _1111), _1111); + float _1137 = (((_1116 * _1116) * (select((_1036 > _1032), (_1007 - (_1069 / (exp2(((_1036 - _1032) * 1.4426950216293335f) * _1071) + 1.0f))), _1042) - _1096)) * (3.0f - (_1116 * 2.0f))) + _1096; + float _1138 = (((_1117 * _1117) * (select((_1037 > _1032), (_1007 - (_1069 / (exp2(((_1037 - _1032) * 1.4426950216293335f) * _1071) + 1.0f))), _1043) - _1097)) * (3.0f - (_1117 * 2.0f))) + _1097; + float _1139 = (((_1118 * _1118) * (select((_1038 > _1032), (_1007 - (_1069 / (exp2(((_1038 - _1032) * 1.4426950216293335f) * _1071) + 1.0f))), _1044) - _1098)) * (3.0f - (_1118 * 2.0f))) + _1098; + float _1140 = dot(float3(_1137, _1138, _1139), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + float _1160 = (cb0_039x * (max(0.0f, (lerp(_1140, _1137, 0.9300000071525574f))) - _856)) + _856; + float _1161 = (cb0_039x * (max(0.0f, (lerp(_1140, _1138, 0.9300000071525574f))) - _857)) + _857; + float _1162 = (cb0_039x * (max(0.0f, (lerp(_1140, _1139, 0.9300000071525574f))) - _858)) + _858; + float _1178 = ((mad(-0.06537103652954102f, _1162, mad(1.451815478503704e-06f, _1161, (_1160 * 1.065374732017517f))) - _1160) * cb0_038z) + _1160; + float _1179 = ((mad(-0.20366770029067993f, _1162, mad(1.2036634683609009f, _1161, (_1160 * -2.57161445915699e-07f))) - _1161) * cb0_038z) + _1161; + float _1180 = ((mad(0.9999996423721313f, _1162, mad(2.0954757928848267e-08f, _1161, (_1160 * 1.862645149230957e-08f))) - _1162) * cb0_038z) + _1162; + + SetTonemappedAP1(_1178, _1179, _1180); + + float _1190 = max(0.0f, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].z), _1180, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].y), _1179, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].x) * _1178)))); + float _1191 = max(0.0f, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].z), _1180, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].y), _1179, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].x) * _1178)))); + float _1192 = max(0.0f, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].z), _1180, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].y), _1179, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].x) * _1178)))); + float _1218 = cb0_016x * (((cb0_041y + (cb0_041x * _1190)) * _1190) + cb0_041z); + float _1219 = cb0_016y * (((cb0_041y + (cb0_041x * _1191)) * _1191) + cb0_041z); + float _1220 = cb0_016z * (((cb0_041y + (cb0_041x * _1192)) * _1192) + cb0_041z); + float _1227 = ((cb0_015x - _1218) * cb0_015w) + _1218; + float _1228 = ((cb0_015y - _1219) * cb0_015w) + _1219; + float _1229 = ((cb0_015z - _1220) * cb0_015w) + _1220; + float _1230 = cb0_016x * mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].z), _820, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].y), _818, (_816 * (WorkingColorSpace_000.FWorkingColorSpaceConstants_192[0].x)))); + float _1231 = cb0_016y * mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].z), _820, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].y), _818, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[1].x) * _816))); + float _1232 = cb0_016z * mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].z), _820, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].y), _818, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_192[2].x) * _816))); + float _1239 = ((cb0_015x - _1230) * cb0_015w) + _1230; + float _1240 = ((cb0_015y - _1231) * cb0_015w) + _1231; + float _1241 = ((cb0_015z - _1232) * cb0_015w) + _1232; + float _1253 = exp2(log2(max(0.0f, _1227)) * cb0_042y); + float _1254 = exp2(log2(max(0.0f, _1228)) * cb0_042y); + float _1255 = exp2(log2(max(0.0f, _1229)) * cb0_042y); + + if (RENODX_TONE_MAP_TYPE != 0) { + u0[SV_DispatchThreadID] = GenerateOutput(float3(_1253, _1254, _1255), cb0_042w); + return; + } + + [branch] + if (cb0_042w == 0) { + do { + if (WorkingColorSpace_000.FWorkingColorSpaceConstants_384 == 0) { + float _1278 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _1253))); + float _1281 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _1253))); + float _1284 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _1253))); + _1295 = mad(_63, _1284, mad(_62, _1281, (_1278 * _61))); + _1296 = mad(_66, _1284, mad(_65, _1281, (_1278 * _64))); + _1297 = mad(_69, _1284, mad(_68, _1281, (_1278 * _67))); + } else { + _1295 = _1253; + _1296 = _1254; + _1297 = _1255; + } + do { + if (_1295 < 0.0031306699384003878f) { + _1308 = (_1295 * 12.920000076293945f); + } else { + _1308 = (((pow(_1295, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + do { + if (_1296 < 0.0031306699384003878f) { + _1319 = (_1296 * 12.920000076293945f); + } else { + _1319 = (((pow(_1296, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + if (_1297 < 0.0031306699384003878f) { + _2870 = _1308; + _2871 = _1319; + _2872 = (_1297 * 12.920000076293945f); + } else { + _2870 = _1308; + _2871 = _1319; + _2872 = (((pow(_1297, 0.4166666567325592f)) * 1.0549999475479126f) + -0.054999999701976776f); + } + } while (false); + } while (false); + } while (false); + } else { + if (cb0_042w == 1) { + float _1346 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _1253))); + float _1349 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _1253))); + float _1352 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _1253))); + float _1355 = mad(_63, _1352, mad(_62, _1349, (_1346 * _61))); + float _1358 = mad(_66, _1352, mad(_65, _1349, (_1346 * _64))); + float _1361 = mad(_69, _1352, mad(_68, _1349, (_1346 * _67))); + _2870 = min((_1355 * 4.5f), ((exp2(log2(max(_1355, 0.017999999225139618f)) * 0.44999998807907104f) * 1.0989999771118164f) + -0.0989999994635582f)); + _2871 = min((_1358 * 4.5f), ((exp2(log2(max(_1358, 0.017999999225139618f)) * 0.44999998807907104f) * 1.0989999771118164f) + -0.0989999994635582f)); + _2872 = min((_1361 * 4.5f), ((exp2(log2(max(_1361, 0.017999999225139618f)) * 0.44999998807907104f) * 1.0989999771118164f) + -0.0989999994635582f)); + } else { + if ((uint)((uint)((int)(cb0_042w) + -3u)) < (uint)2) { + _9[0] = cb0_010x; + _9[1] = cb0_010y; + _9[2] = cb0_010z; + _9[3] = cb0_010w; + _9[4] = cb0_012x; + _9[5] = cb0_012x; + float _1430 = cb0_012z * _1239; + float _1431 = cb0_012z * _1240; + float _1432 = cb0_012z * _1241; + float _1435 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].z), _1432, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].y), _1431, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].x) * _1430))); + float _1438 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].z), _1432, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].y), _1431, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].x) * _1430))); + float _1441 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].z), _1432, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].y), _1431, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].x) * _1430))); + float _1444 = mad(-0.21492856740951538f, _1441, mad(-0.2365107536315918f, _1438, (_1435 * 1.4514392614364624f))); + float _1447 = mad(-0.09967592358589172f, _1441, mad(1.17622971534729f, _1438, (_1435 * -0.07655377686023712f))); + float _1450 = mad(0.9977163076400757f, _1441, mad(-0.006032449658960104f, _1438, (_1435 * 0.008316148072481155f))); + float _1452 = max(_1444, max(_1447, _1450)); + do { + if (!(_1452 < 1.000000013351432e-10f)) { + if (!(((bool)((bool)(_1435 < 0.0f) || (bool)(_1438 < 0.0f))) || (bool)(_1441 < 0.0f))) { + float _1462 = abs(_1452); + float _1463 = (_1452 - _1444) / _1462; + float _1465 = (_1452 - _1447) / _1462; + float _1467 = (_1452 - _1450) / _1462; + do { + if (!(_1463 < 0.8149999976158142f)) { + float _1470 = _1463 + -0.8149999976158142f; + _1482 = ((_1470 / exp2(log2(exp2(log2(_1470 * 3.0552830696105957f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8149999976158142f); + } else { + _1482 = _1463; + } + do { + if (!(_1465 < 0.8029999732971191f)) { + float _1485 = _1465 + -0.8029999732971191f; + _1497 = ((_1485 / exp2(log2(exp2(log2(_1485 * 3.4972610473632812f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8029999732971191f); + } else { + _1497 = _1465; + } + do { + if (!(_1467 < 0.8799999952316284f)) { + float _1500 = _1467 + -0.8799999952316284f; + _1512 = ((_1500 / exp2(log2(exp2(log2(_1500 * 6.810994625091553f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8799999952316284f); + } else { + _1512 = _1467; + } + _1520 = (_1452 - (_1462 * _1482)); + _1521 = (_1452 - (_1462 * _1497)); + _1522 = (_1452 - (_1462 * _1512)); + } while (false); + } while (false); + } while (false); + } else { + _1520 = _1444; + _1521 = _1447; + _1522 = _1450; + } + } else { + _1520 = _1444; + _1521 = _1447; + _1522 = _1450; + } + float _1538 = ((mad(0.16386906802654266f, _1522, mad(0.14067870378494263f, _1521, (_1520 * 0.6954522132873535f))) - _1435) * cb0_012w) + _1435; + float _1539 = ((mad(0.0955343171954155f, _1522, mad(0.8596711158752441f, _1521, (_1520 * 0.044794563204050064f))) - _1438) * cb0_012w) + _1438; + float _1540 = ((mad(1.0015007257461548f, _1522, mad(0.004025210160762072f, _1521, (_1520 * -0.005525882821530104f))) - _1441) * cb0_012w) + _1441; + float _1544 = max(max(_1538, _1539), _1540); + float _1549 = (max(_1544, 1.000000013351432e-10f) - max(min(min(_1538, _1539), _1540), 1.000000013351432e-10f)) / max(_1544, 0.009999999776482582f); + float _1562 = ((_1539 + _1538) + _1540) + (sqrt((((_1540 - _1539) * _1540) + ((_1539 - _1538) * _1539)) + ((_1538 - _1540) * _1538)) * 1.75f); + float _1563 = _1562 * 0.3333333432674408f; + float _1564 = _1549 + -0.4000000059604645f; + float _1565 = _1564 * 5.0f; + float _1569 = max((1.0f - abs(_1564 * 2.5f)), 0.0f); + float _1580 = ((float((int)(((int)(uint)((bool)(_1565 > 0.0f))) - ((int)(uint)((bool)(_1565 < 0.0f))))) * (1.0f - (_1569 * _1569))) + 1.0f) * 0.02500000037252903f; + do { + if (!(_1563 <= 0.0533333346247673f)) { + if (!(_1563 >= 0.1599999964237213f)) { + _1589 = (((0.23999999463558197f / _1562) + -0.5f) * _1580); + } else { + _1589 = 0.0f; + } + } else { + _1589 = _1580; + } + float _1590 = _1589 + 1.0f; + float _1591 = _1590 * _1538; + float _1592 = _1590 * _1539; + float _1593 = _1590 * _1540; + do { + if (!((bool)(_1591 == _1592) && (bool)(_1592 == _1593))) { + float _1600 = ((_1591 * 2.0f) - _1592) - _1593; + float _1603 = ((_1539 - _1540) * 1.7320507764816284f) * _1590; + float _1605 = atan(_1603 / _1600); + bool _1608 = (_1600 < 0.0f); + bool _1609 = (_1600 == 0.0f); + bool _1610 = (_1603 >= 0.0f); + bool _1611 = (_1603 < 0.0f); + _1622 = select((_1610 && _1609), 90.0f, select((_1611 && _1609), -90.0f, (select((_1611 && _1608), (_1605 + -3.1415927410125732f), select((_1610 && _1608), (_1605 + 3.1415927410125732f), _1605)) * 57.2957763671875f))); + } else { + _1622 = 0.0f; + } + float _1627 = min(max(select((_1622 < 0.0f), (_1622 + 360.0f), _1622), 0.0f), 360.0f); + do { + if (_1627 < -180.0f) { + _1636 = (_1627 + 360.0f); + } else { + if (_1627 > 180.0f) { + _1636 = (_1627 + -360.0f); + } else { + _1636 = _1627; + } + } + do { + if ((bool)(_1636 > -67.5f) && (bool)(_1636 < 67.5f)) { + float _1642 = (_1636 + 67.5f) * 0.029629629105329514f; + int _1643 = int(_1642); + float _1645 = _1642 - float((int)(_1643)); + float _1646 = _1645 * _1645; + float _1647 = _1646 * _1645; + if (_1643 == 3) { + _1675 = (((0.1666666716337204f - (_1645 * 0.5f)) + (_1646 * 0.5f)) - (_1647 * 0.1666666716337204f)); + } else { + if (_1643 == 2) { + _1675 = ((0.6666666865348816f - _1646) + (_1647 * 0.5f)); + } else { + if (_1643 == 1) { + _1675 = (((_1647 * -0.5f) + 0.1666666716337204f) + ((_1646 + _1645) * 0.5f)); + } else { + _1675 = select((_1643 == 0), (_1647 * 0.1666666716337204f), 0.0f); + } + } + } + } else { + _1675 = 0.0f; + } + float _1684 = min(max(((((_1549 * 0.27000001072883606f) * (0.029999999329447746f - _1591)) * _1675) + _1591), 0.0f), 65535.0f); + float _1685 = min(max(_1592, 0.0f), 65535.0f); + float _1686 = min(max(_1593, 0.0f), 65535.0f); + float _1699 = min(max(mad(-0.21492856740951538f, _1686, mad(-0.2365107536315918f, _1685, (_1684 * 1.4514392614364624f))), 0.0f), 65504.0f); + float _1700 = min(max(mad(-0.09967592358589172f, _1686, mad(1.17622971534729f, _1685, (_1684 * -0.07655377686023712f))), 0.0f), 65504.0f); + float _1701 = min(max(mad(0.9977163076400757f, _1686, mad(-0.006032449658960104f, _1685, (_1684 * 0.008316148072481155f))), 0.0f), 65504.0f); + float _1702 = dot(float3(_1699, _1700, _1701), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + _16[0] = cb0_010x; + _16[1] = cb0_010y; + _16[2] = cb0_010z; + _16[3] = cb0_010w; + _16[4] = cb0_012x; + _16[5] = cb0_012x; + _17[0] = cb0_011x; + _17[1] = cb0_011y; + _17[2] = cb0_011z; + _17[3] = cb0_011w; + _17[4] = cb0_012y; + _17[5] = cb0_012y; + float _1725 = log2(max((lerp(_1702, _1699, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _1726 = _1725 * 0.3010300099849701f; + float _1727 = log2(cb0_008x); + float _1728 = _1727 * 0.3010300099849701f; + do { + if (!(!(_1726 <= _1728))) { + _1797 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _1735 = log2(cb0_009x); + float _1736 = _1735 * 0.3010300099849701f; + if ((bool)(_1726 > _1728) && (bool)(_1726 < _1736)) { + float _1744 = ((_1725 - _1727) * 0.9030900001525879f) / ((_1735 - _1727) * 0.3010300099849701f); + int _1745 = int(_1744); + float _1747 = _1744 - float((int)(_1745)); + float _1749 = _16[_1745]; + float _1752 = _16[(_1745 + 1)]; + float _1757 = _1749 * 0.5f; + _1797 = dot(float3((_1747 * _1747), _1747, 1.0f), float3(mad((_16[(_1745 + 2)]), 0.5f, mad(_1752, -1.0f, _1757)), (_1752 - _1749), mad(_1752, 0.5f, _1757))); + } else { + do { + if (!(!(_1726 >= _1736))) { + float _1766 = log2(cb0_008z); + if (_1726 < (_1766 * 0.3010300099849701f)) { + float _1774 = ((_1725 - _1735) * 0.9030900001525879f) / ((_1766 - _1735) * 0.3010300099849701f); + int _1775 = int(_1774); + float _1777 = _1774 - float((int)(_1775)); + float _1779 = _17[_1775]; + float _1782 = _17[(_1775 + 1)]; + float _1787 = _1779 * 0.5f; + _1797 = dot(float3((_1777 * _1777), _1777, 1.0f), float3(mad((_17[(_1775 + 2)]), 0.5f, mad(_1782, -1.0f, _1787)), (_1782 - _1779), mad(_1782, 0.5f, _1787))); + break; + } + } + _1797 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + _18[0] = cb0_011x; + _18[1] = cb0_011y; + _18[2] = cb0_011z; + _18[3] = cb0_011w; + _18[4] = cb0_012y; + _18[5] = cb0_012y; + float _1807 = log2(max((lerp(_1702, _1700, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _1808 = _1807 * 0.3010300099849701f; + do { + if (!(!(_1808 <= _1728))) { + _1877 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _1815 = log2(cb0_009x); + float _1816 = _1815 * 0.3010300099849701f; + if ((bool)(_1808 > _1728) && (bool)(_1808 < _1816)) { + float _1824 = ((_1807 - _1727) * 0.9030900001525879f) / ((_1815 - _1727) * 0.3010300099849701f); + int _1825 = int(_1824); + float _1827 = _1824 - float((int)(_1825)); + float _1829 = _9[_1825]; + float _1832 = _9[(_1825 + 1)]; + float _1837 = _1829 * 0.5f; + _1877 = dot(float3((_1827 * _1827), _1827, 1.0f), float3(mad((_9[(_1825 + 2)]), 0.5f, mad(_1832, -1.0f, _1837)), (_1832 - _1829), mad(_1832, 0.5f, _1837))); + } else { + do { + if (!(!(_1808 >= _1816))) { + float _1846 = log2(cb0_008z); + if (_1808 < (_1846 * 0.3010300099849701f)) { + float _1854 = ((_1807 - _1815) * 0.9030900001525879f) / ((_1846 - _1815) * 0.3010300099849701f); + int _1855 = int(_1854); + float _1857 = _1854 - float((int)(_1855)); + float _1859 = _18[_1855]; + float _1862 = _18[(_1855 + 1)]; + float _1867 = _1859 * 0.5f; + _1877 = dot(float3((_1857 * _1857), _1857, 1.0f), float3(mad((_18[(_1855 + 2)]), 0.5f, mad(_1862, -1.0f, _1867)), (_1862 - _1859), mad(_1862, 0.5f, _1867))); + break; + } + } + _1877 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + _19[0] = cb0_010x; + _19[1] = cb0_010y; + _19[2] = cb0_010z; + _19[3] = cb0_010w; + _19[4] = cb0_012x; + _19[5] = cb0_012x; + _20[0] = cb0_011x; + _20[1] = cb0_011y; + _20[2] = cb0_011z; + _20[3] = cb0_011w; + _20[4] = cb0_012y; + _20[5] = cb0_012y; + float _1893 = log2(max((lerp(_1702, _1701, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _1894 = _1893 * 0.3010300099849701f; + do { + if (!(!(_1894 <= _1728))) { + _1963 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _1901 = log2(cb0_009x); + float _1902 = _1901 * 0.3010300099849701f; + if ((bool)(_1894 > _1728) && (bool)(_1894 < _1902)) { + float _1910 = ((_1893 - _1727) * 0.9030900001525879f) / ((_1901 - _1727) * 0.3010300099849701f); + int _1911 = int(_1910); + float _1913 = _1910 - float((int)(_1911)); + float _1915 = _19[_1911]; + float _1918 = _19[(_1911 + 1)]; + float _1923 = _1915 * 0.5f; + _1963 = dot(float3((_1913 * _1913), _1913, 1.0f), float3(mad((_19[(_1911 + 2)]), 0.5f, mad(_1918, -1.0f, _1923)), (_1918 - _1915), mad(_1918, 0.5f, _1923))); + } else { + do { + if (!(!(_1894 >= _1902))) { + float _1932 = log2(cb0_008z); + if (_1894 < (_1932 * 0.3010300099849701f)) { + float _1940 = ((_1893 - _1901) * 0.9030900001525879f) / ((_1932 - _1901) * 0.3010300099849701f); + int _1941 = int(_1940); + float _1943 = _1940 - float((int)(_1941)); + float _1945 = _20[_1941]; + float _1948 = _20[(_1941 + 1)]; + float _1953 = _1945 * 0.5f; + _1963 = dot(float3((_1943 * _1943), _1943, 1.0f), float3(mad((_20[(_1941 + 2)]), 0.5f, mad(_1948, -1.0f, _1953)), (_1948 - _1945), mad(_1948, 0.5f, _1953))); + break; + } + } + _1963 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + float _1967 = cb0_008w - cb0_008y; + float _1968 = (exp2(_1797 * 3.321928024291992f) - cb0_008y) / _1967; + float _1970 = (exp2(_1877 * 3.321928024291992f) - cb0_008y) / _1967; + float _1972 = (exp2(_1963 * 3.321928024291992f) - cb0_008y) / _1967; + float _1975 = mad(0.15618768334388733f, _1972, mad(0.13400420546531677f, _1970, (_1968 * 0.6624541878700256f))); + float _1978 = mad(0.053689517080783844f, _1972, mad(0.6740817427635193f, _1970, (_1968 * 0.2722287178039551f))); + float _1981 = mad(1.0103391408920288f, _1972, mad(0.00406073359772563f, _1970, (_1968 * -0.005574649665504694f))); + float _1994 = min(max(mad(-0.23642469942569733f, _1981, mad(-0.32480329275131226f, _1978, (_1975 * 1.6410233974456787f))), 0.0f), 1.0f); + float _1995 = min(max(mad(0.016756348311901093f, _1981, mad(1.6153316497802734f, _1978, (_1975 * -0.663662850856781f))), 0.0f), 1.0f); + float _1996 = min(max(mad(0.9883948564529419f, _1981, mad(-0.008284442126750946f, _1978, (_1975 * 0.011721894145011902f))), 0.0f), 1.0f); + float _1999 = mad(0.15618768334388733f, _1996, mad(0.13400420546531677f, _1995, (_1994 * 0.6624541878700256f))); + float _2002 = mad(0.053689517080783844f, _1996, mad(0.6740817427635193f, _1995, (_1994 * 0.2722287178039551f))); + float _2005 = mad(1.0103391408920288f, _1996, mad(0.00406073359772563f, _1995, (_1994 * -0.005574649665504694f))); + float _2027 = min(max((min(max(mad(-0.23642469942569733f, _2005, mad(-0.32480329275131226f, _2002, (_1999 * 1.6410233974456787f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f); + float _2028 = min(max((min(max(mad(0.016756348311901093f, _2005, mad(1.6153316497802734f, _2002, (_1999 * -0.663662850856781f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f); + float _2029 = min(max((min(max(mad(0.9883948564529419f, _2005, mad(-0.008284442126750946f, _2002, (_1999 * 0.011721894145011902f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f); + float _2048 = exp2(log2(mad(_63, _2029, mad(_62, _2028, (_2027 * _61))) * 9.999999747378752e-05f) * 0.1593017578125f); + float _2049 = exp2(log2(mad(_66, _2029, mad(_65, _2028, (_2027 * _64))) * 9.999999747378752e-05f) * 0.1593017578125f); + float _2050 = exp2(log2(mad(_69, _2029, mad(_68, _2028, (_2027 * _67))) * 9.999999747378752e-05f) * 0.1593017578125f); + _2870 = exp2(log2((1.0f / ((_2048 * 18.6875f) + 1.0f)) * ((_2048 * 18.8515625f) + 0.8359375f)) * 78.84375f); + _2871 = exp2(log2((1.0f / ((_2049 * 18.6875f) + 1.0f)) * ((_2049 * 18.8515625f) + 0.8359375f)) * 78.84375f); + _2872 = exp2(log2((1.0f / ((_2050 * 18.6875f) + 1.0f)) * ((_2050 * 18.8515625f) + 0.8359375f)) * 78.84375f); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } else { + if ((uint)((uint)((int)(cb0_042w) + -5u)) < (uint)2) { + float _2116 = cb0_012z * _1239; + float _2117 = cb0_012z * _1240; + float _2118 = cb0_012z * _1241; + float _2121 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].z), _2118, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].y), _2117, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[0].x) * _2116))); + float _2124 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].z), _2118, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].y), _2117, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[1].x) * _2116))); + float _2127 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].z), _2118, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].y), _2117, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_256[2].x) * _2116))); + float _2130 = mad(-0.21492856740951538f, _2127, mad(-0.2365107536315918f, _2124, (_2121 * 1.4514392614364624f))); + float _2133 = mad(-0.09967592358589172f, _2127, mad(1.17622971534729f, _2124, (_2121 * -0.07655377686023712f))); + float _2136 = mad(0.9977163076400757f, _2127, mad(-0.006032449658960104f, _2124, (_2121 * 0.008316148072481155f))); + float _2138 = max(_2130, max(_2133, _2136)); + do { + if (!(_2138 < 1.000000013351432e-10f)) { + if (!(((bool)((bool)(_2121 < 0.0f) || (bool)(_2124 < 0.0f))) || (bool)(_2127 < 0.0f))) { + float _2148 = abs(_2138); + float _2149 = (_2138 - _2130) / _2148; + float _2151 = (_2138 - _2133) / _2148; + float _2153 = (_2138 - _2136) / _2148; + do { + if (!(_2149 < 0.8149999976158142f)) { + float _2156 = _2149 + -0.8149999976158142f; + _2168 = ((_2156 / exp2(log2(exp2(log2(_2156 * 3.0552830696105957f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8149999976158142f); + } else { + _2168 = _2149; + } + do { + if (!(_2151 < 0.8029999732971191f)) { + float _2171 = _2151 + -0.8029999732971191f; + _2183 = ((_2171 / exp2(log2(exp2(log2(_2171 * 3.4972610473632812f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8029999732971191f); + } else { + _2183 = _2151; + } + do { + if (!(_2153 < 0.8799999952316284f)) { + float _2186 = _2153 + -0.8799999952316284f; + _2198 = ((_2186 / exp2(log2(exp2(log2(_2186 * 6.810994625091553f) * 1.2000000476837158f) + 1.0f) * 0.8333333134651184f)) + 0.8799999952316284f); + } else { + _2198 = _2153; + } + _2206 = (_2138 - (_2148 * _2168)); + _2207 = (_2138 - (_2148 * _2183)); + _2208 = (_2138 - (_2148 * _2198)); + } while (false); + } while (false); + } while (false); + } else { + _2206 = _2130; + _2207 = _2133; + _2208 = _2136; + } + } else { + _2206 = _2130; + _2207 = _2133; + _2208 = _2136; + } + float _2224 = ((mad(0.16386906802654266f, _2208, mad(0.14067870378494263f, _2207, (_2206 * 0.6954522132873535f))) - _2121) * cb0_012w) + _2121; + float _2225 = ((mad(0.0955343171954155f, _2208, mad(0.8596711158752441f, _2207, (_2206 * 0.044794563204050064f))) - _2124) * cb0_012w) + _2124; + float _2226 = ((mad(1.0015007257461548f, _2208, mad(0.004025210160762072f, _2207, (_2206 * -0.005525882821530104f))) - _2127) * cb0_012w) + _2127; + float _2230 = max(max(_2224, _2225), _2226); + float _2235 = (max(_2230, 1.000000013351432e-10f) - max(min(min(_2224, _2225), _2226), 1.000000013351432e-10f)) / max(_2230, 0.009999999776482582f); + float _2248 = ((_2225 + _2224) + _2226) + (sqrt((((_2226 - _2225) * _2226) + ((_2225 - _2224) * _2225)) + ((_2224 - _2226) * _2224)) * 1.75f); + float _2249 = _2248 * 0.3333333432674408f; + float _2250 = _2235 + -0.4000000059604645f; + float _2251 = _2250 * 5.0f; + float _2255 = max((1.0f - abs(_2250 * 2.5f)), 0.0f); + float _2266 = ((float((int)(((int)(uint)((bool)(_2251 > 0.0f))) - ((int)(uint)((bool)(_2251 < 0.0f))))) * (1.0f - (_2255 * _2255))) + 1.0f) * 0.02500000037252903f; + do { + if (!(_2249 <= 0.0533333346247673f)) { + if (!(_2249 >= 0.1599999964237213f)) { + _2275 = (((0.23999999463558197f / _2248) + -0.5f) * _2266); + } else { + _2275 = 0.0f; + } + } else { + _2275 = _2266; + } + float _2276 = _2275 + 1.0f; + float _2277 = _2276 * _2224; + float _2278 = _2276 * _2225; + float _2279 = _2276 * _2226; + do { + if (!((bool)(_2277 == _2278) && (bool)(_2278 == _2279))) { + float _2286 = ((_2277 * 2.0f) - _2278) - _2279; + float _2289 = ((_2225 - _2226) * 1.7320507764816284f) * _2276; + float _2291 = atan(_2289 / _2286); + bool _2294 = (_2286 < 0.0f); + bool _2295 = (_2286 == 0.0f); + bool _2296 = (_2289 >= 0.0f); + bool _2297 = (_2289 < 0.0f); + _2308 = select((_2296 && _2295), 90.0f, select((_2297 && _2295), -90.0f, (select((_2297 && _2294), (_2291 + -3.1415927410125732f), select((_2296 && _2294), (_2291 + 3.1415927410125732f), _2291)) * 57.2957763671875f))); + } else { + _2308 = 0.0f; + } + float _2313 = min(max(select((_2308 < 0.0f), (_2308 + 360.0f), _2308), 0.0f), 360.0f); + do { + if (_2313 < -180.0f) { + _2322 = (_2313 + 360.0f); + } else { + if (_2313 > 180.0f) { + _2322 = (_2313 + -360.0f); + } else { + _2322 = _2313; + } + } + do { + if ((bool)(_2322 > -67.5f) && (bool)(_2322 < 67.5f)) { + float _2328 = (_2322 + 67.5f) * 0.029629629105329514f; + int _2329 = int(_2328); + float _2331 = _2328 - float((int)(_2329)); + float _2332 = _2331 * _2331; + float _2333 = _2332 * _2331; + if (_2329 == 3) { + _2361 = (((0.1666666716337204f - (_2331 * 0.5f)) + (_2332 * 0.5f)) - (_2333 * 0.1666666716337204f)); + } else { + if (_2329 == 2) { + _2361 = ((0.6666666865348816f - _2332) + (_2333 * 0.5f)); + } else { + if (_2329 == 1) { + _2361 = (((_2333 * -0.5f) + 0.1666666716337204f) + ((_2332 + _2331) * 0.5f)); + } else { + _2361 = select((_2329 == 0), (_2333 * 0.1666666716337204f), 0.0f); + } + } + } + } else { + _2361 = 0.0f; + } + float _2370 = min(max(((((_2235 * 0.27000001072883606f) * (0.029999999329447746f - _2277)) * _2361) + _2277), 0.0f), 65535.0f); + float _2371 = min(max(_2278, 0.0f), 65535.0f); + float _2372 = min(max(_2279, 0.0f), 65535.0f); + float _2385 = min(max(mad(-0.21492856740951538f, _2372, mad(-0.2365107536315918f, _2371, (_2370 * 1.4514392614364624f))), 0.0f), 65504.0f); + float _2386 = min(max(mad(-0.09967592358589172f, _2372, mad(1.17622971534729f, _2371, (_2370 * -0.07655377686023712f))), 0.0f), 65504.0f); + float _2387 = min(max(mad(0.9977163076400757f, _2372, mad(-0.006032449658960104f, _2371, (_2370 * 0.008316148072481155f))), 0.0f), 65504.0f); + float _2388 = dot(float3(_2385, _2386, _2387), float3(0.2722287178039551f, 0.6740817427635193f, 0.053689517080783844f)); + _10[0] = cb0_010x; + _10[1] = cb0_010y; + _10[2] = cb0_010z; + _10[3] = cb0_010w; + _10[4] = cb0_012x; + _10[5] = cb0_012x; + _11[0] = cb0_011x; + _11[1] = cb0_011y; + _11[2] = cb0_011z; + _11[3] = cb0_011w; + _11[4] = cb0_012y; + _11[5] = cb0_012y; + float _2411 = log2(max((lerp(_2388, _2385, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _2412 = _2411 * 0.3010300099849701f; + float _2413 = log2(cb0_008x); + float _2414 = _2413 * 0.3010300099849701f; + do { + if (!(!(_2412 <= _2414))) { + _2483 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _2421 = log2(cb0_009x); + float _2422 = _2421 * 0.3010300099849701f; + if ((bool)(_2412 > _2414) && (bool)(_2412 < _2422)) { + float _2430 = ((_2411 - _2413) * 0.9030900001525879f) / ((_2421 - _2413) * 0.3010300099849701f); + int _2431 = int(_2430); + float _2433 = _2430 - float((int)(_2431)); + float _2435 = _10[_2431]; + float _2438 = _10[(_2431 + 1)]; + float _2443 = _2435 * 0.5f; + _2483 = dot(float3((_2433 * _2433), _2433, 1.0f), float3(mad((_10[(_2431 + 2)]), 0.5f, mad(_2438, -1.0f, _2443)), (_2438 - _2435), mad(_2438, 0.5f, _2443))); + } else { + do { + if (!(!(_2412 >= _2422))) { + float _2452 = log2(cb0_008z); + if (_2412 < (_2452 * 0.3010300099849701f)) { + float _2460 = ((_2411 - _2421) * 0.9030900001525879f) / ((_2452 - _2421) * 0.3010300099849701f); + int _2461 = int(_2460); + float _2463 = _2460 - float((int)(_2461)); + float _2465 = _11[_2461]; + float _2468 = _11[(_2461 + 1)]; + float _2473 = _2465 * 0.5f; + _2483 = dot(float3((_2463 * _2463), _2463, 1.0f), float3(mad((_11[(_2461 + 2)]), 0.5f, mad(_2468, -1.0f, _2473)), (_2468 - _2465), mad(_2468, 0.5f, _2473))); + break; + } + } + _2483 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + _12[0] = cb0_010x; + _12[1] = cb0_010y; + _12[2] = cb0_010z; + _12[3] = cb0_010w; + _12[4] = cb0_012x; + _12[5] = cb0_012x; + _13[0] = cb0_011x; + _13[1] = cb0_011y; + _13[2] = cb0_011z; + _13[3] = cb0_011w; + _13[4] = cb0_012y; + _13[5] = cb0_012y; + float _2499 = log2(max((lerp(_2388, _2386, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _2500 = _2499 * 0.3010300099849701f; + do { + if (!(!(_2500 <= _2414))) { + _2569 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _2507 = log2(cb0_009x); + float _2508 = _2507 * 0.3010300099849701f; + if ((bool)(_2500 > _2414) && (bool)(_2500 < _2508)) { + float _2516 = ((_2499 - _2413) * 0.9030900001525879f) / ((_2507 - _2413) * 0.3010300099849701f); + int _2517 = int(_2516); + float _2519 = _2516 - float((int)(_2517)); + float _2521 = _12[_2517]; + float _2524 = _12[(_2517 + 1)]; + float _2529 = _2521 * 0.5f; + _2569 = dot(float3((_2519 * _2519), _2519, 1.0f), float3(mad((_12[(_2517 + 2)]), 0.5f, mad(_2524, -1.0f, _2529)), (_2524 - _2521), mad(_2524, 0.5f, _2529))); + } else { + do { + if (!(!(_2500 >= _2508))) { + float _2538 = log2(cb0_008z); + if (_2500 < (_2538 * 0.3010300099849701f)) { + float _2546 = ((_2499 - _2507) * 0.9030900001525879f) / ((_2538 - _2507) * 0.3010300099849701f); + int _2547 = int(_2546); + float _2549 = _2546 - float((int)(_2547)); + float _2551 = _13[_2547]; + float _2554 = _13[(_2547 + 1)]; + float _2559 = _2551 * 0.5f; + _2569 = dot(float3((_2549 * _2549), _2549, 1.0f), float3(mad((_13[(_2547 + 2)]), 0.5f, mad(_2554, -1.0f, _2559)), (_2554 - _2551), mad(_2554, 0.5f, _2559))); + break; + } + } + _2569 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + _14[0] = cb0_010x; + _14[1] = cb0_010y; + _14[2] = cb0_010z; + _14[3] = cb0_010w; + _14[4] = cb0_012x; + _14[5] = cb0_012x; + _15[0] = cb0_011x; + _15[1] = cb0_011y; + _15[2] = cb0_011z; + _15[3] = cb0_011w; + _15[4] = cb0_012y; + _15[5] = cb0_012y; + float _2585 = log2(max((lerp(_2388, _2387, 0.9599999785423279f)), 1.000000013351432e-10f)); + float _2586 = _2585 * 0.3010300099849701f; + do { + if (!(!(_2586 <= _2414))) { + _2655 = (log2(cb0_008y) * 0.3010300099849701f); + } else { + float _2593 = log2(cb0_009x); + float _2594 = _2593 * 0.3010300099849701f; + if ((bool)(_2586 > _2414) && (bool)(_2586 < _2594)) { + float _2602 = ((_2585 - _2413) * 0.9030900001525879f) / ((_2593 - _2413) * 0.3010300099849701f); + int _2603 = int(_2602); + float _2605 = _2602 - float((int)(_2603)); + float _2607 = _14[_2603]; + float _2610 = _14[(_2603 + 1)]; + float _2615 = _2607 * 0.5f; + _2655 = dot(float3((_2605 * _2605), _2605, 1.0f), float3(mad((_14[(_2603 + 2)]), 0.5f, mad(_2610, -1.0f, _2615)), (_2610 - _2607), mad(_2610, 0.5f, _2615))); + } else { + do { + if (!(!(_2586 >= _2594))) { + float _2624 = log2(cb0_008z); + if (_2586 < (_2624 * 0.3010300099849701f)) { + float _2632 = ((_2585 - _2593) * 0.9030900001525879f) / ((_2624 - _2593) * 0.3010300099849701f); + int _2633 = int(_2632); + float _2635 = _2632 - float((int)(_2633)); + float _2637 = _15[_2633]; + float _2640 = _15[(_2633 + 1)]; + float _2645 = _2637 * 0.5f; + _2655 = dot(float3((_2635 * _2635), _2635, 1.0f), float3(mad((_15[(_2633 + 2)]), 0.5f, mad(_2640, -1.0f, _2645)), (_2640 - _2637), mad(_2640, 0.5f, _2645))); + break; + } + } + _2655 = (log2(cb0_008w) * 0.3010300099849701f); + } while (false); + } + } + float _2659 = cb0_008w - cb0_008y; + float _2660 = (exp2(_2483 * 3.321928024291992f) - cb0_008y) / _2659; + float _2662 = (exp2(_2569 * 3.321928024291992f) - cb0_008y) / _2659; + float _2664 = (exp2(_2655 * 3.321928024291992f) - cb0_008y) / _2659; + float _2667 = mad(0.15618768334388733f, _2664, mad(0.13400420546531677f, _2662, (_2660 * 0.6624541878700256f))); + float _2670 = mad(0.053689517080783844f, _2664, mad(0.6740817427635193f, _2662, (_2660 * 0.2722287178039551f))); + float _2673 = mad(1.0103391408920288f, _2664, mad(0.00406073359772563f, _2662, (_2660 * -0.005574649665504694f))); + float _2686 = min(max(mad(-0.23642469942569733f, _2673, mad(-0.32480329275131226f, _2670, (_2667 * 1.6410233974456787f))), 0.0f), 1.0f); + float _2687 = min(max(mad(0.016756348311901093f, _2673, mad(1.6153316497802734f, _2670, (_2667 * -0.663662850856781f))), 0.0f), 1.0f); + float _2688 = min(max(mad(0.9883948564529419f, _2673, mad(-0.008284442126750946f, _2670, (_2667 * 0.011721894145011902f))), 0.0f), 1.0f); + float _2691 = mad(0.15618768334388733f, _2688, mad(0.13400420546531677f, _2687, (_2686 * 0.6624541878700256f))); + float _2694 = mad(0.053689517080783844f, _2688, mad(0.6740817427635193f, _2687, (_2686 * 0.2722287178039551f))); + float _2697 = mad(1.0103391408920288f, _2688, mad(0.00406073359772563f, _2687, (_2686 * -0.005574649665504694f))); + float _2719 = min(max((min(max(mad(-0.23642469942569733f, _2697, mad(-0.32480329275131226f, _2694, (_2691 * 1.6410233974456787f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f); + float _2722 = min(max((min(max(mad(0.016756348311901093f, _2697, mad(1.6153316497802734f, _2694, (_2691 * -0.663662850856781f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f) * 0.012500000186264515f; + float _2723 = min(max((min(max(mad(0.9883948564529419f, _2697, mad(-0.008284442126750946f, _2694, (_2691 * 0.011721894145011902f))), 0.0f), 65535.0f) * cb0_008w), 0.0f), 65535.0f) * 0.012500000186264515f; + _2870 = mad(-0.0832589864730835f, _2723, mad(-0.6217921376228333f, _2722, (_2719 * 0.0213131383061409f))); + _2871 = mad(-0.010548308491706848f, _2723, mad(1.140804648399353f, _2722, (_2719 * -0.0016282059950754046f))); + _2872 = mad(1.1529725790023804f, _2723, mad(-0.1289689838886261f, _2722, (_2719 * -0.00030004189466126263f))); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } while (false); + } else { + if (cb0_042w == 7) { + float _2750 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _1241, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _1240, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _1239))); + float _2753 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _1241, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _1240, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _1239))); + float _2756 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _1241, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _1240, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _1239))); + float _2775 = exp2(log2(mad(_63, _2756, mad(_62, _2753, (_2750 * _61))) * 9.999999747378752e-05f) * 0.1593017578125f); + float _2776 = exp2(log2(mad(_66, _2756, mad(_65, _2753, (_2750 * _64))) * 9.999999747378752e-05f) * 0.1593017578125f); + float _2777 = exp2(log2(mad(_69, _2756, mad(_68, _2753, (_2750 * _67))) * 9.999999747378752e-05f) * 0.1593017578125f); + _2870 = exp2(log2((1.0f / ((_2775 * 18.6875f) + 1.0f)) * ((_2775 * 18.8515625f) + 0.8359375f)) * 78.84375f); + _2871 = exp2(log2((1.0f / ((_2776 * 18.6875f) + 1.0f)) * ((_2776 * 18.8515625f) + 0.8359375f)) * 78.84375f); + _2872 = exp2(log2((1.0f / ((_2777 * 18.6875f) + 1.0f)) * ((_2777 * 18.8515625f) + 0.8359375f)) * 78.84375f); + } else { + if (!(cb0_042w == 8)) { + if (cb0_042w == 9) { + float _2824 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _1229, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _1228, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _1227))); + float _2827 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _1229, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _1228, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _1227))); + float _2830 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _1229, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _1228, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _1227))); + _2870 = mad(_63, _2830, mad(_62, _2827, (_2824 * _61))); + _2871 = mad(_66, _2830, mad(_65, _2827, (_2824 * _64))); + _2872 = mad(_69, _2830, mad(_68, _2827, (_2824 * _67))); + } else { + float _2843 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[0].x) * _1253))); + float _2846 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[1].x) * _1253))); + float _2849 = mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].z), _1255, mad((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].y), _1254, ((WorkingColorSpace_000.FWorkingColorSpaceConstants_128[2].x) * _1253))); + _2870 = exp2(log2(mad(_63, _2849, mad(_62, _2846, (_2843 * _61)))) * cb0_042z); + _2871 = exp2(log2(mad(_66, _2849, mad(_65, _2846, (_2843 * _64)))) * cb0_042z); + _2872 = exp2(log2(mad(_69, _2849, mad(_68, _2846, (_2843 * _67)))) * cb0_042z); + } + } else { + _2870 = _1239; + _2871 = _1240; + _2872 = _1241; + } + } + } + } + } + } + u0[int3((uint)(SV_DispatchThreadID.x), (uint)(SV_DispatchThreadID.y), (uint)(SV_DispatchThreadID.z))] = float4((_2870 * 0.9523810148239136f), (_2871 * 0.9523810148239136f), (_2872 * 0.9523810148239136f), 0.0f); +}