From f8b92ce3aa08b1445c9f956d8166830946562d12 Mon Sep 17 00:00:00 2001 From: navewindre Date: Wed, 3 Sep 2025 20:10:09 +0200 Subject: a --- src/util/color.h | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 src/util/color.h (limited to 'src/util/color.h') diff --git a/src/util/color.h b/src/util/color.h new file mode 100644 index 0000000..526cddc --- /dev/null +++ b/src/util/color.h @@ -0,0 +1,168 @@ +#pragma once +#include "typedef.h" +#include + +struct CLR { + F32 r, g, b, a; + + static const CLR WHITE( F32 a_ = 1.f ) { return { 1.f, 1.f, 1.f, a_ }; } + static const CLR BLACK( F32 a_ = 1.f ) { return { 0.f, 0.f, 0.f, a_ }; } + static const CLR RED( F32 a_ = 1.f ) { return { 1.f, 0.f, 0.f, a_ }; } + static const CLR GREEN( F32 a_ = 1.f ) { return { 0.f, 1.f, 0.f, a_ }; } + static const CLR BLUE( F32 a_ = 1.f ) { return { 0.f, 0.f, 1.f, a_ }; } + static const CLR YELLOW( F32 a_ = 1.f ) { return { 1.f, 1.f, 0.f, a_ }; } + static const CLR MAGENTA( F32 a_ = 1.f ) { return { 1.f, 0.f, 1.f, a_ }; } + static const CLR CYAN( F32 a_ = 1.f ) { return { 0.f, 1.f, 1.f, a_ }; } + + // slow accurate blend, looks prettier but cache maybe if possible + static CLR blend( const CLR& c1, const CLR& c2, float t = 0.5f ) { + F32 c1r = c1.r * c1.r; + F32 c1g = c1.g * c1.g; + F32 c1b = c1.b * c1.b; + F32 c1a = c1.a * c1.a; + F32 c2r = c2.r * c2.r; + F32 c2g = c2.g * c2.g; + F32 c2b = c2.b * c2.b; + F32 c2a = c2.a * c2.a; + return { + sqrtf( ( c2r * t ) + ( c1r * ( 1.f - t ) ) ), + sqrtf( ( c2g * t ) + ( c1g * ( 1.f - t ) ) ), + sqrtf( ( c2b * t ) + ( c1b * ( 1.f - t ) ) ), + sqrtf( ( c2a * t ) + ( c1a * ( 1.f - t ) ) ) + }; + } + + // fast inaccurate blend + static CLR blend_root( const CLR& c1, const CLR& c2, float t = 0.5f ) { + return { + ( c2.r * t ) + ( c1.r * ( 1.f - t ) ), + ( c2.g * t ) + ( c1.g * ( 1.f - t ) ), + ( c2.b * t ) + ( c1.b * ( 1.f - t ) ), + ( c2.a * t ) + ( c1.a * ( 1.f - t ) ) + }; + } + + static CLR from_hsb( F32 hue, F32 saturation, F32 brightness ) { + CLR c; + if( saturation <= 0.0f ) { + c.r = c.g = c.b = brightness; + return c; + } + + I32 h = (I32)( hue * 6 ); + F32 f = hue * 6 - h; + F32 p = brightness * ( 1 - saturation ); + F32 q = brightness * ( 1 - f * saturation ); + F32 t = brightness * ( 1 - (1 - f) * saturation ); + + switch( h % 6 ) { + case 0: + c.r = brightness; c.g = t; c.b = p; + return c; + case 1: + c.r = q; c.g = brightness; c.b = p; + return c; + case 2: + c.r = p; c.g = brightness; c.b = t; + return c; + case 3: + c.r = p; c.g = q; c.b = brightness; + return c; + case 4: + c.r = t; c.g = p; c.b = brightness; + return c; + case 5: + c.r = brightness; c.g = p; c.b = q; + return c; + } + + return c; + } + + CLR operator+( const CLR& c2 ) { + return { this->r + c2.r, this->g + c2.g, this->b + c2.b, this->a + c2.a }; + } + CLR operator-( const CLR& c2 ) { + return { this->r - c2.r, this->g - c2.g, this->b - c2.b, this->a - c2.a }; + } + CLR operator*( const CLR& c2 ) { + return { this->r * c2.r, this->g * c2.g, this->b * c2.b, this->a * c2.a }; + } + CLR operator/( const CLR& c2 ) { + F32 r = (c2.r != 0.0f) ? this->r / c2.r : 0.0f; + F32 g = (c2.g != 0.0f) ? this->g / c2.g : 0.0f; + F32 b = (c2.b != 0.0f) ? this->b / c2.b : 0.0f; + F32 a = (c2.a != 0.0f) ? this->a / c2.a : 0.0f; + + return { r, g, b, a }; + } + + CLR& operator+=( const CLR& c2 ) { + r += c2.r; + g += c2.g; + b += c2.b; + a += c2.a; + return *this; + } + + CLR& operator-=( const CLR& c2 ) { + r -= c2.r; + g -= c2.g; + b -= c2.b; + a -= c2.a; + return *this; + } + + CLR& operator*=( const CLR& c2 ) { + r *= c2.r; + g *= c2.g; + b *= c2.b; + a *= c2.a; + return *this; + } + + CLR& operator/=( const CLR& c2 ) { + if( c2.r != 0.0f ) { r /= c2.r; } + else { r = 0.0f; } + + if( c2.g != 0.0f ) { g /= c2.g; } + else { g = 0.0f; } + + if( c2.b != 0.0f ) { b /= c2.b; } + else { b = 0.0f; } + + if( c2.a != 0.0f ) { a /= c2.a; } + else { a = 0.0f; } + + return *this; + } + + CLR operator*( F32 f ) { + return { r * f, g * f, b * f, a * f }; + } + + CLR operator/( F32 f ) { + if( f != 0.0f ) + return { this->r / f, this->g / f, this->b / f, this->a / f }; + else + return { 0.0f, 0.0f, 0.0f, 0.0f }; + } + + CLR& operator*=( F32 f ) { + r *= f; g *= f; b *= f; + return *this; + } + + CLR& operator/=( F32 f ) { + if( f != 0.0f ) { + r /= f; + g /= f; + b /= f; + } + else { + r = g = b = a = 0.f; + } + + return *this; + } +}; -- cgit v1.2.3