diff --git a/src/games/dmc5/ConvertRec2020PS_0x6AB2B106.ps_5_0.hlsl b/src/games/dmc5/ConvertRec2020PS_0x6AB2B106.ps_5_0.hlsl new file mode 100644 index 00000000..4fd353d4 --- /dev/null +++ b/src/games/dmc5/ConvertRec2020PS_0x6AB2B106.ps_5_0.hlsl @@ -0,0 +1,110 @@ +#include "./DICE.hlsl" +#include "./shared.h" + +cbuffer HDRMapping : register(b0) { + float whitePaperNits : packoffset(c0); + float configImageAlphaScale : packoffset(c0.y); + float displayMaxNits : packoffset(c0.z); + float displayMinNits : packoffset(c0.w); + float4 displayMaxNitsRect : packoffset(c1); + float4 standardMaxNitsRect : packoffset(c2); + float4 mdrOutRangeRect : packoffset(c3); + uint drawMode : packoffset(c4); + float gammaForHDR : packoffset(c4.y); + float2 configDrawRectSize : packoffset(c4.z); +} + +SamplerState PointBorder_s : register(s0); +Texture2D tLinearImage : register(t0); + +// 3Dmigoto declarations +#define cmp - + +float4 main(float4 v0: SV_Position0, float2 v1: TEXCOORD0) + : SV_Target { +#if 1 + float3 bt709Color = + tLinearImage.SampleLevel(PointBorder_s, v1.xy, 0.0f).rgb; +#if 1 + bt709Color = renodx::color::correct::GammaSafe(bt709Color); +#endif + +#if 2 + DICESettings config = DefaultDICESettings(); + config.Type = 3; + config.ShoulderStart = 0.5f; + config.DesaturationAmount = 0.f; + config.DarkeningAmount = 0.f; + const float dicePaperWhite = + whitePaperNits / renodx::color::srgb::REFERENCE_WHITE; + const float dicePeakWhite = max(displayMaxNits, whitePaperNits) / renodx::color::srgb::REFERENCE_WHITE; + bt709Color.rgb = + DICETonemap(bt709Color.rgb * dicePaperWhite, dicePeakWhite, config) / dicePaperWhite; +#endif + + float3 bt2020Color = renodx::color::bt2020::from::BT709(bt709Color.rgb); + + float3 pqColor = renodx::color::pq::Encode(bt2020Color, whitePaperNits); + + return float4(pqColor, 1.0); + +#else + + float4 r0, r1, r2, r3, r4, o0; + + r0.xyz = tLinearImage.SampleLevel(PointBorder_s, v1.xy, 0).xyz; + r0.w = dot(float3(0.627403975, 0.329281986, 0.0433136001), r0.xyz); + r1.x = dot(float3(0.0690969974, 0.919539988, 0.0113612004), r0.xyz); + r0.x = dot(float3(0.0163915996, 0.088013202, 0.895595014), r0.xyz); + r2.x = log2(r0.w); + r2.y = log2(r1.x); + r2.z = log2(r0.x); + r0.xyz = gammaForHDR * r2.xyz; + r0.xyz = exp2(r0.xyz); + r0.w = 2.0999999 * whitePaperNits; + r0.w = 10000 / r0.w; + r0.xyz = saturate(r0.xyz / r0.www); + r0.xyz = log2(r0.xyz); + r0.xyz = float3(0.171569824, 0.171569824, 0.171569824) * r0.xyz; + r0.xyz = exp2(r0.xyz); + r1.xyz = r0.xyz * float3(16.71875, 16.71875, 16.71875) + float3(0.84375, 0.84375, 0.84375); + r0.xyz = r0.xyz * float3(16.5625, 16.5625, 16.5625) + float3(1, 1, 1); + r0.xyz = r1.xyz / r0.xyz; + r0.xyz = log2(r0.xyz); + r0.xyz = float3(82.53125, 82.53125, 82.53125) * r0.xyz; + r0.xyz = exp2(r0.xyz); + r0.xyz = min(float3(1, 1, 1), r0.xyz); + r0.w = drawMode & 2; + if (r0.w != 0) { + r1.xyzw = saturate(float4(9.99999975e-005, 9.99999975e-005, 9.99999975e-005, + 9.99999975e-005) + * displayMaxNits); + r1.xyzw = log2(r1.xyzw); + r1.xyzw = + float4(0.159301758, 0.159301758, 0.159301758, 0.159301758) * r1.xyzw; + r1.xyzw = exp2(r1.xyzw); + r1.xyzw = r1.xyzw * float4(18.8515625, 18.6875, 18.8515625, 18.6875) + float4(0.8359375, 1, 0.8359375, 1); + r1.xy = r1.xz / r1.yw; + r1.xy = log2(r1.xy); + r1.xy = float2(78.84375, 78.84375) * r1.xy; + r1.xy = exp2(r1.xy); + r1.xy = min(float2(1, 1), r1.xy); + r1.y = r1.x + -r1.y; + r2.xyz = r0.xyz / r1.xxx; + r2.xyz = min(float3(1, 1, 1), r2.xyz); + r3.xyz = r2.xyz * r1.yyy; + r4.xyz = float3(1, 1, 1) + -r2.xyz; + r1.xzw = r2.xyz * r1.xxx; + r1.xyz = r1.yyy * r4.xyz + r1.xzw; + r1.xyz = r1.xyz * r2.xyz; + r1.xyz = r3.xyz * r4.xyz + r1.xyz; + r1.xyz = min(r1.xyz, r0.xyz); + } + if (r0.w == 0) { + r1.xyz = r0.xyz; + } + o0.xyz = r1.xyz; + o0.w = 1; + return o0; +#endif +} diff --git a/src/games/dmc5/DICE.hlsl b/src/games/dmc5/DICE.hlsl new file mode 100644 index 00000000..b46d3930 --- /dev/null +++ b/src/games/dmc5/DICE.hlsl @@ -0,0 +1,251 @@ +#include "./shared.h" + +static const float HDR10_MaxWhiteNits = 10000.0f; + +float max3(float a, float b, float c) { + return max(a, max(b, c)); +} + +float max3(float3 v) { + return max3(v.x, v.y, v.z); +} + +static const float PQ_constant_M1 = 0.1593017578125f; +static const float PQ_constant_M2 = 78.84375f; +static const float PQ_constant_C1 = 0.8359375f; +static const float PQ_constant_C2 = 18.8515625f; +static const float PQ_constant_C3 = 18.6875f; + +// PQ (Perceptual Quantizer - ST.2084) encode/decode used for HDR10 BT.2100. +// Clamp type: +// 0 None +// 1 Remove negative numbers +// 2 Remove numbers beyond 0-1 +// 3 Mirror negative numbers +float3 Linear_to_PQ(float3 LinearColor, int clampType = 0) { + float3 LinearColorSign = sign(LinearColor); + if (clampType == 1) { + LinearColor = max(LinearColor, 0.f); + } else if (clampType == 2) { + LinearColor = saturate(LinearColor); + } else if (clampType == 3) { + LinearColor = abs(LinearColor); + } + float3 colorPow = pow(LinearColor, PQ_constant_M1); + float3 numerator = PQ_constant_C1 + PQ_constant_C2 * colorPow; + float3 denominator = 1.f + PQ_constant_C3 * colorPow; + float3 pq = pow(numerator / denominator, PQ_constant_M2); + if (clampType == 3) { + return pq * LinearColorSign; + } + return pq; +} + +float3 PQ_to_Linear(float3 ST2084Color, int clampType = 0) { + float3 ST2084ColorSign = sign(ST2084Color); + if (clampType == 1) { + ST2084Color = max(ST2084Color, 0.f); + } else if (clampType == 2) { + ST2084Color = saturate(ST2084Color); + } else if (clampType == 3) { + ST2084Color = abs(ST2084Color); + } + float3 colorPow = pow(ST2084Color, 1.f / PQ_constant_M2); + float3 numerator = max(colorPow - PQ_constant_C1, 0.f); + float3 denominator = PQ_constant_C2 - (PQ_constant_C3 * colorPow); + float3 linearColor = pow(numerator / denominator, 1.f / PQ_constant_M1); + if (clampType == 3) { + return linearColor * ST2084ColorSign; + } + return linearColor; +} + +// Applies exponential ("Photographic") luminance/luma compression. +// The pow can modulate the curve without changing the values around the edges. +// The max is the max possible range to compress from, to not lose any output +// range if the input range was limited. +float rangeCompress(float X, float Max = asfloat(0x7F7FFFFF)) { + // Branches are for static parameters optimizations + if (Max == asfloat(0x7F7FFFFF)) { + // This does e^X. We expect X to be between 0 and 1. + return 1.f - exp(-X); + } + const float lostRange = exp(-Max); + const float restoreRangeScale = 1.f / (1.f - lostRange); + return (1.f - exp(-X)) * restoreRangeScale; +} + +// Refurbished DICE HDR tonemapper (per channel or luminance). +// Expects "InValue" to be >= "ShoulderStart" and "OutMaxValue" to be > +// "ShoulderStart". +float luminanceCompress(float InValue, float OutMaxValue, + float ShoulderStart = 0.f, + bool ConsiderMaxValue = false, + float InMaxValue = asfloat(0x7F7FFFFF)) { + const float compressableValue = InValue - ShoulderStart; + const float compressableRange = InMaxValue - ShoulderStart; + const float compressedRange = OutMaxValue - ShoulderStart; + const float possibleOutValue = + ShoulderStart + compressedRange * rangeCompress(compressableValue / compressedRange, ConsiderMaxValue ? (compressableRange / compressedRange) : asfloat(0x7F7FFFFF)); +#if 1 + return possibleOutValue; +#else // Enable this branch if "InValue" can be smaller than "ShoulderStart" + return (InValue <= ShoulderStart) ? InValue : possibleOutValue; +#endif +} + +#define DICE_TYPE_BY_LUMINANCE_RGB 0 +// Doing the DICE compression in PQ (either on luminance or each color channel) +// produces a curve that is closer to our "perception" and leaves more detail +// highlights without overly compressing them +#define DICE_TYPE_BY_LUMINANCE_PQ 1 +// Modern HDR displays clip individual rgb channels beyond their "white" peak +// brightness, like, if the peak brightness is 700 nits, any r g b color beyond +// a value of 700/80 will be clipped (not acknowledged, it won't make a +// difference). Tonemapping by luminance, is generally more perception accurate +// but can then generate rgb colors "out of range". This setting fixes them up, +// though it's optional as it's working based on assumptions on how current +// displays work, which might not be true anymore in the future. Note that this +// can create some steep (rough, quickly changing) gradients on very bright +// colors. +#define DICE_TYPE_BY_LUMINANCE_PQ_CORRECT_CHANNELS_BEYOND_PEAK_WHITE 2 +// This might look more like classic SDR tonemappers and is closer to how modern +// TVs and Monitors play back colors (usually they clip each individual channel +// to the peak brightness value, though in their native panel color space, or +// current SDR/HDR mode color space). Overall, this seems to handle bright +// gradients more smoothly, even if it shifts hues more (and generally +// desaturating). +#define DICE_TYPE_BY_CHANNEL_PQ 3 + +struct DICESettings { + uint Type; + // Determines where the highlights curve (shoulder) starts. + // Values between 0.25 and 0.5 are good with DICE by PQ (any type). + // With linear/rgb DICE this barely makes a difference, zero is a good default + // but (e.g.) 0.5 would also work. This should always be between 0 and 1. + float ShoulderStart; + + // For "Type == DICE_TYPE_BY_LUMINANCE_PQ_CORRECT_CHANNELS_BEYOND_PEAK_WHITE" + // only: The sum of these needs to be <= 1, both within 0 and 1. The closer + // the sum is to 1, the more each color channel will be containted within its + // peak range. + float DesaturationAmount; + float DarkeningAmount; +}; + +DICESettings DefaultDICESettings() { + DICESettings Settings; + Settings.Type = DICE_TYPE_BY_CHANNEL_PQ; + Settings.ShoulderStart = + (Settings.Type > DICE_TYPE_BY_LUMINANCE_RGB) + ? (1.f / 3.f) + : 0.f; // TODOFT3: increase value!!! (did I already?) + Settings.DesaturationAmount = 1.0 / 3.0; + Settings.DarkeningAmount = 1.0 / 3.0; + return Settings; +} + +// Tonemapper inspired from DICE. Can work by luminance to maintain hue. +// Takes scRGB colors with a white level (the value of 1 1 1) of 80 nits (sRGB) +// (to not be confused with paper white). Paper white is expected to have +// already been multiplied in. +float3 DICETonemap(float3 Color, float PeakWhite, + const DICESettings Settings /*= DefaultDICESettings()*/) { + const float sourceLuminance = renodx::color::y::from::BT709(Color); + + if (Settings.Type != DICE_TYPE_BY_LUMINANCE_RGB) { + static const float HDR10_MaxWhite = + HDR10_MaxWhiteNits / renodx::color::srgb::REFERENCE_WHITE; + + // We could first convert the peak white to PQ and then apply the "shoulder + // start" alpha to it (in PQ), but tests showed scaling it in linear + // actually produces a better curve and more consistently follows the peak + // across different values + const float shoulderStartPQ = + Linear_to_PQ((Settings.ShoulderStart * PeakWhite) / HDR10_MaxWhite).x; + if (Settings.Type == DICE_TYPE_BY_LUMINANCE_PQ || Settings.Type == DICE_TYPE_BY_LUMINANCE_PQ_CORRECT_CHANNELS_BEYOND_PEAK_WHITE) { + const float sourceLuminanceNormalized = sourceLuminance / HDR10_MaxWhite; + const float sourceLuminancePQ = + Linear_to_PQ(sourceLuminanceNormalized, 1).x; + + if (sourceLuminancePQ > shoulderStartPQ) // Luminance below the shoulder (or below zero) don't + // need to be adjusted + { + const float peakWhitePQ = Linear_to_PQ(PeakWhite / HDR10_MaxWhite).x; + + const float compressedLuminancePQ = + luminanceCompress(sourceLuminancePQ, peakWhitePQ, shoulderStartPQ); + const float compressedLuminanceNormalized = + PQ_to_Linear(compressedLuminancePQ).x; + Color *= compressedLuminanceNormalized / sourceLuminanceNormalized; + + if (Settings.Type == DICE_TYPE_BY_LUMINANCE_PQ_CORRECT_CHANNELS_BEYOND_PEAK_WHITE) { + float3 Color_BT2020 = renodx::color::bt2020::from::BT709(Color); + if (any(Color_BT2020 > PeakWhite)) // Optional "optimization" branch + { + float colorLuminance = renodx::color::y::from::BT2020(Color_BT2020); + float colorLuminanceInExcess = colorLuminance - PeakWhite; + float maxColorInExcess = + max3(Color_BT2020) - PeakWhite; // This is guaranteed to be >= + // "colorLuminanceInExcess" + float brightnessReduction = saturate(renodx::math::SafeDivision( + PeakWhite, max3(Color_BT2020), + 1)); // Fall back to one in case of division by zero + float desaturateAlpha = saturate(renodx::math::SafeDivision( + maxColorInExcess, maxColorInExcess - colorLuminanceInExcess, + 0)); // Fall back to zero in case of division by zero + Color_BT2020 = lerp(Color_BT2020, colorLuminance, + desaturateAlpha * Settings.DesaturationAmount); + Color_BT2020 = + lerp(Color_BT2020, Color_BT2020 * brightnessReduction, + Settings.DarkeningAmount); // Also reduce the brightness to + // partially maintain the hue, + // at the cost of brightness + Color = renodx::color::bt709::from::BT2020(Color_BT2020); + } + } + } + } else // DICE_TYPE_BY_CHANNEL_PQ + { + const float peakWhitePQ = Linear_to_PQ(PeakWhite / HDR10_MaxWhite).x; + + // Tonemap in BT.2020 to more closely match the primaries of modern + // displays + const float3 sourceColorNormalized = + renodx::color::bt2020::from::BT709(Color) / HDR10_MaxWhite; + const float3 sourceColorPQ = Linear_to_PQ(sourceColorNormalized, 1); + + [unroll] + for (uint i = 0; i < 3; + i++) // TODO LUMA: optimize? will the shader compile already convert + // this to float3? Or should we already make a version with no + // branches that works in float3? + { + if (sourceColorPQ[i] > shoulderStartPQ) // Colors below the shoulder (or below zero) don't + // need to be adjusted + { + const float compressedColorPQ = + luminanceCompress(sourceColorPQ[i], peakWhitePQ, shoulderStartPQ); + const float compressedColorNormalized = + PQ_to_Linear(compressedColorPQ).x; + Color[i] = renodx::color::bt709::from::BT2020( + Color[i] * (compressedColorNormalized / sourceColorNormalized[i])) + .x; + } + } + } + } else // DICE_TYPE_BY_LUMINANCE_RGB + { + const float shoulderStart = + PeakWhite * Settings.ShoulderStart; // From alpha to linear range + if (sourceLuminance > shoulderStart) // Luminances below the shoulder (or below zero) don't + // need to be adjusted + { + const float compressedLuminance = + luminanceCompress(sourceLuminance, PeakWhite, shoulderStart); + Color *= compressedLuminance / sourceLuminance; + } + } + + return Color; +} diff --git a/src/games/dmc5/LUTBlackCorrection.hlsl b/src/games/dmc5/LUTBlackCorrection.hlsl new file mode 100644 index 00000000..d41c64f2 --- /dev/null +++ b/src/games/dmc5/LUTBlackCorrection.hlsl @@ -0,0 +1,86 @@ +#include "./shared.h" + +/// Adjusts gamma based on luminance using the guidelines from ITU BT.2408. +/// At `gammaAdjustmentFactor` = 1.15, it works well to preserve the appearance of +/// shadows and midtones at 100 cd/m2 while scaling the SDR nominal peak white to 203 cd/m2. +/// See: https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2408-7-2023-PDF-E.pdf Section 5.1.3.2 +/// @param linearColor The color to adjust. +/// @param gammaAdjustmentFactor Factor to adjust the gamma. +/// @return The color with adjusted gamma. +float3 AdjustGammaOnLuminance(float3 linearColor, float gammaAdjustmentFactor) { + // Calculate the original luminance + float originalLuminance = renodx::color::y::from::BT709(abs(linearColor)); + + // Adjust luminance only if it is less than or equal to 1 + float adjustedLuminance = originalLuminance > 1.0 ? originalLuminance : renodx::color::gamma::Encode(originalLuminance, 1 / gammaAdjustmentFactor); + + // Recombine the colors with the adjusted luminance + if (originalLuminance == 0) return float3(0, 0, 0); // Prevent division by zero + return linearColor * (adjustedLuminance / originalLuminance); +} + +/// Applies a modified `renodx::lut::Sample` that accounts for only black level correction, +/// leaving peak white untouched as LUTs are already HDR, ensuring no highlight impact. +/// @param color_input Input color to apply the LUT to. +/// @param lut_texture The LUT texture. +/// @param lut_config Configuration for LUT sampling. +/// @return Color output after applying LUT correction. +float3 LUTBlackCorrection(float3 color_input, Texture3D lut_texture, renodx::lut::Config lut_config) { + float3 lutInputColor = renodx::lut::ConvertInput(color_input, lut_config); + float3 lutOutputColor = renodx::lut::SampleColor(lutInputColor, lut_config, lut_texture); + float3 color_output = renodx::lut::LinearOutput(lutOutputColor, lut_config); + + float3 original_output = color_output; + + if (lut_config.scaling != 0) { + float3 lutBlack = renodx::lut::SampleColor(renodx::lut::ConvertInput(0, lut_config), lut_config, lut_texture); + float3 lutMid = renodx::lut::SampleColor(renodx::lut::ConvertInput(0.18f, lut_config), lut_config, lut_texture); + float3 unclamped = renodx::lut::Unclamp( + renodx::lut::GammaOutput(lutOutputColor, lut_config), + renodx::lut::GammaOutput(lutBlack, lut_config), + renodx::lut::GammaOutput(lutMid, lut_config), + 1.f, // set peak to 1 so it doesn't touch highlights + renodx::lut::GammaInput(color_input, lutInputColor, lut_config)); + float3 recolored = renodx::lut::RecolorUnclamped(color_output, renodx::lut::LinearUnclampedOutput(unclamped, lut_config)); + color_output = lerp(color_output, recolored, lut_config.scaling); +#if 0 // fixes crushed blacks with 2.2 gamma correction + color_output = lerp(color_output, original_output, saturate(pow(color_output, lutMid))); +#endif + } + color_output = renodx::lut::RestoreSaturationLoss(color_input, color_output, lut_config); + if (lut_config.strength != 1.f) { + color_output = lerp(color_input, color_output, lut_config.strength); + } + return color_output; +} + +/// Applies a customized version of RenoDRT tonemapper that tonemaps down to 1.0. +/// This function is used to compress HDR color to SDR range for use alongside `UpgradeToneMap`. +/// +/// @param lutInputColor The color input that needs to be tonemapped. +/// @return The tonemapped color compressed to the SDR range, ensuring that it can be applied to SDR color grading with `UpgradeToneMap`. +float3 renoDRTSmoothClamp(float3 untonemapped) { + renodx::tonemap::renodrt::Config renodrt_config = renodx::tonemap::renodrt::config::Create(); + renodrt_config.nits_peak = 100.f; + renodrt_config.mid_gray_value = 0.18f; + renodrt_config.mid_gray_nits = 18.f; + renodrt_config.exposure = 1.f; + renodrt_config.highlights = 1.f; + renodrt_config.shadows = 1.f; + renodrt_config.contrast = 1.05f; + renodrt_config.saturation = 1.03f; + renodrt_config.dechroma = 0.f; + renodrt_config.flare = 0.f; + renodrt_config.hue_correction_strength = 0.f; + // renodrt_config.hue_correction_source = renodx::tonemap::uncharted2::BT709(untonemapped); + renodrt_config.hue_correction_method = renodx::tonemap::renodrt::config::hue_correction_method::OKLAB; + renodrt_config.tone_map_method = renodx::tonemap::renodrt::config::tone_map_method::DANIELE; + renodrt_config.hue_correction_type = renodx::tonemap::renodrt::config::hue_correction_type::INPUT; + renodrt_config.working_color_space = 2u; + renodrt_config.per_channel = false; + + float3 renoDRTColor = renodx::tonemap::renodrt::BT709(untonemapped, renodrt_config); + renoDRTColor = lerp(untonemapped, renoDRTColor, saturate(renodx::color::y::from::BT709(untonemapped) / renodrt_config.mid_gray_value)); + + return renoDRTColor; +} diff --git a/src/games/dmc5/addon.cpp b/src/games/dmc5/addon.cpp new file mode 100644 index 00000000..f7a83406 --- /dev/null +++ b/src/games/dmc5/addon.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 Musa Haji + * Copyright (C) 2024 Carlos Lopez + * SPDX-License-Identifier: MIT + */ +#define ImTextureID ImU64 + +#define DEBUG_LEVEL_0 + +// #include // Tonemap + Postfx + +// #include // BT.2020 + PQ Encoding +// #include // HDR Calibration Menu + BT.2020 + PQ Encoding + +#include + +#include +#include "../../mods/shader.hpp" + +namespace { + +renodx::mods::shader::CustomShaders custom_shaders = { + CustomShaderEntry(0xA59B718D), // Tonemap + Postfx + + CustomShaderEntry(0x6AB2B106), // BT.2020 + PQ Encoding + // CustomShaderEntry(), // HDR Calibration Menu + BT.2020 + PQ Encoding +}; + +} // namespace + +// NOLINTBEGIN(readability-identifier-naming) + +extern "C" __declspec(dllexport) const char* NAME = "RenoDX"; +extern "C" __declspec(dllexport) const char* DESCRIPTION = "RenoDX for Devil May Cry 5"; + +// NOLINTEND(readability-identifier-naming) + +BOOL APIENTRY DllMain(HMODULE h_module, DWORD fdw_reason, LPVOID lpv_reserved) { + switch (fdw_reason) { + case DLL_PROCESS_ATTACH: + if (!reshade::register_addon(h_module)) return FALSE; + break; + case DLL_PROCESS_DETACH: + reshade::unregister_addon(h_module); + break; + } + + renodx::mods::shader::Use(fdw_reason, custom_shaders); + + return TRUE; +} \ No newline at end of file diff --git a/src/games/dmc5/shared.h b/src/games/dmc5/shared.h new file mode 100644 index 00000000..bd5a49bd --- /dev/null +++ b/src/games/dmc5/shared.h @@ -0,0 +1,8 @@ +#ifndef SRC_DMCV_SHARED_H_ +#define SRC_DMCV_SHARED_H_ + +#ifndef __cplusplus +#include "../../shaders/renodx.hlsl" +#endif + +#endif // SRC_DMCV_SHARED_H_ \ No newline at end of file diff --git a/src/games/dmc5/tonemap_0xA59B718D.ps_5_0.hlsl b/src/games/dmc5/tonemap_0xA59B718D.ps_5_0.hlsl new file mode 100644 index 00000000..e44aa7e0 --- /dev/null +++ b/src/games/dmc5/tonemap_0xA59B718D.ps_5_0.hlsl @@ -0,0 +1,635 @@ +#include ".\LUTBlackCorrection.hlsl" +#include ".\shared.h" + +// ---- Created with 3Dmigoto v1.3.16 on Thu Dec 05 14:56:05 2024 + +struct RadialBlurComputeResult { + float computeAlpha; // Offset: 0 +}; + +cbuffer SceneInfo : register(b0) { + row_major float4x4 viewProjMat : packoffset(c0); + row_major float3x4 transposeViewMat : packoffset(c4); + row_major float3x4 transposeViewInvMat : packoffset(c7); + float4 projElement[2] : packoffset(c10); + float4 projInvElements[2] : packoffset(c12); + row_major float4x4 viewProjInvMat : packoffset(c14); + row_major float4x4 prevViewProjMat : packoffset(c18); + float3 ZToLinear : packoffset(c22); + float subdivisionLevel : packoffset(c22.w); + float2 screenSize : packoffset(c23); + float2 screenInverseSize : packoffset(c23.z); + float2 cullingHelper : packoffset(c24); + float cameraNearPlane : packoffset(c24.z); + float cameraFarPlane : packoffset(c24.w); + float4 viewFrustum[6] : packoffset(c25); + float4 clipplane : packoffset(c31); +} + +cbuffer Tonemap : register(b1) { + float exposureAdjustment : packoffset(c0); + float tonemapRange : packoffset(c0.y); + float sharpness : packoffset(c0.z); + float preTonemapRange : packoffset(c0.w); + int useAutoExposure : packoffset(c1); + float echoBlend : packoffset(c1.y); + float AABlend : packoffset(c1.z); + float AASubPixel : packoffset(c1.w); + float ResponsiveAARate : packoffset(c2); +} + +cbuffer CameraKerare : register(b2) { + float kerare_scale : packoffset(c0); + float kerare_offset : packoffset(c0.y); +} + +cbuffer LensDistortionParam : register(b3) { + float fDistortionCoef : packoffset(c0); + float fRefraction : packoffset(c0.y); + uint aberrationEnable : packoffset(c0.z); + uint reserved : packoffset(c0.w); +} + +cbuffer RadialBlurRenderParam : register(b4) { + float4 cbRadialColor : packoffset(c0); + float2 cbRadialScreenPos : packoffset(c1); + float2 cbRadialMaskSmoothstep : packoffset(c1.z); + float2 cbRadialMaskRate : packoffset(c2); + float cbRadialBlurPower : packoffset(c2.z); + float cbRadialSharpRange : packoffset(c2.w); + uint cbRadialBlurFlags : packoffset(c3); + float cbRadialReserve0 : packoffset(c3.y); + float cbRadialReserve1 : packoffset(c3.z); + float cbRadialReserve2 : packoffset(c3.w); +} + +cbuffer FilmGrainParam : register(b5) { + float2 fNoisePower : packoffset(c0); + float2 fNoiseUVOffset : packoffset(c0.z); + float fNoiseDensity : packoffset(c1); + float fNoiseContrast : packoffset(c1.y); + float fBlendRate : packoffset(c1.z); + float fReverseNoiseSize : packoffset(c1.w); +} + +cbuffer ColorCorrectTexture : register(b6) { + float fTextureSize : packoffset(c0); + float fTextureBlendRate : packoffset(c0.y); + float fTextureBlendRate2 : packoffset(c0.z); + float fTextureInverseSize : packoffset(c0.w); + row_major float4x4 fColorMatrix : packoffset(c1); +} + +cbuffer ColorDeficientTable : register(b7) { + float4 cvdR : packoffset(c0); + float4 cvdG : packoffset(c1); + float4 cvdB : packoffset(c2); +} + +cbuffer ImagePlaneParam : register(b8) { + float4 ColorParam : packoffset(c0); + float Levels_Rate : packoffset(c1); + float Levels_Range : packoffset(c1.y); + uint Blend_Type : packoffset(c1.z); +} + +cbuffer CBControl : register(b9) { + uint cPassEnabled : packoffset(c0); +} + +SamplerState BilinearClamp_s : register(s0); +SamplerState TrilinearClamp_s : register(s1); +Texture2D SourceImage : register(t0); +StructuredBuffer ComputeResultSRV : register(t1); +Texture3D tTextureMap0 : register(t2); +Texture3D tTextureMap1 : register(t3); +Texture3D tTextureMap2 : register(t4); +Texture2D ImagePlameBase : register(t5); +Texture2D ImagePlameAlpha : register(t6); + +// 3Dmigoto declarations +#define cmp - + +void main( + float4 v0: SV_Position0, + float4 v1: Kerare0, + float v2: Exposure0, + out float4 o0: SV_Target0) { + float4 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; + + // declare lut config for use with lut black correction + renodx::lut::Config lut_config = renodx::lut::config::Create( + TrilinearClamp_s, + 1.f, // strength + 1.f, // scaling + renodx::lut::config::type::SRGB, + renodx::lut::config::type::LINEAR, + fTextureSize); + float3 sdrColor; + float3 untonemapped; + float3 hdrColor; + + r0.xyzw = cPassEnabled & int4(1, 32, 2, 4); + if (r0.x != 0) { + r1.xy = v0.xy * screenInverseSize.xy + float2(-0.5, -0.5); + r1.z = fDistortionCoef * 0.5 + 1; + r1.z = max(1, r1.z); + r1.z = rcp(r1.z); + r1.w = dot(r1.xy, r1.xy); + r2.x = fDistortionCoef * r1.w + 1; + r2.xy = r2.xx * r1.xy; + r2.xy = r2.xy * r1.zz + float2(0.5, 0.5); + if (aberrationEnable == 0) { + r3.xyz = SourceImage.Sample(BilinearClamp_s, r2.xy).xyz; + r3.xyz = v2.xxx * r3.xyz; + r2.z = max(r3.x, r3.y); + r2.z = max(r2.z, r3.z); + r2.w = (int)r2.z & 0x7f800000; + // r2.w = cmp((int)r2.w == 0x7f800000); + r2.w = cmp((uint)r2.w == 0x7f800000); + if (r2.w != 0) { + r4.xyz = float3(1, 1, 1); + } + if (r2.w == 0) { + r2.z = r2.z * tonemapRange + 1; + r4.xyz = r3.xyz / r2.zzz; + } + } else { + r1.w = fRefraction + r1.w; + r2.z = fDistortionCoef * r1.w + 1; + r2.zw = r2.zz * r1.xy; + r2.zw = r2.zw * r1.zz + float2(0.5, 0.5); + r1.w = fRefraction + r1.w; + r1.w = fDistortionCoef * r1.w + 1; + r1.xy = r1.xy * r1.ww; + r1.xy = r1.xy * r1.zz + float2(0.5, 0.5); + r3.xyz = SourceImage.Sample(BilinearClamp_s, r2.xy).xyz; + r3.xyz = v2.xxx * r3.xyz; + r1.w = max(r3.x, r3.y); + r1.w = max(r1.w, r3.z); + r2.x = (int)r1.w & 0x7f800000; + // r2.x = cmp((int)r2.x == 0x7f800000); + r2.x = cmp((uint)r2.x == 0x7f800000); + if (r2.x != 0) { + r4.x = 1; + } + if (r2.x == 0) { + r1.w = r1.w * tonemapRange + 1; + r4.x = r3.x / r1.w; + } + r2.xyz = SourceImage.Sample(BilinearClamp_s, r2.zw).xyz; + r2.xyz = v2.xxx * r2.xyz; + r1.w = max(r2.x, r2.y); + r1.w = max(r1.w, r2.z); + r2.x = (int)r1.w & 0x7f800000; + // r2.x = cmp((int)r2.x == 0x7f800000); + r2.x = cmp((uint)r2.x == 0x7f800000); + if (r2.x != 0) { + r4.y = 1; + } + if (r2.x == 0) { + r1.w = r1.w * tonemapRange + 1; + r4.y = r2.y / r1.w; + } + r1.xyw = SourceImage.Sample(BilinearClamp_s, r1.xy).xyz; + r1.xyw = v2.xxx * r1.xyw; + r1.x = max(r1.x, r1.y); + r1.x = max(r1.x, r1.w); + r1.y = (int)r1.x & 0x7f800000; + // r1.y = cmp((int)r1.y == 0x7f800000); + r1.y = cmp((uint)r1.y == 0x7f800000); + if (r1.y != 0) { + r4.z = 1; + } + if (r1.y == 0) { + r1.x = r1.x * tonemapRange + 1; + r4.z = r1.w / r1.x; + } + } + r1.x = fDistortionCoef; + } else { + r2.xy = (uint2)v0.xy; + r2.zw = float2(0, 0); + r2.xyz = SourceImage.Load(r2.xyz).xyz; + r2.xyz = v2.xxx * r2.xyz; + r1.y = max(r2.x, r2.y); + r1.y = max(r1.y, r2.z); + r1.w = (int)r1.y & 0x7f800000; + // r1.w = cmp((int)r1.w == 0x7f800000); + r1.w = cmp((uint)r1.w == 0x7f800000); + if (r1.w != 0) { + r4.xyz = float3(1, 1, 1); + } + if (r1.w == 0) { + r1.y = r1.y * tonemapRange + 1; + r4.xyz = r2.xyz / r1.yyy; + } + r1.xz = float2(0, 1); + } + if (r0.y != 0) { + r0.y = asint(cbRadialBlurFlags) & 2; + r1.yw = r0.yy ? float2(1, 0) : float2(0, 1); + r0.y = ComputeResultSRV[0].computeAlpha; + r0.y = r0.y * r1.y + r1.w; + r0.y = cbRadialColor.w * r0.y; + r1.y = cmp(r0.y == 0.000000); + if (r1.y != 0) { + r2.xyz = r4.xyz; + } + if (r1.y == 0) { + r0.x = r0.x ? 1 : 0; + r1.yw = screenInverseSize.xy * v0.xy; + r3.xy = v0.xy * screenInverseSize.xy + float2(-0.5, -0.5); + r3.xy = -cbRadialScreenPos.xy + r3.xy; + r3.zw = cmp(r3.xy < float2(0, 0)); + r5.xy = -v0.xy * screenInverseSize.xy + float2(1, 1); + r1.yw = r3.zw ? r5.xy : r1.yw; + r2.w = asint(cbRadialBlurFlags) & 1; + r3.z = dot(r3.xy, r3.xy); + r3.w = rsqrt(r3.z); + r5.xy = r3.xy * r3.ww; + r5.xy = cbRadialSharpRange * r5.xy; + // r5.xy = (uint3)abs(r5.xy); + r5.xy = abs(r5.xy); + r3.w = (int)r5.y + (int)r5.x; + r4.w = (int)r3.w ^ 61; + r3.w = (uint)r3.w >> 16; + r3.w = (int)r3.w ^ (int)r4.w; + r3.w = (int)r3.w * 9; + r4.w = (uint)r3.w >> 4; + r3.w = (int)r3.w ^ (int)r4.w; + r3.w = (int)r3.w * 0x27d4eb2d; + r4.w = (uint)r3.w >> 15; + r3.w = (int)r3.w ^ (int)r4.w; + r3.w = (uint)r3.w; + r3.w = 2.32830644e-010 * r3.w; + r2.w = r2.w ? r3.w : 1; + if (r0.x != 0) { + r0.x = sqrt(r3.z); + r0.x = max(1, r0.x); + r0.x = 1 / r0.x; + r5.xy = -cbRadialBlurPower * r1.yw; + r5.xy = r5.xy * r0.xx; + r5.xy = r5.xy * r2.ww; + r6.xyzw = r5.xyxy * float4(0.00111111114, 0.00111111114, 0.00999999978, 0.00999999978) + float4(1, 1, 1, 1); + r6.xyzw = r3.xyxy * r6.xyzw + cbRadialScreenPos.xyxy; + r0.x = dot(r6.xy, r6.xy); + r0.x = r1.x * r0.x + 1; + r5.zw = r6.xy * r0.xx; + r5.zw = r5.zw * r1.zz + float2(0.5, 0.5); + r7.xyz = SourceImage.SampleLevel(BilinearClamp_s, r5.zw, 0).xyz; + r8.xyzw = r5.xyxy * float4(0.00222222228, 0.00222222228, 0.00333333341, 0.00333333341) + float4(1, 1, 1, 1); + r8.xyzw = r3.xyxy * r8.xyzw + cbRadialScreenPos.xyxy; + r0.x = dot(r8.xy, r8.xy); + r0.x = r1.x * r0.x + 1; + r5.zw = r8.xy * r0.xx; + r5.zw = r5.zw * r1.zz + float2(0.5, 0.5); + r9.xyz = SourceImage.SampleLevel(BilinearClamp_s, r5.zw, 0).xyz; + r9.xyz = float3(0.100000001, 0.100000001, 0.100000001) * r9.xyz; + r7.xyz = r7.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r9.xyz; + r0.x = dot(r8.zw, r8.zw); + r0.x = r1.x * r0.x + 1; + r5.zw = r8.zw * r0.xx; + r5.zw = r5.zw * r1.zz + float2(0.5, 0.5); + r8.xyz = SourceImage.SampleLevel(BilinearClamp_s, r5.zw, 0).xyz; + r7.xyz = r8.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r8.xyzw = r5.xyxy * float4(0.00444444455, 0.00444444455, 0.00555555569, 0.00555555569) + float4(1, 1, 1, 1); + r8.xyzw = r3.xyxy * r8.xyzw + cbRadialScreenPos.xyxy; + r0.x = dot(r8.xy, r8.xy); + r0.x = r1.x * r0.x + 1; + r5.zw = r8.xy * r0.xx; + r5.zw = r5.zw * r1.zz + float2(0.5, 0.5); + r9.xyz = SourceImage.SampleLevel(BilinearClamp_s, r5.zw, 0).xyz; + r7.xyz = r9.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r0.x = dot(r8.zw, r8.zw); + r0.x = r1.x * r0.x + 1; + r5.zw = r8.zw * r0.xx; + r5.zw = r5.zw * r1.zz + float2(0.5, 0.5); + r8.xyz = SourceImage.SampleLevel(BilinearClamp_s, r5.zw, 0).xyz; + r7.xyz = r8.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r8.xyzw = r5.xyxy * float4(0.00666666683, 0.00666666683, 0.00777777797, 0.00777777797) + float4(1, 1, 1, 1); + r8.xyzw = r3.xyxy * r8.xyzw + cbRadialScreenPos.xyxy; + r0.x = dot(r8.xy, r8.xy); + r0.x = r1.x * r0.x + 1; + r5.zw = r8.xy * r0.xx; + r5.zw = r5.zw * r1.zz + float2(0.5, 0.5); + r9.xyz = SourceImage.SampleLevel(BilinearClamp_s, r5.zw, 0).xyz; + r7.xyz = r9.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r0.x = dot(r8.zw, r8.zw); + r0.x = r1.x * r0.x + 1; + r5.zw = r8.zw * r0.xx; + r5.zw = r5.zw * r1.zz + float2(0.5, 0.5); + r8.xyz = SourceImage.SampleLevel(BilinearClamp_s, r5.zw, 0).xyz; + r7.xyz = r8.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r5.xy = r5.xy * float2(0.0088888891, 0.0088888891) + float2(1, 1); + r5.xy = r3.xy * r5.xy + cbRadialScreenPos.xy; + r0.x = dot(r5.xy, r5.xy); + r0.x = r1.x * r0.x + 1; + r5.xy = r5.xy * r0.xx; + r5.xy = r5.xy * r1.zz + float2(0.5, 0.5); + r5.xyz = SourceImage.SampleLevel(BilinearClamp_s, r5.xy, 0).xyz; + r5.xyz = r5.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r0.x = dot(r6.zw, r6.zw); + r0.x = r1.x * r0.x + 1; + r6.xy = r6.zw * r0.xx; + r1.xz = r6.xy * r1.zz + float2(0.5, 0.5); + r6.xyz = SourceImage.SampleLevel(BilinearClamp_s, r1.xz, 0).xyz; + r5.xyz = r6.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r5.xyz; + r5.xyz = cbRadialColor.xyz * r5.xyz; + r5.xyz = v2.xxx * r5.xyz; + r0.x = max(r5.x, r5.y); + r0.x = max(r0.x, r5.z); + r1.x = (int)r0.x & 0x7f800000; + r1.x = cmp((int)r1.x == 0x7f800000); + if (r1.x != 0) { + r6.xyz = float3(1, 1, 1); + } + if (r1.x == 0) { + r0.x = r0.x * tonemapRange + 1; + r6.xyz = r5.xyz / r0.xxx; + } + r5.xyz = cbRadialColor.xyz * r4.xyz; + r5.xyz = r5.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r6.xyz; + } else { + r0.x = sqrt(r3.z); + r0.x = max(1, r0.x); + r0.x = 1 / r0.x; + r1.xy = -cbRadialBlurPower * r1.yw; + r1.xy = r1.xy * r0.xx; + r1.xy = r1.xy * r2.ww; + r6.xyzw = r1.xyxy * float4(0.00111111114, 0.00111111114, 0.00999999978, 0.00999999978) + float4(1, 1, 1, 1); + r6.xyzw = r3.xyxy * r6.xyzw + cbRadialScreenPos.xyxy; + r6.xyzw = float4(0.5, 0.5, 0.5, 0.5) + r6.xyzw; + r7.xyz = SourceImage.SampleLevel(BilinearClamp_s, r6.xy, 0).xyz; + r8.xyzw = r1.xyxy * float4(0.00222222228, 0.00222222228, 0.00333333341, 0.00333333341) + float4(1, 1, 1, 1); + r8.xyzw = r3.xyxy * r8.xyzw + cbRadialScreenPos.xyxy; + r8.xyzw = float4(0.5, 0.5, 0.5, 0.5) + r8.xyzw; + r9.xyz = SourceImage.SampleLevel(BilinearClamp_s, r8.xy, 0).xyz; + r9.xyz = float3(0.100000001, 0.100000001, 0.100000001) * r9.xyz; + r7.xyz = r7.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r9.xyz; + r8.xyz = SourceImage.SampleLevel(BilinearClamp_s, r8.zw, 0).xyz; + r7.xyz = r8.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r8.xyzw = r1.xyxy * float4(0.00444444455, 0.00444444455, 0.00555555569, 0.00555555569) + float4(1, 1, 1, 1); + r8.xyzw = r3.xyxy * r8.xyzw + cbRadialScreenPos.xyxy; + r8.xyzw = float4(0.5, 0.5, 0.5, 0.5) + r8.xyzw; + r9.xyz = SourceImage.SampleLevel(BilinearClamp_s, r8.xy, 0).xyz; + r7.xyz = r9.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r8.xyz = SourceImage.SampleLevel(BilinearClamp_s, r8.zw, 0).xyz; + r7.xyz = r8.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r8.xyzw = r1.xyxy * float4(0.00666666683, 0.00666666683, 0.00777777797, 0.00777777797) + float4(1, 1, 1, 1); + r8.xyzw = r3.xyxy * r8.xyzw + cbRadialScreenPos.xyxy; + r8.xyzw = float4(0.5, 0.5, 0.5, 0.5) + r8.xyzw; + r9.xyz = SourceImage.SampleLevel(BilinearClamp_s, r8.xy, 0).xyz; + r7.xyz = r9.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r8.xyz = SourceImage.SampleLevel(BilinearClamp_s, r8.zw, 0).xyz; + r7.xyz = r8.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r1.xy = r1.xy * float2(0.0088888891, 0.0088888891) + float2(1, 1); + r1.xy = r3.xy * r1.xy + cbRadialScreenPos.xy; + r1.xy = float2(0.5, 0.5) + r1.xy; + r1.xyz = SourceImage.SampleLevel(BilinearClamp_s, r1.xy, 0).xyz; + r1.xyz = r1.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r7.xyz; + r3.xyw = SourceImage.SampleLevel(BilinearClamp_s, r6.zw, 0).xyz; + r1.xyz = r3.xyw * float3(0.100000001, 0.100000001, 0.100000001) + r1.xyz; + r1.xyz = cbRadialColor.xyz * r1.xyz; + r1.xyz = v2.xxx * r1.xyz; + r0.x = max(r1.x, r1.y); + r0.x = max(r0.x, r1.z); + r1.w = (int)r0.x & 0x7f800000; + r1.w = cmp((int)r1.w == 0x7f800000); + if (r1.w != 0) { + r3.xyw = float3(1, 1, 1); + } + if (r1.w == 0) { + r0.x = r0.x * tonemapRange + 1; + r3.xyw = r1.xyz / r0.xxx; + } + r1.xyz = cbRadialColor.xyz * r4.xyz; + r5.xyz = r1.xyz * float3(0.100000001, 0.100000001, 0.100000001) + r3.xyw; + } + r0.x = cmp(0 < cbRadialMaskRate.x); + if (r0.x != 0) { + r0.x = sqrt(r3.z); + r0.x = saturate(r0.x * cbRadialMaskSmoothstep.x + cbRadialMaskSmoothstep.y); + r1.x = r0.x * r0.x; + r0.x = -r0.x * 2 + 3; + r0.x = r1.x * r0.x; + r0.x = cbRadialMaskRate.x * r0.x + cbRadialMaskRate.y; + r1.xyz = r5.xyz + -r4.xyz; + r5.xyz = r0.xxx * r1.xyz + r4.xyz; + } + r1.xyz = r5.xyz + -r4.xyz; + r4.xyz = r0.yyy * r1.xyz + r4.xyz; + } else { + r4.xyz = r2.xyz; + } + } + r1.xyz = v1.xyz / v1.www; + r0.x = dot(r1.xyz, r1.xyz); + r0.x = rsqrt(r0.x); + r0.x = r1.z * r0.x; + r0.y = saturate(abs(r0.x) * kerare_scale + kerare_offset); + r0.y = 1 + -r0.y; + r0.x = abs(r0.x) * abs(r0.x); + r0.x = r0.x * r0.x; + r0.x = r0.x * r0.y; + r0.x = min(1, r0.x); + r1.xyz = r4.xyz * r0.xxx; + if (r0.z != 0) { + r0.yz = fNoiseUVOffset.xy * screenSize.xy + v0.xy; + r0.yz = fReverseNoiseSize * r0.yz; + r0.yz = floor(r0.yz); + r1.w = dot(r0.yz, float2(0.0671105608, 0.00583714992)); + r1.w = frac(r1.w); + r1.w = 52.9829178 * r1.w; + r1.w = frac(r1.w); + r2.x = cmp(r1.w < fNoiseDensity); + if (r2.x != 0) { + r0.y = r0.y * r0.z; + r0.y = (uint)r0.y; + r0.y = (int)r0.y ^ 0x00bc602f; + r0.y = (int)r0.y * 0x003779b9; + r0.z = (uint)r0.y << 6; + r2.x = (uint)r0.y >> 26; + r0.y = (int)r0.y ^ (int)r0.z; + r0.y = (int)r0.y ^ (int)r2.x; + r0.y = (uint)r0.y; + r0.y = 2.32830644e-010 * r0.y; + } else { + r0.y = 0; + } + r0.z = 757.48468 * r1.w; + r0.z = frac(r0.z); + r1.w = cmp(r0.z < fNoiseDensity); + if (r1.w != 0) { + r1.w = (int)r0.z ^ 0x00bc602f; + r1.w = (int)r1.w * 0x003779b9; + r2.x = (uint)r1.w << 6; + r2.y = (uint)r1.w >> 26; + r1.w = (int)r1.w ^ (int)r2.x; + r1.w = (int)r1.w ^ (int)r2.y; + r1.w = (uint)r1.w; + r1.w = r1.w * 2.32830644e-010 + -0.5; + } else { + r1.w = 0; + } + r0.z = 757.48468 * r0.z; + r0.z = frac(r0.z); + r2.x = cmp(r0.z < fNoiseDensity); + if (r2.x != 0) { + r0.z = (int)r0.z ^ 0x00bc602f; + r0.z = (int)r0.z * 0x003779b9; + r2.x = (uint)r0.z << 6; + r2.y = (uint)r0.z >> 26; + r0.z = (int)r0.z ^ (int)r2.x; + r0.z = (int)r0.z ^ (int)r2.y; + r0.z = (uint)r0.z; + r0.z = r0.z * 2.32830644e-010 + -0.5; + } else { + r0.z = 0; + } + r2.xy = fNoisePower.xy * r0.yz; + r2.z = fNoisePower.y * r1.w; + r3.x = dot(r2.xz, float2(1, 1.40199995)); + r3.y = dot(r2.xyz, float3(1, -0.344000012, -0.713999987)); + r3.z = dot(r2.xy, float2(1, 1.77199996)); + r0.y = saturate(dot(r1.xyz, float3(0.298999995, -0.169, 0.5))); + r0.y = 1 + -r0.y; + r0.y = log2(r0.y); + r0.y = fNoiseContrast * r0.y; + r0.y = exp2(r0.y); + r0.y = fBlendRate * r0.y; + r2.xyz = -r4.xyz * r0.xxx + r3.xyz; + r1.xyz = r0.yyy * r2.xyz + r1.xyz; + } + if (r0.w != 0) { + r0.x = max(r1.x, r1.y); + r0.x = max(r0.x, r1.z); + r0.y = cmp(1 < r0.x); +#if 0 + if (r0.y != 0) { + r1.xyz = r1.xyz / r0.xxx; + } +#else + untonemapped = r1.xyz; + hdrColor = untonemapped; + + sdrColor = renoDRTSmoothClamp(untonemapped); // use neutral RenoDRT as a smoothclamp + r1.xyz = sdrColor; +#endif +#if 0 + r0.z = 0.5 * fTextureInverseSize; + r0.w = cmp(0.00313080009 >= r1.x); + r1.w = 12.9200001 * r1.x; + r2.x = log2(r1.x); + r2.x = 0.416666657 * r2.x; + r2.x = exp2(r2.x); + r2.x = r2.x * 1.05499995 + -0.0549999997; + r2.x = r0.w ? r1.w : r2.x; + r0.w = cmp(0.00313080009 >= r1.y); + r1.w = 12.9200001 * r1.y; + r2.w = log2(r1.y); + r2.w = 0.416666657 * r2.w; + r2.w = exp2(r2.w); + r2.w = r2.w * 1.05499995 + -0.0549999997; + r2.y = r0.w ? r1.w : r2.w; + r0.w = cmp(0.00313080009 >= r1.z); + r1.w = 12.9200001 * r1.z; + r2.w = log2(r1.z); + r2.w = 0.416666657 * r2.w; + r2.w = exp2(r2.w); + r2.w = r2.w * 1.05499995 + -0.0549999997; + r2.z = r0.w ? r1.w : r2.w; + r0.w = 1 + -fTextureInverseSize; + r2.xyz = r2.xyz * r0.www + r0.zzz; + r3.xyz = tTextureMap0.SampleLevel(TrilinearClamp_s, r2.xyz, 0).xyz; +#else + r3.xyz = LUTBlackCorrection(r1.xyz, tTextureMap0, lut_config); +#endif + r0.z = cmp(0 < fTextureBlendRate); + if (r0.z != 0) { +#if 0 + r4.xyz = tTextureMap1.SampleLevel(TrilinearClamp_s, r2.xyz, 0).xyz; +#else + r4.xyz = LUTBlackCorrection(r1.xyz, tTextureMap1, lut_config); +#endif + r4.xyz = r4.xyz + -r3.xyz; + r4.xyz = fTextureBlendRate * r4.xyz + r3.xyz; + r0.z = cmp(0 < fTextureBlendRate2); + if (r0.z != 0) { +#if 0 + r5.xyz = cmp(float3(0.00313080009,0.00313080009,0.00313080009) >= r4.xyz); + r6.xyz = float3(12.9200001,12.9200001,12.9200001) * r4.xyz; + r7.xyz = log2(r4.xyz); + r7.xyz = float3(0.416666657,0.416666657,0.416666657) * r7.xyz; + r7.xyz = exp2(r7.xyz); + r7.xyz = r7.xyz * float3(1.05499995,1.05499995,1.05499995) + float3(-0.0549999997,-0.0549999997,-0.0549999997); + r5.xyz = r5.xyz ? r6.xyz : r7.xyz; + r5.xyz = tTextureMap2.SampleLevel(TrilinearClamp_s, r5.xyz, 0).xyz; +#else + r5.xyz = LUTBlackCorrection(r4.xyz, tTextureMap2, lut_config); +#endif + r5.xyz = r5.xyz + -r4.xyz; + r4.xyz = fTextureBlendRate2 * r5.xyz + r4.xyz; + } + } else { +#if 0 + r5.xyz = cmp(float3(0.00313080009,0.00313080009,0.00313080009) >= r3.xyz); + r6.xyz = float3(12.9200001,12.9200001,12.9200001) * r3.xyz; + r7.xyz = log2(r3.xyz); + r7.xyz = float3(0.416666657,0.416666657,0.416666657) * r7.xyz; + r7.xyz = exp2(r7.xyz); + r7.xyz = r7.xyz * float3(1.05499995,1.05499995,1.05499995) + float3(-0.0549999997,-0.0549999997,-0.0549999997); + r5.xyz = r5.xyz ? r6.xyz : r7.xyz; + r5.xyz = tTextureMap2.SampleLevel(TrilinearClamp_s, r5.xyz, 0).xyz; +#else + r5.xyz = LUTBlackCorrection(r3.xyz, tTextureMap2, lut_config); +#endif + r5.xyz = r5.xyz + -r3.xyz; + r4.xyz = fTextureBlendRate2 * r5.xyz + r3.xyz; + } + r3.xyz = fColorMatrix._m10_m11_m12 * r4.yyy; + r3.xyz = r4.xxx * fColorMatrix._m00_m01_m02 + r3.xyz; + r3.xyz = r4.zzz * fColorMatrix._m20_m21_m22 + r3.xyz; + r1.xyz = fColorMatrix._m30_m31_m32 + r3.xyz; +#if 0 + if (r0.y != 0) { + r0.y = 0.100000001 * r0.x; + r0.y = min(1, r0.y); + r2.xyz = r2.xyz + -r1.xyz; + r0.yzw = r0.yyy * r2.xyz + r1.xyz; + r1.xyz = r0.yzw * r0.xxx; + } +#else + float3 postProcessColor = r1.xyz; + r1.xyz = renodx::tonemap::UpgradeToneMap(hdrColor, sdrColor, postProcessColor, 1.f); +#endif + } + r0.xy = cPassEnabled & int2(8, 16); + if (r0.x != 0) { + r2.x = saturate(dot(r1.xyz, cvdR.xyz)); + r2.y = saturate(dot(r1.xyz, cvdG.xyz)); + r2.z = saturate(dot(r1.xyz, cvdB.xyz)); + r1.xyz = r2.xyz; + } + if (r0.y != 0) { + r0.xy = screenInverseSize.xy * v0.xy; + r2.xyzw = ImagePlameBase.SampleLevel(BilinearClamp_s, r0.xy, 0).xyzw; + r3.xyzw = ColorParam.xyzw * r2.xyzw; + r0.x = ImagePlameAlpha.SampleLevel(BilinearClamp_s, r0.xy, 0).x; + r0.x = saturate(r0.x * Levels_Rate + Levels_Range); + r0.x = r0.x * r3.w; + r0.yzw = cmp(r3.xyz < float3(0.5, 0.5, 0.5)); + r3.xyz = r3.xyz * r1.xyz; + r3.xyz = r3.xyz + r3.xyz; + r2.xyz = -r2.xyz * ColorParam.xyz + float3(1, 1, 1); + r2.xyz = r2.xyz + r2.xyz; + r4.xyz = float3(1, 1, 1) + -r1.xyz; + r2.xyz = -r2.xyz * r4.xyz + float3(1, 1, 1); + r0.yzw = r0.yzw ? r3.xyz : r2.xyz; + r0.yzw = r0.yzw + -r1.xyz; + r1.xyz = r0.xxx * r0.yzw + r1.xyz; + } + o0.xyz = r1.xyz; + o0.w = 0; + return; +}