Blender V5.0
types_rgbe.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7#include "util/math_fast.h"
8#include "util/math_float3.h"
9#include "util/types_base.h"
10
12
13struct RGBE {
14 union {
15 struct {
16 uint8_t r, g, b, e;
17 };
18 float f;
19 };
20
21 RGBE() = default;
22
23 ccl_device_inline_method RGBE(const float f_) : f(f_) {}
24};
25
26static_assert(sizeof(RGBE) == 4, "RGBE expected to be exactly 4 bytes");
27
54
55#define RGBE_EXP_BIAS 15
56#define RGBE_MANTISSA_BITS 8
57#define RGBE_EXPONENT_BITS 5
58#define RGBE_MAX 65280.0f
59
61{
62 const float max_v = min(reduce_max(fabs(rgb)), RGBE_MAX);
63 if (max_v < ldexpf(0.5f, -RGBE_EXP_BIAS - RGBE_MANTISSA_BITS)) {
64 return RGBE(0.0f);
65 }
66
67 int e = max(-RGBE_EXP_BIAS - 1, floor_log2f(max_v)) + 1;
68 float v = ldexpf(1.0f, RGBE_MANTISSA_BITS - e);
69
70 /* The original implementation by Greg Ward uses `floor`, causing systematic bias when
71 * accumulated in a buffer.
72 * We use `round` instead, but need to deal with overflow. */
73 if (int(roundf(max_v * v)) == power_of_2(RGBE_MANTISSA_BITS)) {
74 e += 1;
75 v *= 0.5f;
76 }
77
78 /* Get sign bits. */
79 const uint sign_bits = ((__float_as_uint(rgb.x) >> 31) << 7) |
80 ((__float_as_uint(rgb.y) >> 31) << 6) |
81 ((__float_as_uint(rgb.z) >> 31) << 5);
82
83 RGBE rgbe;
84 rgb = min(round(fabs(rgb) * v), make_float3(255.0f));
85 rgbe.r = uint8_t(rgb.x);
86 rgbe.g = uint8_t(rgb.y);
87 rgbe.b = uint8_t(rgb.z);
88 rgbe.e = uint8_t(((e + RGBE_EXP_BIAS) & 0x1Fu) | sign_bits);
89 return rgbe;
90}
91
93{
94 if (rgbe.f == 0.0f) {
95 return zero_float3();
96 }
97
98 const int e = rgbe.e & 0x1Fu;
99 const float f = ldexpf(1.0f, e - (int)(RGBE_EXP_BIAS + RGBE_MANTISSA_BITS));
100 float3 result = make_float3(rgbe.r, rgbe.g, rgbe.b) * f;
101
102 /* Set sign bits. */
103 result.x = or_mask(result.x, (uint(rgbe.e) & 0x80u) << 24);
104 result.y = or_mask(result.y, (uint(rgbe.e) & 0x40u) << 25);
105 result.z = or_mask(result.z, (uint(rgbe.e) & 0x20u) << 26);
106 return result;
107}
108
MINLINE float power_of_2(float f)
unsigned int uint
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
reduce_max(value.rgb)") DEFINE_VALUE("REDUCE(lhs
#define ccl_device_inline
#define RGBE_EXP_BIAS
#define RGBE_MANTISSA_BITS
#define RGBE_MAX
#define ccl_device_inline_method
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define ldexpf(x, y)
#define roundf(x)
#define __float_as_uint(x)
#define round
ccl_device_inline float or_mask(const float x, const uint y)
Definition math_base.h:671
ccl_device_inline int floor_log2f(const float x)
Definition math_fast.h:344
ccl_device_inline float2 fabs(const float2 a)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
#define ccl_device
#define min(a, b)
Definition sort.cc:36
uint8_t r
Definition types_rgbe.h:16
uint8_t g
Definition types_rgbe.h:16
ccl_device_inline_method RGBE(const float f_)
Definition types_rgbe.h:23
uint8_t e
Definition types_rgbe.h:16
float f
Definition types_rgbe.h:18
uint8_t b
Definition types_rgbe.h:16
RGBE()=default
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
max
Definition text_draw.cc:251
ccl_device_inline float3 rgbe_to_rgb(const RGBE rgbe)
Definition types_rgbe.h:92
ccl_device RGBE rgb_to_rgbe(float3 rgb)
Definition types_rgbe.h:60