diff --git a/src/nvmath/PackedFloat.cpp b/src/nvmath/PackedFloat.cpp index 3327d20..6f3d107 100755 --- a/src/nvmath/PackedFloat.cpp +++ b/src/nvmath/PackedFloat.cpp @@ -25,24 +25,25 @@ Vector3 nv::r11g11b10_to_vector3(FloatR11G11B10 v) { FloatR11G11B10 nv::vector3_to_r11g11b10(const Vector3 & v) { } -// These are based on: -// http://www.graphics.cornell.edu/~bjw/rgbe/rgbe.c -// While this may not be the best way to encode/decode RGBE8, I'm not making any changes to maintain compatibility. +// Implementation based on on: +// https://cbloomrants.blogspot.com/2020/06/widespread-error-in-radiance-hdr-rgbe.html FloatRGBE8 nv::vector3_to_rgbe8(const Vector3 & v) { float m = max3(v.x, v.y, v.z); FloatRGBE8 rgbe; - if (m < 1e-32) { + if (m < 1e-32f) { + // Exponent byte = 0 is a special encoding that makes RGB output = 0 rgbe.v = 0; } else { int e; - float scale = frexpf(m, &e) * 256.0f / m; - rgbe.r = U8(ftoi_round(v.x * scale)); - rgbe.g = U8(ftoi_round(v.y * scale)); - rgbe.b = U8(ftoi_round(v.z * scale)); + frexpf(m, &e); + float scale = ldexpf(1.0f, -exponent + 8); + rgbe.r = U8(v.x * scale); + rgbe.g = U8(v.y * scale); + rgbe.b = U8(v.z * scale); rgbe.e = U8(e + 128); } @@ -52,8 +53,8 @@ FloatRGBE8 nv::vector3_to_rgbe8(const Vector3 & v) { Vector3 nv::rgbe8_to_vector3(FloatRGBE8 v) { if (v.e != 0) { - float scale = ldexpf(1.0f, v.e-(int)(128+8)); // +8 to divide by 256. @@ Shouldn't we divide by 255 instead? - return scale * Vector3(float(v.r), float(v.g), float(v.b)); + float scale = ldexpf(1.0f, (int)v.e-128+8); // +8 to divide by 256. + return scale * Vector3(float(v.r + 0.5f), float(v.g + 0.5f), float(v.b + 0.5f)); } return Vector3(0);