@@ -523,6 +523,167 @@ float3 GamutCompressWeightedLMSCoreRGBBoundFromAdaptiveWeightedInputPrecise(
523523 strength);
524524}
525525
526+ float ComputeGamutCompressionScaleWeightedLMSCoreRGBBoundFromWeightedInput (
527+ float3 lms_weighted_input,
528+ float2 bound_r,
529+ float2 bound_g,
530+ float2 bound_b,
531+ float strength) {
532+ float3 lms_weighted_clamped = ClampWeightedLMSToCIE1702 (max (lms_weighted_input, 0 ));
533+ float3 mb = renodx::color ::macleod_boynton::from::WeightedLMS (lms_weighted_clamped);
534+ float y_mb = mb.z;
535+ float2 ls = mb.xy;
536+ if (!(y_mb > EPSILON)) {
537+ return 1.f ;
538+ }
539+
540+ float2 mb_white = CIE1702WhiteChromaticity ();
541+ float2 direction = ls - mb_white;
542+ if (dot (direction, direction) <= MB_NEAR_WHITE_EPSILON) {
543+ return 1.f ;
544+ }
545+
546+ bool has_peak = false ;
547+ float t_peak = RayMaxT_RGBTriangleInMB (
548+ mb_white, direction, bound_r, bound_g, bound_b, has_peak);
549+ float t_clip = RayExitTCIE1702D (direction);
550+ if (!has_peak) {
551+ t_peak = t_clip;
552+ }
553+
554+ float t_hard = saturate (t_peak);
555+ float t_soft = NeutwoScaleFromRayT (min (t_peak, t_clip), t_clip);
556+ float soft_mix = saturate (strength) * SoftCompressionActivationFromRayT (t_peak);
557+ return lerp (t_hard, t_soft, soft_mix);
558+ }
559+
560+ float ComputeGamutCompressionScaleWeightedLMSCoreRGBBoundFromWeightedInput (
561+ float3 lms_weighted_input,
562+ float3x3 bound_rgb_to_lms_weighted_mat,
563+ float strength) {
564+ float2 bound_r;
565+ float2 bound_g;
566+ float2 bound_b;
567+ MakeRGBTriangleInMBWeighted (bound_rgb_to_lms_weighted_mat, bound_r, bound_g, bound_b);
568+ return ComputeGamutCompressionScaleWeightedLMSCoreRGBBoundFromWeightedInput (
569+ lms_weighted_input,
570+ bound_r,
571+ bound_g,
572+ bound_b,
573+ strength);
574+ }
575+
576+ float ComputeGamutCompressionScaleWeightedLMSCoreRGBBoundFromAdaptiveWeightedInput (
577+ float3 lms_weighted_input,
578+ float3 current_adaptive_state_lms,
579+ float3x3 bound_rgb_to_lms_weighted_mat,
580+ float strength) {
581+ float2 bound_r;
582+ float2 bound_g;
583+ float2 bound_b;
584+ MakeRGBTriangleInMBAdaptiveWeighted (
585+ bound_rgb_to_lms_weighted_mat,
586+ current_adaptive_state_lms,
587+ bound_r,
588+ bound_g,
589+ bound_b);
590+ return ComputeGamutCompressionScaleWeightedLMSCoreRGBBoundFromWeightedInput (
591+ lms_weighted_input,
592+ bound_r,
593+ bound_g,
594+ bound_b,
595+ strength);
596+ }
597+
598+ float3 CompressWeightedLMSFromCIE1702White (float3 lms_weighted_input, float compression_scale) {
599+ float3 lms_weighted_clamped = ClampWeightedLMSToCIE1702 (max (lms_weighted_input, 0 ));
600+ float3 mb = renodx::color ::macleod_boynton::from::WeightedLMS (lms_weighted_clamped);
601+ float y_mb = mb.z;
602+ float2 ls = mb.xy;
603+ if (!(y_mb > EPSILON)) {
604+ return float3 (lms_weighted_clamped.x, lms_weighted_clamped.y, 0.f );
605+ }
606+
607+ float2 mb_white = CIE1702WhiteChromaticity ();
608+ float2 direction = ls - mb_white;
609+ if (dot (direction, direction) <= MB_NEAR_WHITE_EPSILON) {
610+ return lms_weighted_clamped;
611+ }
612+
613+ float2 ls_out = mb_white + saturate (compression_scale) * direction;
614+ return renodx::color ::macleod_boynton::WeightedLMSFromMacleodBoynton (ls_out, y_mb);
615+ }
616+
617+ float3 DecompressWeightedLMSFromCIE1702White (float3 lms_weighted_input, float compression_scale) {
618+ float3 lms_weighted_clamped = max (lms_weighted_input, 0 );
619+ float3 mb = renodx::color ::macleod_boynton::from::WeightedLMS (lms_weighted_clamped);
620+ float y_mb = mb.z;
621+ float2 ls = mb.xy;
622+ if (!(y_mb > EPSILON)) {
623+ return float3 (lms_weighted_clamped.x, lms_weighted_clamped.y, 0.f );
624+ }
625+
626+ float2 mb_white = CIE1702WhiteChromaticity ();
627+ float2 direction = ls - mb_white;
628+ if (dot (direction, direction) <= MB_NEAR_WHITE_EPSILON) {
629+ return lms_weighted_clamped;
630+ }
631+
632+ float safe_scale = max (compression_scale, 1e-6f );
633+ float2 ls_out = mb_white + direction * rcp (safe_scale);
634+ return renodx::color ::macleod_boynton::WeightedLMSFromMacleodBoynton (ls_out, y_mb);
635+ }
636+
637+ float ComputeGamutCompressionScaleBT709AdaptiveD65 (
638+ float3 bt709_input,
639+ float3 current_adaptive_state_lms,
640+ float strength = 1.f ) {
641+ float3 lms_input = renodx::color ::lms::from::BT709 (bt709_input);
642+ float3 lms_weighted_relative = renodx::math::DivideSafe (
643+ renodx::color ::macleod_boynton::WeighLMS (lms_input),
644+ current_adaptive_state_lms,
645+ 0.f );
646+ return ComputeGamutCompressionScaleWeightedLMSCoreRGBBoundFromAdaptiveWeightedInput (
647+ lms_weighted_relative,
648+ current_adaptive_state_lms,
649+ renodx::color ::macleod_boynton::BT709_TO_LMS_WEIGHTED_MAT,
650+ strength);
651+ }
652+
653+ float3 GamutCompressBT709AdaptiveD65 (
654+ float3 bt709_input,
655+ float3 current_adaptive_state_lms,
656+ float compression_scale) {
657+ float3 lms_input = renodx::color ::lms::from::BT709 (bt709_input);
658+ float3 lms_weighted_relative = renodx::math::DivideSafe (
659+ renodx::color ::macleod_boynton::WeighLMS (lms_input),
660+ current_adaptive_state_lms,
661+ 0.f );
662+ float3 lms_weighted_relative_out = CompressWeightedLMSFromCIE1702White (
663+ lms_weighted_relative,
664+ compression_scale);
665+ return renodx::color ::bt709::from::LMS (
666+ renodx::color ::macleod_boynton::UnweighLMS (
667+ lms_weighted_relative_out * max (current_adaptive_state_lms, 1e-6f )));
668+ }
669+
670+ float3 GamutDecompressBT709AdaptiveD65 (
671+ float3 bt709_input,
672+ float3 current_adaptive_state_lms,
673+ float compression_scale) {
674+ float3 lms_input = renodx::color ::lms::from::BT709 (bt709_input);
675+ float3 lms_weighted_relative = renodx::math::DivideSafe (
676+ renodx::color ::macleod_boynton::WeighLMS (lms_input),
677+ current_adaptive_state_lms,
678+ 0.f );
679+ float3 lms_weighted_relative_out = DecompressWeightedLMSFromCIE1702White (
680+ lms_weighted_relative,
681+ compression_scale);
682+ return renodx::color ::bt709::from::LMS (
683+ renodx::color ::macleod_boynton::UnweighLMS (
684+ lms_weighted_relative_out * max (current_adaptive_state_lms, 1e-6f )));
685+ }
686+
526687float3 GamutCompressLMS (float3 lms_input, float strength = 1.f ) {
527688 float3 lms_weighted_input = renodx::color ::macleod_boynton::WeighLMS (lms_input);
528689 float3 lms_weighted_clamped = max (lms_weighted_input, 0 );
0 commit comments