ACES Fitting
| // Mostly code from https://github.com/ampas/aces-dev | |
| Vec3 ACES_RRT( Vec3 aces ) | |
| { | |
| // --- Glow module --- // | |
| float saturation = rgb_2_saturation( aces); | |
| float ycIn = rgb_2_yc( aces); | |
| float s = sigmoid_shaper( (saturation - 0.4f) / 0.2f); | |
| float addedGlow = 1.0f + glow_fwd( ycIn, RRT_GLOW_GAIN * s, RRT_GLOW_MID); | |
| aces = mult_f_f3( addedGlow, aces); | |
| // --- Red modifier --- // | |
| float hue = rgb_2_hue( aces); | |
| float centeredHue = center_hue( hue, RRT_RED_HUE); | |
| float hueWeight = cubic_basis_shaper( centeredHue, RRT_RED_WIDTH); | |
| aces[0] = aces[0] + hueWeight * saturation * (RRT_RED_PIVOT - aces[0]) * (1.0f - RRT_RED_SCALE); | |
| // --- ACES to RGB rendering space --- // | |
| aces = clamp( aces, 0.0f, HALF_POS_INF); // avoids saturated negative colors from becoming positive in the matrix | |
| Vec3 rgbPre = mult_f3_f33( aces, AP0_2_AP1_MAT); | |
| rgbPre = clamp( rgbPre, 0.0f, HALF_MAX); | |
| // --- Global desaturation --- // | |
| rgbPre = mult_f3_f33( rgbPre, RRT_SAT_MAT); | |
| // --- Apply the tonescale independently in rendering-space RGB --- // | |
| Vec3 rgbPost; | |
| rgbPost[0] = segmented_spline_c5_fwd( rgbPre[0]); | |
| rgbPost[1] = segmented_spline_c5_fwd( rgbPre[1]); | |
| rgbPost[2] = segmented_spline_c5_fwd( rgbPre[2]); | |
| // --- RGB rendering space to OCES --- // | |
| Vec3 rgbOces = mult_f3_f33( rgbPost, AP1_2_AP0_MAT); | |
| return rgbOces; | |
| } | |
| Vec3 ACES_ODT( Vec3 oces ) | |
| { | |
| // OCES to RGB rendering space | |
| Vec3 rgbPre = mult_f3_f33( oces, AP0_2_AP1_MAT); | |
| // Apply the tonescale independently in rendering-space RGB | |
| Vec3 rgbPost; | |
| rgbPost[0] = segmented_spline_c9_fwd( rgbPre[0]); | |
| rgbPost[1] = segmented_spline_c9_fwd( rgbPre[1]); | |
| rgbPost[2] = segmented_spline_c9_fwd( rgbPre[2]); | |
| // Scale luminance to linear code value | |
| Vec3 linearCV; | |
| linearCV[0] = Y_2_linCV( rgbPost[0], CINEMA_WHITE, CINEMA_BLACK); | |
| linearCV[1] = Y_2_linCV( rgbPost[1], CINEMA_WHITE, CINEMA_BLACK); | |
| linearCV[2] = Y_2_linCV( rgbPost[2], CINEMA_WHITE, CINEMA_BLACK); | |
| // Apply gamma adjustment to compensate for dim surround | |
| linearCV = darkSurround_to_dimSurround( linearCV); | |
| // Apply desaturation to compensate for luminance difference | |
| linearCV = mult_f3_f33( linearCV, ODT_SAT_MAT); | |
| // Convert to display primary encoding | |
| // Rendering space RGB to XYZ | |
| Vec3 XYZ = mult_f3_f33( linearCV, AP1_2_XYZ_MAT); | |
| // Apply CAT from ACES white point to assumed observer adapted white point | |
| //XYZ = mult_f3_f33( XYZ, D60_2_D65_CAT ); | |
| // CIE XYZ to display primaries | |
| linearCV = mult_f3_f33( XYZ, XYZ_2_DISPLAY_PRI_MAT); | |
| // Handle out-of-gamut values | |
| // Clip values < 0 or > 1 (i.e. projecting outside the display primaries) | |
| linearCV = clamp( linearCV, 0.0f, 1.0f); | |
| return linearCV; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment