Skip to content

Instantly share code, notes, and snippets.

@knarkowicz
Created August 6, 2018 17:20
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save knarkowicz/96200ae2ddeb648d0e07446679627bf0 to your computer and use it in GitHub Desktop.
Save knarkowicz/96200ae2ddeb648d0e07446679627bf0 to your computer and use it in GitHub Desktop.
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