/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #pragma once #include "Math/Math.hpp" #include namespace OpenVulkano::Math { class RGB565 { static uint16_t Make5(uint8_t val) { return val * 31.0f / 255.0f; } static uint16_t Make6(uint8_t val) { return val * 63.0f / 255.0f; } static uint8_t Unmake5(uint16_t val) { return static_cast(val * 255.0f / 31.0f); } static uint8_t Unmake6(uint16_t val) { return static_cast(val * 255.0f / 63.0f); } static float Unmake5ToFloat(uint16_t val) { return std::clamp(val / 31.0f, 0.0f, 1.0f); } static float Unmake6ToFloat(uint16_t val) { return std::clamp(val / 63.0f, 0.0f, 1.0f); } static uint16_t Make5FromFloat(float val) { return (uint16_t) std::clamp(val * 31.0f, 0.0f, 31.f); } static uint16_t Make6FromFloat(float val) { return (uint16_t) std::clamp(val * 63.0f, 0.0f, 63.f); } public: union { uint16_t value; struct { uint16_t b : 5; uint16_t g : 6; uint16_t r : 5; }; }; RGB565() : r(0), g(0), b(0) {} template || std::is_signed_v>> RGB565(const Math::Vector3& color) : b(Make5(color.b)), g(Make6(color.g)), r(Make5(color.r)) { } template || std::is_signed_v>> RGB565(const Math::Vector4& color) : b(Make5(color.b)), g(Make6(color.g)), r(Make5(color.r)) { } template || std::is_signed_v>> RGB565(const Math::Vector3_SIMD& color) : b(Make5(color.b)), g(Make6(color.g)), r(Make5(color.r)) { } template>> RGB565(const Math::Vector3& color) : b(Make5FromFloat(color.b)), g(Make6FromFloat(color.g)), r(Make5FromFloat(color.r)) { } template>> RGB565(const Math::Vector4& color) : b(Make5FromFloat(color.b)), g(Make6FromFloat(color.g)), r(Make5FromFloat(color.r)) { } template>> RGB565(const Math::Vector3_SIMD& color) : b(Make5FromFloat(color.b)), g(Make6FromFloat(color.g)), r(Make5FromFloat(color.r)) { } uint8_t GetR() { return Unmake5(r); } uint8_t GetG() { return Unmake6(g); } uint8_t GetB() { return Unmake5(b); } template || std::is_signed_v>> Math::Vector3 Get3() { return { GetR(), GetG(), GetB() }; } template || std::is_signed_v>> Math::Vector4 Get4() { return { GetR(), GetG(), GetB(), 1 }; } template || std::is_signed_v>> Math::Vector3_SIMD GetSIMD() { return { GetR(), GetG(), GetB() }; } template>> Math::Vector3 Get3Normalized() { return { GetR_Normalized(), GetG_Normalized(), GetB_Normalized() }; } template>> Math::Vector4 Get4Normalized() { return { GetR_Normalized(), GetG_Normalized(), GetB_Normalized(), 1 }; } template>> Math::Vector3_SIMD Get3NormalizedSIMD() { return { GetR_Normalized(), GetG_Normalized(), GetB_Normalized() }; } void SetR(uint8_t red) { r = Make5(red); } void SetG(uint8_t green) { g = Make6(green); } void SetB(uint8_t blue) { b = Make5(blue); } template || std::is_signed_v>> void Set(const Math::Vector3& color) { r = Make5(color.r); g = Make6(color.g); b = Make5(color.b); } template || std::is_signed_v>> void Set(const Math::Vector4& color) { r = Make5(color.r); g = Make6(color.g); b = Make5(color.b); } template>> void SetNormalized(const Math::Vector3& color) { r = Make5FromFloat(color.r); g = Make6FromFloat(color.g); b = Make5FromFloat(color.b); } template>> void SetNormalized(const Math::Vector4& color) { r = Make5FromFloat(color.r); g = Make6FromFloat(color.g); b = Make5FromFloat(color.b); } float GetR_Normalized() { return Unmake5ToFloat(r); } float GetG_Normalized() { return Unmake6ToFloat(g); } float GetB_Normalized() { return Unmake5ToFloat(b); } void SetR_Normalized(float red) { r = Make5FromFloat(red); } void SetG_Normalized(float green) { g = Make6FromFloat(green); } void SetB_Normalized(float blue) { b = Make5FromFloat(blue); } RGB565& operator=(const RGB565& other) { value = other.value; return *this; } RGB565& operator=(RGB565&& other) noexcept { value = other.value; return *this; } template || std::is_signed_v>> RGB565& operator=(const Vector3& color) { Set(color); return *this; } template || std::is_signed_v>> RGB565& operator=(const Vector4& color) { Set(color); return *this; } template || std::is_signed_v>> RGB565& operator=(const Vector3_SIMD& color) { Set(color); return *this; } template || std::is_signed_v>> RGB565& operator=(const Vector4_SIMD& color) { Set(color); return *this; } template>> RGB565& operator=(const Vector3& color) { SetNormalized(color); return *this; } template>> RGB565& operator=(const Vector4& color) { SetNormalized(color); return *this; } template>> RGB565& operator=(const Vector3_SIMD& color) { SetNormalized(color); return *this; } template || std::is_signed_v>> RGB565& operator+=(const Vector3& color) { Set(Get3() + color); return *this; } template || std::is_signed_v>> RGB565& operator+=(const Vector4& color) { Set(Get4() + color); return *this; } template || std::is_signed_v>> RGB565& operator+=(const Vector3_SIMD& color) { Set(Get3SIMD() + color); return *this; } template>> RGB565& operator+=(const Vector3& color) { SetNormalized(Get3Normalized() + color); return *this; } template>> RGB565& operator+=(const Vector4& color) { SetNormalized(Get4Normalized() + color); return *this; } template>> RGB565& operator+=(const Vector3_SIMD& color) { SetNormalized(Get3NormalizedSIMD() + color); return *this; } template || std::is_signed_v>> RGB565& operator-=(const Vector3& color) { Set(Get3() - color); return *this; } template || std::is_signed_v>> RGB565& operator-=(const Vector4& color) { Set(Get4() - color); return *this; } template || std::is_signed_v>> RGB565& operator-=(const Vector3_SIMD& color) { Set(Get3SIMD() - color); return *this; } template>> RGB565& operator-=(const Vector3& color) { SetNormalized(Get3Normalized() - color); return *this; } template>> RGB565& operator-=(const Vector4& color) { SetNormalized(Get4Normalized() - color); return *this; } template>> RGB565& operator-=(const Vector3_SIMD& color) { SetNormalized(Get3NormalizedSIMD() - color); return *this; } bool operator==(const RGB565& other) const { return value == other.value; } bool operator!=(const RGB565& other) const { return value != other.value; } template || std::is_signed_v>> operator Math::Vector4() { return Get4(); } template || std::is_signed_v>> operator Math::Vector3() { return Get3(); } template || std::is_signed_v>> operator Math::Vector3_SIMD() { return Get3SIMD(); } template>> operator Math::Vector4() { return Get4Normalized(); } template>> operator Math::Vector3() { return Get3Normalized(); } }; static_assert(sizeof(RGB565) == 2); }