37 #ifndef RixColorUtils_h
38 #define RixColorUtils_h
40 #include <unordered_map>
43 #include "pxrcore/ustring/ustring.h"
45 #define F_LOGDOTFIVE (-0.30102999566f)
46 #define F_INVLOGDOTFIVE (-3.32192809489f)
64 static float s_RGBtoXYZ[][9] = {
66 { 0.4124564f, 0.3575761f, 0.1804375f,
67 0.2126729f, 0.7151522f, 0.0721750f,
68 0.0193339f, 0.1191920f, 0.9503041f
71 { 0.4123866f, 0.3575915f, 0.1804505f,
72 0.2126368f, 0.7151830f, 0.0721802f,
73 0.0193306f, 0.1191972f, 0.9503726f
76 { 0.6369535f, 0.1446192f, 0.1688559f,
77 0.2626983f, 0.6780088f, 0.0592929f,
78 0.0000000f, 0.0280731f, 1.0608272f
81 { 4.45169816e-01f, 2.77134409e-01f, 1.72282670e-01f,
82 2.09491678e-01f, 7.21595254e-01f, 6.89130679e-02f,
83 -3.63410132e-17f, 4.70605601e-02f, 9.07355394e-01f
86 { 0.638008f, 0.214704f, 0.097744f,
87 0.291954f, 0.823841f, -0.115795f,
88 0.002798f, -0.067034f, 1.153294f
91 { 0.66245418f, 0.13400421f, 0.15618769f,
92 0.27222872f, 0.67408177f, 0.05368952f,
93 -0.00557465f, 0.00406073f, 1.0103391f
97 0.71603649f, 0.12968185f, 0.10471021f,
98 0.26125656f, 0.86963121f, -0.13088776f,
99 -0.00967617f, -0.23647866f, 1.3350552f,
102 { 1.909851f, -0.984623f, 0.058331f,
103 -0.532414f, 1.999082f, -0.118429f,
104 -0.288187f, -0.028307f, 0.897936f
110 static float s_XYZtoRGB[][9] = {
112 { 3.2404542f, -1.5371385f, -0.4985314f,
113 -0.9692660f, 1.8760108f, 0.0415560f,
114 0.0556434f, -0.2040259f, 1.0572252f
117 { 3.24100326f, -1.53739899f, -0.49861587f,
118 -0.96922426f, 1.87592999f, 0.04155422f,
119 0.05563942f, -0.2040112f, 1.05714897f
122 { 1.71666343f, -0.35567332f, -0.25336809f,
123 -0.66667384f, 1.61645574f, 0.0157683f,
124 0.01764248f, -0.04277698f, 0.94224328f
127 { 2.72539403f, -1.01800301f, -0.4401632f,
128 -0.79516803f, 1.68973205f, 0.02264719f,
129 0.04124189f, -0.08763902f, 1.10092938f
132 { 1.78906454f, -0.48253382f, -0.20007503f,
133 -0.63984874f, 1.3964001f, 0.19443223f,
134 -0.04153097f, 0.08233496f, 0.87886816f
137 { 1.64102338f, -0.32480329f, -0.2364247f,
138 -0.66366286f, 1.61533159f, 0.01675635f,
139 0.01172189f, -0.00828444f, 0.98839486f
143 1.48984566f, -0.2609007f, -0.14242914f,
144 -0.45817234f, 1.26164365f, 0.15962564f,
145 -0.07035813f, 0.22158431f, 0.77627493f
148 { 0.606937f, 0.298939f, 0.0f,
149 0.173509f, 0.586625f, 0.066099f,
150 0.200263f, 0.114436f, 1.115749f
154 static const RtMatrix4x4 s_rgbMatrices[2][2]
158 RtMatrix4x4(RtVector3(1.0)),
160 RtMatrix4x4(0.612459f, 0.070664f, 0.020755f, 0.000000f,
161 0.338722f, 0.917631f, 0.106878f, 0.000000f,
162 0.048818f, 0.011705f, 0.872367f, 0.000000f,
163 0.000000f, 0.000000f, 0.000000f, 1.000000f)
172 RtMatrix4x4(1.707255f, -0.131157f, -0.024550f, 0.000000f,
173 -0.620035f, 1.139101f, -0.124805f, 0.000000f,
174 -0.087220f, -0.007944f, 1.149354f, 0.000000f,
175 0.000000f, 0.000000f, 0.000000f, 1.000000f),
177 RtMatrix4x4(RtVector3(1.0))
190 PRMAN_INLINE RtColorRGB
195 RtVector3 vec = s_rgbMatrices[
static_cast<int>(from)][static_cast<int>(to)].vTransform(RtVector3(rgb.r, rgb.g, rgb.b));
196 return RtColorRGB(vec.x, vec.y, vec.z);
202 static const RtUString s_SceneOption(
"user:scenecolorspace");
203 static const std::unordered_map<std::string, RenderColorSpace> s_nameMap = {
213 int sceneCSLen =
sizeof(RtString);
215 int err = rstate->
GetOption(s_SceneOption, &sceneCS, sceneCSLen, &sceneCSType, &sceneCSCount);
219 sceneColorSpace = s_nameMap.at(std::string(sceneCS));
224 msgs->
Error(
"'%s' is not a known color space (Rec709, ACEScg). Defaulting to Rec709 !", sceneCS);
228 return sceneColorSpace;
237 #define IFLOOR(x) (((x) < 0.0f && (x) != (int)(x)) ? (int)x - 1 : (int)x)
247 h = h -
static_cast<float>(
static_cast<int>(h)) + (h < 0.0f ? 1.0f : 0.0f);
250 f = h -
static_cast<float>(i);
251 m = hsv.b * (1.0f - hsv.g);
252 n = hsv.b * (1.0f - (hsv.g * f));
253 k = hsv.b * (1.0f - (hsv.g * (1.0f - f)));
357 h = 1.0f - (v - rgb.g) / (v - x);
361 h = 5.0f + (v - rgb.b) / (v - x);
365 h = 3.0f - (v - rgb.b) / (v - x);
369 h = 1.0f + (v - rgb.r) / (v - x);
373 h = 3.0f + (v - rgb.g) / (v - x);
377 h = 5.0f - (v - rgb.r) / (v - x);
381 hsv.r = h * (1.0f / 6.0f);
402 hue = hue - (float)(
int)hue + (hue < (float)0.0 ? (
float)1.0 : (float)0.0);
403 if (hue < (
float)0.16666667)
404 return (n1 + (n2 - n1) * hue * (
float)6.0);
405 if (hue < (
float)0.5)
407 if (hue < (
float)0.66666667)
408 return (n1 + (n2 - n1) * ((
float)4.0 - hue * (
float)6.0));
424 rgb.r = rgb.g = rgb.b = l;
435 rgb.r =
rixValue(m1, m2, h + 0.33333333f);
437 rgb.b =
rixValue(m1, m2, h - 0.33333333f);
443 float maxi, mini, maxmin;
444 float rc, gc, bc, hue, sat, light;
448 mini = (rgb.r < rgb.b) ? rgb.r : rgb.b;
449 maxi = (rgb.g > rgb.b) ? rgb.g : rgb.b;
453 mini = (rgb.g < rgb.b) ? rgb.g : rgb.b;
454 maxi = (rgb.r > rgb.b) ? rgb.r : rgb.b;
456 light = (maxi + mini) / 2.0f;
459 hsl.r = hsl.g = 0.0f;
463 sat = (maxi - mini) / (maxi + mini);
465 sat = (maxi - mini) / (2.0f - maxi - mini);
467 maxmin = 1.0f / (maxi - mini);
468 rc = (maxi - rgb.r) * maxmin;
469 gc = (maxi - rgb.g) * maxmin;
470 bc = (maxi - rgb.b) * maxmin;
474 else if (rgb.g == maxi)
475 hue = 2.0f + rc - bc;
477 hue = 4.0f + gc - rc;
503 rgb.r = s_XYZtoRGB[cs][0] * xyz.r + s_XYZtoRGB[cs][1] * xyz.g + s_XYZtoRGB[cs][2] * xyz.b;
504 rgb.g = s_XYZtoRGB[cs][3] * xyz.r + s_XYZtoRGB[cs][4] * xyz.g + s_XYZtoRGB[cs][5] * xyz.b;
505 rgb.b = s_XYZtoRGB[cs][6] * xyz.r + s_XYZtoRGB[cs][7] * xyz.g + s_XYZtoRGB[cs][8] * xyz.b;
514 xyz.r = s_RGBtoXYZ[cs][0] * rgb.r + s_RGBtoXYZ[cs][1] * rgb.g + s_RGBtoXYZ[cs][2] * rgb.b;
515 xyz.g = s_RGBtoXYZ[cs][3] * rgb.r + s_RGBtoXYZ[cs][4] * rgb.g + s_RGBtoXYZ[cs][5] * rgb.b;
516 xyz.b = s_RGBtoXYZ[cs][6] * rgb.r + s_RGBtoXYZ[cs][7] * rgb.g + s_RGBtoXYZ[cs][8] * rgb.b;
531 if (min == 0.f && max == 1.f)
534 return ((f < min)? 0.f : 1.f);
535 return ((f - min) / (max - min));
547 PRMAN_INLINE RtColorRGB
548 RixInputRange(
const RtColorRGB& rgb,
const RtFloat& min,
const RtFloat& max)
551 for (
int i=0; i<3; i++)
567 template <
typename T>
568 PRMAN_INLINE RtColorRGB
572 for (
int i=0; i<3; i++)
589 if (min == 0.f && max == 1.f)
591 return ((max - min) * f + min);
603 PRMAN_INLINE RtColorRGB
607 for (
int i=0; i<3; i++)
623 template <
typename T>
624 PRMAN_INLINE RtColorRGB
628 for (
int i=0; i<3; i++)
645 return (f * powf(2.f, e));
657 PRMAN_INLINE RtColorRGB
660 RtColorRGB result = rgb;
663 float exposure = powf(2.f, e);
664 result[0] *= exposure;
665 result[1] *= exposure;
666 result[2] *= exposure;
681 template <
typename T>
682 PRMAN_INLINE RtColorRGB
716 PRMAN_INLINE RtColorRGB
719 RtColorRGB result = rgb;
722 float safe_g = 1.f/
RixMax(g, 1e-5f);
723 result[0] = powf(rgb[0], safe_g);
724 result[1] = powf(rgb[1], safe_g);
725 result[2] = powf(rgb[2], safe_g);
740 template <
typename T>
741 PRMAN_INLINE RtColorRGB
763 if (contrast == 0.f || f == pivot)
769 float C = (
RixClamp(contrast, -1.f, 1.f) * 0.5f) + 0.5f;
775 result = powf(result, power);
780 result = (f - pivot) / (1.0f - pivot);
781 result = 1.0f - powf(1.0f - result, power);
782 result *= (1.0f - pivot) + pivot;
798 template <
typename T>
799 PRMAN_INLINE RtColorRGB
800 RixContrast(
const RtColorRGB& rgb,
const T& contrast,
const T& pivot)
803 for (
int i=0; i<3; i++)
804 result[i] =
RixContrast(rgb[i], contrast[i], pivot[i]);
818 PRMAN_INLINE RtColorRGB
820 const RtFloat& hue,
const RtFloat& sat,
const RtFloat& val)
822 RtColorRGB tmp, result;
825 tmp[1] =
RixClamp(tmp[1] * sat, 0.f, 1.f);
826 tmp[2] =
RixClamp(tmp[2] * val, 0.f, 1.f);
842 template <
typename T>
843 PRMAN_INLINE RtColorRGB
846 RtColorRGB tmp, result;
849 tmp[1] =
RixClamp(tmp[1] * hsv[1], 0.f, 1.f);
850 tmp[2] =
RixClamp(tmp[2] * hsv[2], 0.f, 1.f);
865 template <
typename T>
866 PRMAN_INLINE RtColorRGB
869 RtColorRGB tmp, result;
872 tmp[1] =
RixClamp(tmp[1] * hsl[1], 0.f, 1.f);
873 tmp[2] =
RixClamp(tmp[2] * hsl[2], 0.f, 1.f);
889 template <
typename T>
890 PRMAN_INLINE RtColorRGB
894 for (
int i=0; i<3; i++)
895 result[i] =
RixClamp(rgb[i], min[i], max[i]);
910 PRMAN_INLINE RtColorRGB
913 RtColorRGB result = rgb;
914 if (saturation != 1.f)
916 float middleGrey = (1.f -
RixMax(0.f, saturation)) * rgb.Luminance();
917 result.r =
RixMax(0.f, middleGrey + saturation * rgb.r);
918 result.g =
RixMax(0.f, middleGrey + saturation * rgb.g);
919 result.b =
RixMax(0.f, middleGrey + saturation * rgb.b);
936 if (saturation != 1.f)
938 float middleGrey = (1.f -
RixMax(0.f, saturation)) * rgb.Luminance();
939 rgb.r =
RixMax(0.f, middleGrey + saturation * rgb.r);
940 rgb.g =
RixMax(0.f, middleGrey + saturation * rgb.g);
941 rgb.b =
RixMax(0.f, middleGrey + saturation * rgb.b);
948 #endif // RixColorUtils_h