diff --git a/src/common/colorgrade.hlsl b/src/common/colorgrade.hlsl index 64587378..f6e53811 100644 --- a/src/common/colorgrade.hlsl +++ b/src/common/colorgrade.hlsl @@ -1,3 +1,8 @@ +#ifndef SRC_COMMON_COLORGRADE_HLSL_ +#define SRC_COMMON_COLORGRADE_HLSL_ + +#include "./color.hlsl" + float3 applyContrastSafe(float3 color, float contrast, float midGray = 0.18f, float3x3 colorspace = BT709_2_XYZ_MAT) { float3 workingColor = pow(abs(color) / midGray, contrast) * sign(color) * midGray; float workingLuminance = dot(abs(workingColor), float3(colorspace[1].r, colorspace[1].g, colorspace[1].b)); @@ -44,7 +49,7 @@ float3 apply_user_shadows(float3 rgb, float shadows = 1.f) { // Perf: explicit cube // rgb = shd_con(rgb, -1.8f, pow(2.f - shadows, 3) * 0.04); // 0.04 @ 1 rgb = sign(rgb) * shd_con(abs(rgb), -1.8f, pow(2.f - 2 * min(shadows, 1.f), 4.f) * 0.025); // 0.04 @ 1 - rgb = sign(rgb) * shd_con(abs(rgb), -0.50f * shadows * (1.f - shadows), 0.25f); // 0 @ 1 + rgb = sign(rgb) * shd_con(abs(rgb), -0.50f * shadows * (1.f - shadows), 0.25f); // 0 @ 1 return rgb; } @@ -52,4 +57,34 @@ float3 apply_user_shadows(float3 rgb, float shadows = 1.f) { float3 apply_user_highlights(float3 rgb, float highlights = 1.f) { rgb = sign(rgb) * hl_con(abs(rgb), (highlights - 1.f) * 4.f, 2.f); return rgb; -} \ No newline at end of file +} + +float3 applyUserColorGrading( + float3 color, + float userExposure = 1.f, + float userSaturation = 1.f, + float userShadows = 1.f, + float userHighlights = 1.f, + float userContrast = 1.f +) { + if (userExposure != 1.f) { + color *= userExposure; + } + if (userSaturation != 1.f) { + float3 okLCh = okLChFromBT709(color); + okLCh[1] *= userSaturation; + color = bt709FromOKLCh(okLCh); + } + if (userShadows != 1.f) { + color = apply_user_shadows(color, userShadows); + } + if (userHighlights != 1.f) { + color = apply_user_highlights(color, userHighlights); + } + if (userContrast != 1.f) { + color = applyContrastSafe(color, userContrast); + } + return color; +} + +#endif // SRC_COMMON_COLORGRADE_HLSL_ diff --git a/src/lostplanet/postprocess08_clamp_0x98F668B5.ps_4_0.hlsl b/src/lostplanet/postprocess08_clamp_0x98F668B5.ps_4_0.hlsl index 90dfac01..f8fa373e 100644 --- a/src/lostplanet/postprocess08_clamp_0x98F668B5.ps_4_0.hlsl +++ b/src/lostplanet/postprocess08_clamp_0x98F668B5.ps_4_0.hlsl @@ -36,53 +36,51 @@ float4 main(float4 v0 : SV_POSITION0, float2 v1 : TEXCOORD0) : SV_TARGET0 { if (injectedData.toneMapType != 0) { outputColor = max(0, textureColor.rgb) * gXfInWhite * gXfOutWhite; outputColor = pow(outputColor, gXfInGamma.xyz); - outputColor = pow(outputColor, 2.2f); // linear + } - if (injectedData.toneMapType != 1.f) { - if (injectedData.colorGradeSaturation != 1.f) { - float grayscale = yFromBT709(outputColor); - outputColor = lerp(grayscale, outputColor, injectedData.colorGradeSaturation); - outputColor = max(0, outputColor); - } + outputColor = pow(outputColor, 2.2f); // linear + outputColor = applyUserColorGrading( + outputColor, + 1.f, + injectedData.colorGradeSaturation, + injectedData.colorGradeShadows, + injectedData.colorGradeHighlights, + injectedData.colorGradeContrast + ); - if (injectedData.colorGradeShadows != 1.f) { - outputColor = apply_user_shadows(outputColor, injectedData.colorGradeShadows); - } - if (injectedData.colorGradeHighlights != 1.f) { - outputColor = apply_user_highlights(outputColor, injectedData.colorGradeHighlights); - } - if (injectedData.colorGradeContrast != 1.f) { - float3 workingColor = pow(outputColor / 0.18f, injectedData.colorGradeContrast) * 0.18f; - // Working in BT709 still - float workingColorY = yFromBT709(workingColor); - float outputColorY = yFromBT709(outputColor); - outputColor *= outputColorY ? workingColorY / outputColorY : 1.f; - } + const float vanillaMidGray = 0.18f; - float hdrScale = (injectedData.toneMapPeakNits / injectedData.toneMapGameNits); - if (injectedData.toneMapType == 2.f) { - // ACES - outputColor = aces_rgc_rrt_odt( - outputColor, - 0.0001f / hdrScale, // minY - 48.f * hdrScale - ); - outputColor /= 48.f; - } else { // OpenDRT - outputColor = apply_aces_highlights(outputColor); - outputColor = open_drt_transform( - outputColor, - 100.f * hdrScale, - 0, - 1.f, - 0 - ); - outputColor *= hdrScale; - } - } - outputColor *= injectedData.toneMapGameNits / injectedData.toneMapUINits; - outputColor = pow(outputColor, 1.f / 2.2f); + if (injectedData.toneMapType == 2.f) { + const float ACES_MID_GRAY = 0.10f; + float paperWhite = injectedData.toneMapGameNits * (vanillaMidGray / ACES_MID_GRAY); + float hdrScale = (injectedData.toneMapPeakNits / paperWhite); + outputColor = aces_rgc_rrt_odt( + outputColor, + 0.0001f / hdrScale, + 48.f * hdrScale + ); + outputColor /= 48.f; + outputColor *= (vanillaMidGray / ACES_MID_GRAY); + } else if (injectedData.toneMapType == 3.f) { + const float OPENDRT_MID_GRAY = 11.696f / 100.f; // open_drt_transform(0.18); + float paperWhite = injectedData.toneMapGameNits * (vanillaMidGray / OPENDRT_MID_GRAY); + float hdrScale = (injectedData.toneMapPeakNits / paperWhite); + outputColor = mul(BT709_2_BT2020_MAT, outputColor); + outputColor = max(0, outputColor); + outputColor = open_drt_transform( + outputColor, + 100.f * hdrScale, + 0, + 1.f, + 0 + ); + outputColor = mul(BT2020_2_BT709_MAT, outputColor); + outputColor *= hdrScale; + outputColor *= (vanillaMidGray / OPENDRT_MID_GRAY); } + outputColor *= injectedData.toneMapGameNits / injectedData.toneMapUINits; + outputColor = sign(outputColor) * pow(abs(outputColor), 1.f / 2.2f); + return float4(outputColor.rgb, textureColor.a); }