skip to content
==> include/pathtrace/t_tonemap.h <==
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"
6
7static 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}
13
14/* 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}
22
23/* 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}