Skip to content

Commit 713a584

Browse files
committed
Fix matrix 3x3 inverse, improve LogLuv
1 parent 0a51b55 commit 713a584

3 files changed

Lines changed: 74 additions & 28 deletions

File tree

include/math/color-space.hpp

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -176,30 +176,50 @@ static f32x4 xyyToRgb(f32x4 xyy) noexcept { return xyzToRgb(xyyToXyz(xyy)); }
176176
// Linear sRGB <-> LogLuv
177177
static const f32x4x4 rgbToLogLuvMat = f32x4x4
178178
(
179-
f32x4(0.2209f, 0.3390f, 0.4184f, 0.0f),
180-
f32x4(0.1138f, 0.6780f, 0.7319f, 0.0f),
181-
f32x4(0.0102f, 0.1130f, 0.2969f, 0.0f),
179+
f32x4(0.1832848040f, 0.2126390040f, 0.252131164f, 0.0f),
180+
f32x4(0.1589263680f, 0.7151686540f, 0.788274765f, 0.0f),
181+
f32x4(0.0802136883f, 0.0721923187f, 0.283475161f, 0.0f),
182182
f32x4::zero
183183
);
184184
static const f32x4x4 logLuvToRgbMat = f32x4x4
185185
(
186-
f32x4( 6.0014f, -2.7008f, -1.7996f, 0.0f),
187-
f32x4(-1.3320f, 3.1029f, -5.7721f, 0.0f),
188-
f32x4( 0.3008f, -1.0882f, 5.6268f, 0.0f),
186+
f32x4( 7.666140550f, -2.211964610f, -0.667561352f, 0.0f),
187+
f32x4( 0.955670714f, 1.668192390f, -5.488834380f, 0.0f),
188+
f32x4(-2.412632940f, 0.201072842f, 5.114378450f, 0.0f),
189189
f32x4::zero
190190
);
191191

192+
static f32x4x4 calcLogLuvMat(const f32x4x4& rgbToXyzMat) noexcept
193+
{
194+
static const f32x4x4 m1 = f32x4x4
195+
(
196+
f32x4(1.0f, 0.0f, 1.0f, 0.0f),
197+
f32x4(0.0f, 1.0f, 15.0f, 0.0f),
198+
f32x4(0.0f, 0.0f, 3.0f, 0.0f),
199+
f32x4::zero
200+
);
201+
static const f32x4x4 m2 = f32x4x4
202+
(
203+
f32x4(4.0f / 9.0f, 0.0f, 0.0f, 0.0f),
204+
f32x4(0.0f, 1.0f, 0.0f, 0.0f),
205+
f32x4(0.0f, 0.0f, 0.62f / 9.0f, 0.0f),
206+
f32x4::zero
207+
);
208+
return dot3x3(m2, dot3x3(m1, rgbToXyzMat));
209+
}
210+
192211
/**
193212
* @brief Encodes linear RGB color (HDR) to the LogLuv format.
213+
* @details Encodes log2(Y) in [-20,20) range.
194214
* @param rgb target linear RGB color
195215
*/
196216
static uint32 rgbToLogLuv(f32x4 rgb) noexcept
197217
{
198218
auto luv = max(dot3x3(rgbToLogLuvMat, rgb), f32x4(1e-6f));
199-
auto uv = (uint2)fma(saturate((float2)luv / luv.getZ()), float2(255.0f), float2(0.5f));
200-
auto logLuv = (uint32)std::fma(saturate(std::fma(std::log2(
201-
luv.getY()), 1.0f / 64.0f, 0.5f)), 65535.0f, 0.5f);
202-
logLuv |= (uv.x << 24u) | (uv.y << 16u);
219+
auto uv = (uint2)fma(saturate((float2)luv / luv.getZ()), float2(511.0f), float2(0.5f));
220+
auto le = (uint32)std::fma(saturate(std::fma(std::log2(
221+
luv.getY()), (1.0f / 40.0f), 0.5f)), 16383.0f, 0.5f);
222+
auto logLuv = (uv.y << 23u) | (uv.x << 14u) | le;
203223
return dot3(rgb, rgb) > 0.0f ? logLuv : 0;
204224
}
205225
/**
@@ -208,8 +228,8 @@ static uint32 rgbToLogLuv(f32x4 rgb) noexcept
208228
*/
209229
static f32x4 logLuvToRgb(uint32 logLuv)
210230
{
211-
f32x4 luv; auto uv = float2(uint2(logLuv >> 24u, logLuv >> 16u) & 255u) * (1.0f / 255.0f);
212-
luv.floats.y = std::exp2(std::fma(logLuv & 65535u, (1.0f / 65535.0f) * 64.0f, -32.0f));
231+
f32x4 luv; auto uv = float2(uint2(logLuv >> 14u, logLuv >> 23u) & 511u) * (1.0f / 511.0f);
232+
luv.floats.y = std::exp2(std::fma(logLuv & 16383u, 40.0f / 16383.0f, -20.0f));
213233
luv.floats.z = luv.floats.y / uv.y; luv.floats.x = luv.floats.z * uv.x;
214234
return logLuv > 0 ? max(dot3x3(logLuvToRgbMat, luv), f32x4::zero) : f32x4::zero;
215235
}

include/math/matrix/float.hpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -778,30 +778,30 @@ static constexpr float4x4 transpose(float4x4 m) noexcept
778778
*/
779779
static constexpr float2x2 inverse(float2x2 m) noexcept
780780
{
781-
auto oneOverDeterminant = 1.0f / (m.c0.x * m.c1.y - m.c1.x * m.c0.y);
782-
return float2x2(m.c1.y * oneOverDeterminant, -m.c0.y * oneOverDeterminant,
783-
-m.c1.x * oneOverDeterminant, m.c0.x * oneOverDeterminant);
781+
auto invDeterminant = 1.0f / (m.c0.x * m.c1.y - m.c1.x * m.c0.y);
782+
return float2x2(m.c1.y * invDeterminant, -m.c0.y * invDeterminant,
783+
-m.c1.x * invDeterminant, m.c0.x * invDeterminant);
784784
}
785785
/**
786786
* @brief Calculates matrix inverse. (Useful for undoing transformations)
787787
* @param matrix target matrix to inverse
788788
*/
789789
static constexpr float3x3 inverse(float3x3 m) noexcept
790790
{
791-
auto oneOverDeterminant = 1.0f / (
792-
m.c0.x * (m.c1.y * m.c2.z - m.c2.y * m.c1.z)
791+
auto invDeterminant = 1.0f / (
792+
m.c0.x * (m.c1.y * m.c2.z - m.c2.y * m.c1.z)
793793
-m.c1.x * (m.c0.y * m.c2.z - m.c2.y * m.c0.z) +
794-
m.c2.x * (m.c0.y * m.c1.z - m.c1.y * m.c0.z));
794+
m.c2.x * (m.c0.y * m.c1.z - m.c1.y * m.c0.z));
795795
return float3x3(
796-
(m.c1.y * m.c2.z - m.c2.y * m.c1.z) * oneOverDeterminant,
797-
-(m.c0.y * m.c2.z - m.c2.y * m.c0.z) * oneOverDeterminant,
798-
(m.c0.y * m.c2.z - m.c1.y * m.c0.z) * oneOverDeterminant,
799-
-(m.c1.x * m.c2.z - m.c2.x * m.c1.z) * oneOverDeterminant,
800-
(m.c0.x * m.c2.z - m.c2.x * m.c0.z) * oneOverDeterminant,
801-
-(m.c0.x * m.c2.z - m.c1.x * m.c0.z) * oneOverDeterminant,
802-
(m.c1.x * m.c2.y - m.c2.x * m.c1.y) * oneOverDeterminant,
803-
-(m.c0.x * m.c2.y - m.c2.x * m.c0.y) * oneOverDeterminant,
804-
(m.c0.x * m.c2.y - m.c1.x * m.c0.y) * oneOverDeterminant);
796+
(m.c1.y * m.c2.z - m.c2.y * m.c1.z) * invDeterminant,
797+
-(m.c1.x * m.c2.z - m.c2.x * m.c1.z) * invDeterminant,
798+
(m.c1.x * m.c2.y - m.c2.x * m.c1.y) * invDeterminant,
799+
-(m.c0.y * m.c2.z - m.c2.y * m.c0.z) * invDeterminant,
800+
(m.c0.x * m.c2.z - m.c2.x * m.c0.z) * invDeterminant,
801+
-(m.c0.x * m.c2.y - m.c2.x * m.c0.y) * invDeterminant,
802+
(m.c0.y * m.c1.z - m.c1.y * m.c0.z) * invDeterminant,
803+
-(m.c0.x * m.c1.z - m.c1.x * m.c0.z) * invDeterminant,
804+
(m.c0.x * m.c1.y - m.c1.x * m.c0.y) * invDeterminant);
805805
}
806806
/**
807807
* @brief Calculates matrix inverse. (Useful for undoing transformations)

include/math/simd/matrix/float.hpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,32 @@ static f32x4x4 inverse4x4(const f32x4x4& m) noexcept
616616
#endif
617617
}
618618

619-
// TODO: inverse of the 3x3 matrix like in the Jolt lib.
619+
/**
620+
* @brief Calculates 3x3 SIMD matrix determinant.
621+
* @param[in] m target SIMD matrix
622+
*/
623+
static float calcDeterminant3x3(const f32x4x4& m) noexcept
624+
{
625+
return dot3(m.c0, cross3(m.c1, m.c2));
626+
}
627+
/**
628+
* @brief Calculates 3x3 SIMD matrix inverse. (Useful for undoing transformations)
629+
* @param[in] m target SIMD matrix to inverse
630+
*/
631+
static f32x4x4 inverse3x3(const f32x4x4& m) noexcept
632+
{
633+
auto invDeterminant = 1.0f / calcDeterminant3x3(m);
634+
return f32x4x4(
635+
(m.c1[1] * m.c2[2] - m.c2[1] * m.c1[2]) * invDeterminant,
636+
-(m.c1[0] * m.c2[2] - m.c2[0] * m.c1[2]) * invDeterminant,
637+
(m.c1[0] * m.c2[1] - m.c2[0] * m.c1[1]) * invDeterminant, 0.0f,
638+
-(m.c0[1] * m.c2[2] - m.c2[1] * m.c0[2]) * invDeterminant,
639+
(m.c0[0] * m.c2[2] - m.c2[0] * m.c0[2]) * invDeterminant,
640+
-(m.c0[0] * m.c2[1] - m.c2[0] * m.c0[1]) * invDeterminant, 0.0f,
641+
(m.c0[1] * m.c1[2] - m.c1[1] * m.c0[2]) * invDeterminant,
642+
-(m.c0[0] * m.c1[2] - m.c1[0] * m.c0[2]) * invDeterminant,
643+
(m.c0[0] * m.c1[1] - m.c1[0] * m.c0[1]) * invDeterminant, 0.0f,
644+
0.0f, 0.0f, 0.0f, 0.0f);
645+
}
620646

621647
} // namespace math

0 commit comments

Comments
 (0)