1/* Template (included once per instantiation after t_math.h; see pathtrace/real.h): a linear sum of
2 * samples to an 8-bit sRGB pixel. */
3#include "pathtrace/real.h"
4#include "pathtrace/scene.h"
5#include "pathtrace/srgb.h"
67static inline float PT_FN(curve)(float m, uint32_t op) {
8 float one = PT_K(PT_C_ONE);
9 if (op == PT_TONEMAP_REINHARD) return PT_DIV(m, PT_ADD(one, m));
10 return PT_DIV(PT_MUL(m, PT_ADD(PT_MUL(PT_K(pt_c_aces[0]), m), PT_K(pt_c_aces[1]))),
11 PT_ADD(PT_MUL(m, PT_ADD(PT_MUL(PT_K(pt_c_aces[2]), m), PT_K(pt_c_aces[3]))), PT_K(pt_c_aces[4])));
12}
1314/* The sRGB code of a linear value: the largest k with x >= pt_srgb_t[k] (binary search; NaN and
15 * x < pt_srgb_t[1]: 0). */
16PT_API uint32_t PT_FN(quantize)(float x) {
17 uint32_t lo = 0;
18 for (uint32_t step = 128; step > 0; step >>= 1)
19 if (PT_GE(x, PT_K(pt_srgb_t[lo + step]))) lo += step;
20 return lo;
21}
2223/* An accumulated pixel (the sum of n samples) as 0xffBBGGRR. */
24PT_API uint32_t PT_FN(tonemap)(pt_v acc, uint32_t n, float exposure, uint32_t op) {
25 float nf = PT_FROM_U32(n);
26 uint32_t r = PT_FN(quantize)(PT_FN(curve)(PT_MUL(PT_DIV(acc.x, nf), exposure), op));
27 uint32_t g = PT_FN(quantize)(PT_FN(curve)(PT_MUL(PT_DIV(acc.y, nf), exposure), op));
28 uint32_t b = PT_FN(quantize)(PT_FN(curve)(PT_MUL(PT_DIV(acc.z, nf), exposure), op));
29 return r | g << 8 | b << 16 | 0xff000000u;
30}