ref: 1ec784ed5ae593f3d382c37c6f34fabe1497a861
parent: 10e8543f5aeabb345fa146c7401ef4ac9eb5df28
author: rodri <rgl@antares-labs.eu>
date: Mon Aug 19 01:16:26 EDT 2024
color: add ACES tone mapping functions.
--- a/color.c
+++ b/color.c
@@ -147,3 +147,74 @@
return (c & 0xFF)<<24|(c>>24 & 0xFF)<<16|
(c>>16 & 0xFF)<<8|(c>>8 & 0xFF);
}
+
+
+/* tone mapping */
+
+/*
+ * simplified ACES filmic tone mapping curve by Krzysztof Narkowicz
+ * https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
+ */
+static double
+_aces(double value)
+{
+ double a = 2.51;
+ double b = 0.03;
+ double c = 2.43;
+ double d = 0.59;
+ double e = 0.14;
+ value = (value * (a * value + b)) / (value * (c * value + d) + e);
+ return fclamp(value, 0, 1);
+}
+
+Color
+aces(Color c)
+{
+ c.r = _aces(c.r);
+ c.g = _aces(c.g);
+ c.b = _aces(c.b);
+ return c;
+}
+
+static double
+RRTAndODTFit(double v)
+{
+ double a = v * (v + 0.0245786f) - 0.000090537f;
+ double b = v * (0.983729f * v + 0.4329510f) + 0.238081f;
+ return a / b;
+}
+
+/*
+ * a better ACES curve fit by Stephen Hill (@self_shadow)
+ * https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
+ */
+Color
+aces2(Color c)
+{
+ /* sRGB → XYZ → D65_2_D60 → AP1 → RRT_SAT */
+ Matrix3 ACESInputMat = {
+ 0.59719, 0.35458, 0.04823, 0,
+ 0.07600, 0.90834, 0.01566, 0,
+ 0.02840, 0.13383, 0.83777, 0,
+ 0, 0, 0, 1,
+ };
+ /* ODT_SAT → XYZ → D60_2_D65 → sRGB */
+ Matrix3 ACESOutputMat = {
+ 1.60475, -0.53108, -0.07367, 0,
+ -0.10208, 1.10813, -0.00605, 0,
+ -0.00327, -0.07276, 1.07602, 0,
+ 0, 0, 0, 1,
+ };
+
+ c = xform3(c, ACESInputMat);
+ /* Apply RRT and ODT */
+ c.r = RRTAndODTFit(c.r);
+ c.g = RRTAndODTFit(c.g);
+ c.b = RRTAndODTFit(c.b);
+
+ c = xform3(c, ACESOutputMat);
+ c.r = fclamp(c.r, 0, 1);
+ c.g = fclamp(c.g, 0, 1);
+ c.b = fclamp(c.b, 0, 1);
+ return c;
+}
--- a/graphics.h
+++ b/graphics.h
@@ -418,6 +418,8 @@
Color srgb2linear(Color);
Color linear2srgb(Color);
ulong rgba2xrgb(ulong);
+Color aces(Color);
+Color aces2(Color);
/* shadeop */
double sign(double);