diff --git a/glm/gtc/packing.hpp b/glm/gtc/packing.hpp index 8808aa4f..16b8a02f 100644 --- a/glm/gtc/packing.hpp +++ b/glm/gtc/packing.hpp @@ -472,6 +472,28 @@ namespace glm /// @see uint32 packF2x11_1x10(vec3 const & v) GLM_FUNC_DECL vec3 unpackF2x11_1x10(uint32 p); + + /// First, converts the first two components of the normalized floating-point value v into 11-bit signless floating-point values. + /// Then, converts the third component of the normalized floating-point value v into a 10-bit signless floating-point value. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The first vector component specifies the 11 least-significant bits of the result; + /// the last component specifies the 10 most-significant bits. + /// + /// @see gtc_packing + /// @see vec3 unpackF3x9_E1x5(uint32 const & p) + GLM_FUNC_DECL uint32 packF3x9_E1x5(vec3 const & v); + + /// First, unpacks a single 32-bit unsigned integer p into two 11-bit signless floating-point values and one 10-bit signless floating-point value . + /// Then, each component is converted to a normalized floating-point value to generate the returned three-component vector. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packF3x9_E1x5(vec3 const & v) + GLM_FUNC_DECL vec3 unpackF3x9_E1x5(uint32 p); + /// @} }// namespace glm diff --git a/glm/gtc/packing.inl b/glm/gtc/packing.inl index 6f351a8f..97a148a7 100644 --- a/glm/gtc/packing.inl +++ b/glm/gtc/packing.inl @@ -248,6 +248,18 @@ namespace detail uint32 pack; }; + union u9u9u9e5 + { + struct + { + uint x : 9; + uint y : 9; + uint z : 9; + uint w : 5; + } data; + uint32 pack; + }; + }//namespace detail GLM_FUNC_QUALIFIER uint8 packUnorm1x8(float v) @@ -486,4 +498,31 @@ namespace detail detail::packed10bitToFloat(v >> 22)); } + GLM_FUNC_QUALIFIER uint32 packF3x9_E1x5(vec3 const & v) + { + float const SharedExpMax = (pow(2.0f, 9.0f - 1.0f) / pow(2.0f, 9.0f)) * pow(2.0f, 31.f - 15.f); + vec3 const Color = clamp(v, 0.0f, SharedExpMax); + float const MaxColor = max(Color.x, max(Color.y, Color.z)); + + float const ExpSharedP = max(-15.f - 1.f, floor(log2(MaxColor))) + 1.0f + 15.f; + float const MaxShared = floor(MaxColor / pow(2.0f, (ExpSharedP - 16.f - 9.f)) + 0.5f); + float const ExpShared = MaxShared == pow(2.0f, 9.0f) ? ExpSharedP + 1.0f : ExpSharedP; + + uvec3 const ColorComp(floor(Color / pow(2.f, (ExpShared - 15.f - 9.f)) + 0.5f)); + + detail::u9u9u9e5 Unpack; + Unpack.data.x = ColorComp.x; + Unpack.data.y = ColorComp.y; + Unpack.data.z = ColorComp.z; + Unpack.data.w = uint(ExpShared); + return Unpack.pack; + } + + GLM_FUNC_QUALIFIER vec3 unpackF3x9_E1x5(uint32 v) + { + detail::u9u9u9e5 Unpack; + Unpack.pack = v; + + return vec3(Unpack.data.x, Unpack.data.y, Unpack.data.z) * pow(2.0f, Unpack.data.w - 15.f - 9.f); + } }//namespace glm diff --git a/readme.md b/readme.md index c70e22c4..18041c21 100644 --- a/readme.md +++ b/readme.md @@ -54,6 +54,7 @@ glm::mat4 camera(float Translate, glm::vec2 const & Rotate) #### [GLM 0.9.7.2](https://github.com/g-truc/glm/releases/latest) - 2015-XX-XX ##### Improvements: - Added compNormalize and compScale functions to GTX_component_wise +- Added packF3x9_E1x5 and unpackF3x9_E1x5 to GTC_packing for RGB9E5 #416 ##### Fixes: - Fixed GTC_round floorMultiple/ceilMultiple #412 diff --git a/test/gtc/gtc_packing.cpp b/test/gtc/gtc_packing.cpp index 45a67f3f..000eafc5 100644 --- a/test/gtc/gtc_packing.cpp +++ b/test/gtc/gtc_packing.cpp @@ -254,6 +254,30 @@ int test_F2x11_1x10() return Error; } +int test_F3x9_E1x5() +{ + int Error = 0; + + std::vector Tests; + Tests.push_back(glm::vec3(1.0f)); + Tests.push_back(glm::vec3(0.0f)); + Tests.push_back(glm::vec3(2.0f)); + Tests.push_back(glm::vec3(0.1f)); + Tests.push_back(glm::vec3(0.5f)); + Tests.push_back(glm::vec3(0.9f)); + + for (std::size_t i = 0; i < Tests.size(); ++i) + { + glm::uint32 p0 = glm::packF3x9_E1x5(Tests[i]); + glm::vec3 v0 = glm::unpackF3x9_E1x5(p0); + glm::uint32 p1 = glm::packF3x9_E1x5(v0); + glm::vec3 v1 = glm::unpackF3x9_E1x5(p1); + Error += glm::all(glm::epsilonEqual(v0, v1, 0.01f)) ? 0 : 1; + } + + return Error; +} + int test_packUnorm1x16() { int Error = 0; @@ -522,6 +546,7 @@ int main() Error += test_packUnorm4x8(); Error += test_F2x11_1x10(); + Error += test_F3x9_E1x5(); Error += test_Snorm3x10_1x2(); Error += test_Unorm3x10_1x2(); Error += test_I3x10_1x2();