#pragma once #include "string.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; } }; inline STR to_str( CLR c ) { return STR( "%.02f %.02f %.02f %.02f", c.r, c.g, c.b, c.a ); }