#pragma once namespace colors { glm::vec4 const none{ 0.f, 0.f, 0.f, 1.f }; glm::vec4 const white{ 1.f, 1.f, 1.f, 1.f }; glm::vec4 const shadow{ 0.25f, 0.30f, 0.35f, 1.f }; inline glm::vec3 XYZtoRGB( glm::vec3 const &XYZ ) { // M^-1 for Adobe RGB from http://www.brucelindbloom.com/Eqn_RGB_XYZ_Matrix.html float const mi[ 3 ][ 3 ] = { 2.041369f, -0.969266f, 0.0134474f, -0.5649464f, 1.8760108f, -0.1183897f, -0.3446944f, 0.041556f, 1.0154096f }; // m^-1 for sRGB: // float const mi[ 3 ][ 3 ] = { 3.240479f, -0.969256f, 0.055648f, -1.53715f, 1.875991f, -0.204043f, -0.49853f, 0.041556f, 1.057311f }; return glm::vec3{ XYZ.x*mi[ 0 ][ 0 ] + XYZ.y*mi[ 1 ][ 0 ] + XYZ.z*mi[ 2 ][ 0 ], XYZ.x*mi[ 0 ][ 1 ] + XYZ.y*mi[ 1 ][ 1 ] + XYZ.z*mi[ 2 ][ 1 ], XYZ.x*mi[ 0 ][ 2 ] + XYZ.y*mi[ 1 ][ 2 ] + XYZ.z*mi[ 2 ][ 2 ] }; } inline glm::vec3 RGBtoHSV( glm::vec3 const &RGB ) { glm::vec3 hsv; float const max = std::max( std::max( RGB.r, RGB.g ), RGB.b ); float const min = std::min( std::min( RGB.r, RGB.g ), RGB.b ); float const delta = max - min; hsv.z = max; // v if( delta < 0.00001 ) { hsv.y = 0; hsv.x = 0; // undefined, maybe nan? return hsv; } if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash hsv.y = ( delta / max ); // s } else { // if max is 0, then r = g = b = 0 // s = 0, v is undefined hsv.y = 0.0; hsv.x = NAN; // its now undefined return hsv; } if( RGB.r >= max ) // > is bogus, just keeps compilor happy hsv.x = ( RGB.g - RGB.b ) / delta; // between yellow & magenta else if( RGB.g >= max ) hsv.x = 2.f + ( RGB.g - RGB.r ) / delta; // between cyan & yellow else hsv.x = 4.f + ( RGB.r - RGB.g ) / delta; // between magenta & cyan hsv.x *= 60.0; // degrees if( hsv.x < 0.0 ) hsv.x += 360.0; return hsv; } inline glm::vec3 HSVtoRGB( glm::vec3 const &HSV ) { glm::vec3 rgb; if( HSV.y <= 0.0 ) { // < is bogus, just shuts up warnings rgb.r = HSV.z; rgb.g = HSV.z; rgb.b = HSV.z; return rgb; } float hh = HSV.x; if( hh >= 360.0 ) hh = 0.0; hh /= 60.0; int const i = (int)hh; float const ff = hh - i; float const p = HSV.z * ( 1.f - HSV.y ); float const q = HSV.z * ( 1.f - ( HSV.y * ff ) ); float const t = HSV.z * ( 1.f - ( HSV.y * ( 1.f - ff ) ) ); switch( i ) { case 0: rgb.r = HSV.z; rgb.g = t; rgb.b = p; break; case 1: rgb.r = q; rgb.g = HSV.z; rgb.b = p; break; case 2: rgb.r = p; rgb.g = HSV.z; rgb.b = t; break; case 3: rgb.r = p; rgb.g = q; rgb.b = HSV.z; break; case 4: rgb.r = t; rgb.g = p; rgb.b = HSV.z; break; case 5: default: rgb.r = HSV.z; rgb.g = p; rgb.b = q; break; } return rgb; } } // namespace colors