/* * 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(int16_t val) { val = std::clamp(val, 0, 255); return val * 31.0f / 255.0f; } static uint16_t Make6(int16_t val) { val = std::clamp(val, 0, 255); 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, bool> = true> RGB565(const Math::Vector3& color) : b(Make5(color.b)), g(Make6(color.g)), r(Make5(color.r)) { } template, bool> = true> RGB565(const Math::Vector4& color) : b(Make5(color.b)), g(Make6(color.g)), r(Make5(color.r)) { } template, bool> = true> RGB565(const Math::Vector3_SIMD& color) : b(Make5(color.b)), g(Make6(color.g)), r(Make5(color.r)) { } template, bool> = true> RGB565(const Math::Vector3& color) : b(Make5FromFloat(color.b)), g(Make6FromFloat(color.g)), r(Make5FromFloat(color.r)) { } template, bool> = true> RGB565(const Math::Vector4& color) : b(Make5FromFloat(color.b)), g(Make6FromFloat(color.g)), r(Make5FromFloat(color.r)) { } template, bool> = true> 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, bool> = true> Math::Vector3 Get3() { return { GetR(), GetG(), GetB() }; } template, bool> = true> Math::Vector4 Get4() { return { GetR(), GetG(), GetB(), 1 }; } template, bool> = true> Math::Vector3_SIMD GetSIMD() { return { GetR(), GetG(), GetB() }; } template, bool> = true> Math::Vector3 Get3Normalized() { return { GetR_Normalized(), GetG_Normalized(), GetB_Normalized() }; } template, bool> = true> Math::Vector4 Get4Normalized() { return { GetR_Normalized(), GetG_Normalized(), GetB_Normalized(), 1 }; } template, bool> = true> 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, bool> = true> void Set(const Math::Vector3& color) { r = Make5(color.r); g = Make6(color.g); b = Make5(color.b); } template, bool> = true> void Set(const Math::Vector4& color) { r = Make5(color.r); g = Make6(color.g); b = Make5(color.b); } template, bool> = true> void SetNormalized(const Math::Vector3& color) { r = Make5FromFloat(color.r); g = Make6FromFloat(color.g); b = Make5FromFloat(color.b); } template, bool> = true> 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); } template, bool> = true> RGB565& operator=(const Vector3& color) { Set(color); return *this; } template, bool> = true> RGB565& operator=(const Vector3_SIMD& color) { Set(color); return *this; } template, bool> = true> RGB565& operator=(const Vector4_SIMD& color) { Set(color); return *this; } template, bool> = true> RGB565& operator=(const Vector3& color) { SetNormalized(color); return *this; } template, bool> = true> RGB565& operator=(const Vector4& color) { SetNormalized(color); return *this; } template, bool> = true> RGB565& operator=(const Vector3_SIMD& color) { SetNormalized(color); return *this; } template, bool> = true> RGB565& operator+=(const Vector3& color) { Set(Get3() + color); return *this; } template, bool> = true> RGB565& operator+=(const Vector4& color) { Set(Get4() + color); return *this; } template, bool> = true> RGB565& operator+=(const Vector3_SIMD& color) { Set(GetSIMD() + color); return *this; } template, bool> = true> RGB565& operator+=(const Vector3& color) { SetNormalized(Get3Normalized() + color); return *this; } template, bool> = true> RGB565& operator+=(const Vector4& color) { SetNormalized(Get4Normalized() + color); return *this; } template, bool> = true> RGB565& operator+=(const Vector3_SIMD& color) { SetNormalized(Get3NormalizedSIMD() + color); return *this; } template, bool> = true> RGB565& operator-=(const Vector3& color) { Set(Get3() - color); return *this; } template, bool> = true> RGB565& operator-=(const Vector4& color) { Set(Get4() - color); return *this; } template, bool> = true> RGB565& operator-=(const Vector3_SIMD& color) { Set(GetSIMD() - color); return *this; } template, bool> = true> RGB565& operator-=(const Vector3& color) { SetNormalized(Get3Normalized() - color); return *this; } template, bool> = true> RGB565& operator-=(const Vector4& color) { SetNormalized(Get4Normalized() - color); return *this; } template, bool> = true> 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, bool> = true> operator Math::Vector4() { return Get4(); } template, bool> = true> operator Math::Vector3() { return Get3(); } template, bool> = true> operator Math::Vector3_SIMD() { return GetSIMD(); } template, bool> = true> operator Math::Vector4() { return Get4Normalized(); } template, bool> = true> operator Math::Vector3() { return Get3Normalized(); } }; static_assert(sizeof(RGB565) == 2); }