RenderManAPI  24.0
RixColorUtils.h
Go to the documentation of this file.
1 /*
2 # ------------------------------------------------------------------------------
3 #
4 # Copyright (c) 2020 Pixar. All rights reserved.
5 #
6 # The information in this file (the "Software") is provided for the exclusive
7 # use of the software licensees of Pixar ("Licensees"). Licensees have the
8 # right to incorporate the Software into other products for use by other
9 # authorized software licensees of Pixar, without fee. Except as expressly
10 # permitted herein, the Software may not be disclosed to third parties, copied
11 # or duplicated in any form, in whole or in part, without the prior written
12 # permission of Pixar.
13 #
14 # The copyright notices in the Software and this entire statement, including the
15 # above license grant, this restriction and the following disclaimer, must be
16 # included in all copies of the Software, in whole or in part, and all permitted
17 # derivative works of the Software, unless such copies or derivative works are
18 # solely in the form of machine-executable object code generated by a source
19 # language processor.
20 #
21 # PIXAR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL PIXAR BE
23 # LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
24 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
25 # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26 # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. IN NO CASE WILL
27 # PIXAR'S TOTAL LIABILITY FOR ALL DAMAGES ARISING OUT OF OR IN CONNECTION WITH
28 # THE USE OR PERFORMANCE OF THIS SOFTWARE EXCEED $50.
29 #
30 # Pixar
31 # 1200 Park Ave
32 # Emeryville CA 94608
33 #
34 # ------------------------------------------------------------------------------
35 */
36 
37 #ifndef RixColorUtils_h
38 #define RixColorUtils_h
39 
40 #include <unordered_map>
41 #include <string>
42 #include "RixShadingUtils.h" // for PRMAN_INLINE
43 #include "pxrcore/ustring/ustring.h" // for RtUString
44 
45 #define F_LOGDOTFIVE (-0.30102999566f)
46 #define F_INVLOGDOTFIVE (-3.32192809489f)
47 
49 {
50  k_sRGB = 0,
59 };
60 
61 // NOTE: All matrices assume their default illuminant (usually D65)
62 
63 // clang-format off
64 static float s_RGBtoXYZ[][9] = {
65  // sRGB D65
66  { 0.4124564f, 0.3575761f, 0.1804375f,
67  0.2126729f, 0.7151522f, 0.0721750f,
68  0.0193339f, 0.1191920f, 0.9503041f
69  },
70  // Rec.709
71  { 0.4123866f, 0.3575915f, 0.1804505f,
72  0.2126368f, 0.7151830f, 0.0721802f,
73  0.0193306f, 0.1191972f, 0.9503726f
74  },
75  // Rec.2020
76  { 0.6369535f, 0.1446192f, 0.1688559f,
77  0.2626983f, 0.6780088f, 0.0592929f,
78  0.0000000f, 0.0280731f, 1.0608272f
79  },
80  // DCI-P3
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
84  },
85  // Alexa Wide
86  { 0.638008f, 0.214704f, 0.097744f,
87  0.291954f, 0.823841f, -0.115795f,
88  0.002798f, -0.067034f, 1.153294f
89  },
90  // ACES cg
91  { 0.66245418f, 0.13400421f, 0.15618769f,
92  0.27222872f, 0.67408177f, 0.05368952f,
93  -0.00557465f, 0.00406073f, 1.0103391f
94  },
95  // Canon Cinema Gamut
96  {
97  0.71603649f, 0.12968185f, 0.10471021f,
98  0.26125656f, 0.86963121f, -0.13088776f,
99  -0.00967617f, -0.23647866f, 1.3350552f,
100  },
101  // old NTSC - for backward compatibility
102  { 1.909851f, -0.984623f, 0.058331f,
103  -0.532414f, 1.999082f, -0.118429f,
104  -0.288187f, -0.028307f, 0.897936f
105  }
106 };
107 // clang-format on
108 
109 // clang-format off
110 static float s_XYZtoRGB[][9] = {
111  // sRGB D65
112  { 3.2404542f, -1.5371385f, -0.4985314f,
113  -0.9692660f, 1.8760108f, 0.0415560f,
114  0.0556434f, -0.2040259f, 1.0572252f
115  },
116  // Rec.709 D65
117  { 3.24100326f, -1.53739899f, -0.49861587f,
118  -0.96922426f, 1.87592999f, 0.04155422f,
119  0.05563942f, -0.2040112f, 1.05714897f
120  },
121  // Rec.2020 D65
122  { 1.71666343f, -0.35567332f, -0.25336809f,
123  -0.66667384f, 1.61645574f, 0.0157683f,
124  0.01764248f, -0.04277698f, 0.94224328f
125  },
126  // DCI-P3
127  { 2.72539403f, -1.01800301f, -0.4401632f,
128  -0.79516803f, 1.68973205f, 0.02264719f,
129  0.04124189f, -0.08763902f, 1.10092938f
130  },
131  // Alexa Wide
132  { 1.78906454f, -0.48253382f, -0.20007503f,
133  -0.63984874f, 1.3964001f, 0.19443223f,
134  -0.04153097f, 0.08233496f, 0.87886816f
135  },
136  // ACES cg
137  { 1.64102338f, -0.32480329f, -0.2364247f,
138  -0.66366286f, 1.61533159f, 0.01675635f,
139  0.01172189f, -0.00828444f, 0.98839486f
140  },
141  // Canon Cinema Gamut
142  {
143  1.48984566f, -0.2609007f, -0.14242914f,
144  -0.45817234f, 1.26164365f, 0.15962564f,
145  -0.07035813f, 0.22158431f, 0.77627493f
146  },
147  // old NTSC - for backward compatibility
148  { 0.606937f, 0.298939f, 0.0f,
149  0.173509f, 0.586625f, 0.066099f,
150  0.200263f, 0.114436f, 1.115749f
151  }
152 };
153 
154 static const RtMatrix4x4 s_rgbMatrices[2][2]
155 {
156  {
157  // ITU-R BT.709 -> ITU-R BT.709 - identity
158  RtMatrix4x4(RtVector3(1.0)),
159  // ITU-R BT.709 -> ACEScg - chromatic adaptation: Bianco
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)
164  // ILM original matrix from PxrHairColor
165  // RtMatrix4x4(0.610277f , 0.0688436f , 0.0241673f, 0.0f,
166  // 0.345424f , 0.934974f , 0.121814f , 0.0f,
167  // 0.0443001f, -0.00381805f, 0.854019f , 0.0f,
168  // 0.0f, 0.0f, 0.0f, 1.0f)
169  },
170  {
171  // ACEScg -> ITU-R BT.709 - chromatic adaptation: Bianco
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),
176  // ACEScg -> ACEScg - identity
177  RtMatrix4x4(RtVector3(1.0))
178  }
179 };
180 // clang-format on
181 
183 {
184  kScene=-1,
188 };
189 
191 RixToColorSpace(const RenderColorSpace &from, const RenderColorSpace &to, const RtColorRGB &rgb)
192 {
193  if (from == to || from == RenderColorSpace::kScene || to == RenderColorSpace::kScene)
194  return rgb;
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);
197 }
198 
201 {
202  static const RtUString s_SceneOption("user:scenecolorspace");
203  static const std::unordered_map<std::string, RenderColorSpace> s_nameMap = {
204  {std::string("Rec709"), RenderColorSpace::kRec709},
205  {std::string("ACEScg"), RenderColorSpace::kACEScg}
206  };
209  if (rstate)
210  {
211  RtString sceneCS;
212  RixRenderState::Type sceneCSType;
213  int sceneCSLen = sizeof(RtString);
214  int sceneCSCount;
215  int err = rstate->GetOption(s_SceneOption, &sceneCS, sceneCSLen, &sceneCSType, &sceneCSCount);
216  if (!err)
217  {
218  try {
219  sceneColorSpace = s_nameMap.at(std::string(sceneCS));
220  }
221  catch(...) {
222  sceneColorSpace = RenderColorSpace::kRec709;
224  msgs->Error("'%s' is not a known color space (Rec709, ACEScg). Defaulting to Rec709 !", sceneCS);
225  }
226  }
227  }
228  return sceneColorSpace;
229 }
230 
231 /*
232  * RixHsvToRgb(hsv, rgb) converts a hue/saturation/value triple into an
233  * RGB triple.
234  * Based on the "hexcone" model. See A.R.Smith, Color Gamut Transform Pairs,
235  * Proc. Siggraph '78.
236  */
237 #define IFLOOR(x) (((x) < 0.0f && (x) != (int)(x)) ? (int)x - 1 : (int)x)
238 
239 PRMAN_INLINE void
241 {
242  float h, f;
243  float m, n, k;
244  int i;
245 
246  h = hsv.r;
247  h = h - static_cast<float>(static_cast<int>(h)) + (h < 0.0f ? 1.0f : 0.0f); /* h mod 1.0 */
248  h = h * 6.0f;
249  i = IFLOOR(h); /* integer part */
250  f = h - static_cast<float>(i); /* fractional part */
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)));
254 
255  switch (i)
256  { /* around the color wheel */
257  case 0:
258  default:
259  rgb.r = hsv.b;
260  rgb.g = k;
261  rgb.b = m;
262  break;
263  case 1:
264  rgb.r = n;
265  rgb.g = hsv.b;
266  rgb.b = m;
267  break;
268  case 2:
269  rgb.r = m;
270  rgb.g = hsv.b;
271  rgb.b = k;
272  break;
273  case 3:
274  rgb.r = m;
275  rgb.g = n;
276  rgb.b = hsv.b;
277  break;
278  case 4:
279  rgb.r = k;
280  rgb.g = m;
281  rgb.b = hsv.b;
282  break;
283  case 5:
284  rgb.r = hsv.b;
285  rgb.g = m;
286  rgb.b = n;
287  break;
288  }
289 }
290 
291 PRMAN_INLINE void
293 {
294  int spoke; /* part of color wheel it's in */
295  float h, s, v; /* hue, saturation & value components of HSV */
296  float x; /* smallest RGB component */
297 
298  /* set v to largest rgb component, x to smallest */
299  if (rgb.r > rgb.g)
300  {
301  if (rgb.r > rgb.b)
302  {
303  v = rgb.r;
304  spoke = 0;
305  }
306  else
307  {
308  v = rgb.b;
309  spoke = 4;
310  }
311  if (rgb.g < rgb.b)
312  {
313  x = rgb.g;
314  spoke++;
315  }
316  else
317  {
318  x = rgb.b;
319  }
320  }
321  else
322  {
323  if (rgb.g > rgb.b)
324  {
325  v = rgb.g;
326  spoke = 2;
327  }
328  else
329  {
330  v = rgb.b;
331  spoke = 4;
332  }
333  if (rgb.r < rgb.b)
334  {
335  x = rgb.r;
336  }
337  else
338  {
339  x = rgb.b;
340  spoke++;
341  }
342  }
343 
344  h = 0.0f; /* default hue is red */
345  s = 0.0f; /* default saturation is unsaturated (gray) */
346  if (v < 0.0001f) /* black */
347  goto done;
348 
349  s = (v - x) / v; /* actual saturation */
350  if (s < 0.0001f) /* gray */
351  goto done;
352 
353  /* now compute actual hue */
354  switch (spoke)
355  {
356  case 0: /* red largest, blue smallest */
357  h = 1.0f - (v - rgb.g) / (v - x);
358  break;
359 
360  case 1: /* red largest, green smallest */
361  h = 5.0f + (v - rgb.b) / (v - x);
362  break;
363 
364  case 2: /* green largest, red smallest */
365  h = 3.0f - (v - rgb.b) / (v - x);
366  break;
367 
368  case 3: /* green largest, blue smallest */
369  h = 1.0f + (v - rgb.r) / (v - x);
370  break;
371 
372  case 4: /* blue largest, red smallest */
373  h = 3.0f + (v - rgb.g) / (v - x);
374  break;
375 
376  case 5: /* blue largest, green smallest */
377  h = 5.0f - (v - rgb.r) / (v - x);
378  break;
379  }
380 done:
381  hsv.r = h * (1.0f / 6.0f);
382  hsv.g = s;
383  hsv.b = v;
384 }
385 
386 /*
387  * RixHslToRgb(hsl, rgb) converts a color in hue/saturation/lightness space into
388  * an RGB triple.
389  *
390  * Based on the HLS color model. See Foley and Van Dam, "Fundamentals of
391  * Interactive Computer Graphics", 1982.
392  *
393  * RixHslToRgb assumes h is in the range [0,1) instead of [0,360) as defined
394  * in Foley and Van Dam.
395  */
396 
397 // private function
398 PRMAN_INLINE float
399 rixValue(float n1, float n2, float hue)
400 {
401  /* hue = hue mod 1.0 */
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)
406  return (n2);
407  if (hue < (float)0.66666667)
408  return (n1 + (n2 - n1) * ((float)4.0 - hue * (float)6.0));
409  return (n1);
410 }
411 
412 PRMAN_INLINE void
414 {
415  float h, s, l;
416  float m1, m2;
417 
418  h = hsl.r;
419  s = hsl.g;
420  l = hsl.b;
421 
422  if (s == 0.0f)
423  {
424  rgb.r = rgb.g = rgb.b = l;
425  return;
426  }
427 
428  if (l <= 0.5f)
429  m2 = l * (1.0f + s);
430  else
431  m2 = l + s - l * s;
432 
433  m1 = 2.0f * l - m2;
434 
435  rgb.r = rixValue(m1, m2, h + 0.33333333f);
436  rgb.g = rixValue(m1, m2, h);
437  rgb.b = rixValue(m1, m2, h - 0.33333333f);
438 }
439 
440 PRMAN_INLINE void
442 {
443  float maxi, mini, maxmin;
444  float rc, gc, bc, hue, sat, light;
445 
446  if (rgb.r < rgb.g)
447  {
448  mini = (rgb.r < rgb.b) ? rgb.r : rgb.b;
449  maxi = (rgb.g > rgb.b) ? rgb.g : rgb.b;
450  }
451  else
452  {
453  mini = (rgb.g < rgb.b) ? rgb.g : rgb.b;
454  maxi = (rgb.r > rgb.b) ? rgb.r : rgb.b;
455  }
456  light = (maxi + mini) / 2.0f;
457 
458  if (maxi == mini)
459  hsl.r = hsl.g = 0.0f;
460  else
461  {
462  if (light < 0.5f)
463  sat = (maxi - mini) / (maxi + mini);
464  else
465  sat = (maxi - mini) / (2.0f - maxi - mini);
466 
467  maxmin = 1.0f / (maxi - mini);
468  rc = (maxi - rgb.r) * maxmin;
469  gc = (maxi - rgb.g) * maxmin;
470  bc = (maxi - rgb.b) * maxmin;
471 
472  if (rgb.r == maxi)
473  hue = bc - gc;
474  else if (rgb.g == maxi)
475  hue = 2.0f + rc - bc;
476  else
477  hue = 4.0f + gc - rc;
478 
479  hue /= 6.0f;
480  if (hue < 0.0f)
481  hue = hue + 1.0f;
482 
483  hsl.r = hue;
484  hsl.g = sat;
485  }
486  hsl.b = light;
487 }
488 
489 /*
490  * RixXyzToRgb(xyz, rgb) converts a color in CIE xyz space into a RGB triple.
491  * The functions default to sRGB but other pre-defined color spaces are
492  * available.
493  * See RixColorSpace for a full list.
494  */
495 
496 // clang-format off
497 PRMAN_INLINE void
499 {
500  if (cs < 0 || cs >= k_numColorSpaces)
501  return;
502 
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;
506 }
507 
508 PRMAN_INLINE void
510 {
511  if (cs < 0 || cs >= k_numColorSpaces)
512  return;
513 
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;
517 }
518 
529 RixInputRange(const RtFloat& f, const RtFloat& min, const RtFloat& max)
530 {
531  if (min == 0.f && max == 1.f)
532  return f;
533  if (min == max)
534  return ((f < min)? 0.f : 1.f);
535  return ((f - min) / (max - min));
536 }
537 
548 RixInputRange(const RtColorRGB& rgb, const RtFloat& min, const RtFloat& max)
549 {
550  RtColorRGB result;
551  for (int i=0; i<3; i++)
552  result[i] = RixInputRange(rgb[i], min, max);
553  return result;
554 }
555 
567 template <typename T>
569 RixInputRange(const RtColorRGB& rgb, const T& min, const T& max)
570 {
571  RtColorRGB result;
572  for (int i=0; i<3; i++)
573  result[i] = RixInputRange(rgb[i], min[i], max[i]);
574  return result;
575 }
576 
587 RixOutputRange(const RtFloat& f, const RtFloat& min, const RtFloat& max)
588 {
589  if (min == 0.f && max == 1.f)
590  return f;
591  return ((max - min) * f + min);
592 }
593 
604 RixOutputRange(const RtColorRGB& rgb, const RtFloat& min, const RtFloat& max)
605 {
606  RtColorRGB result;
607  for (int i=0; i<3; i++)
608  result[i] = RixOutputRange(rgb[i], min, max);
609  return result;
610 }
611 
623 template <typename T>
625 RixOutputRange(const RtColorRGB& rgb, const T& min, const T& max)
626 {
627  RtColorRGB result;
628  for (int i=0; i<3; i++)
629  result[i] = RixOutputRange(rgb[i], min[i], max[i]);
630  return result;
631 }
632 
642 RixExposure(float const& f, float const& e)
643 {
644  if (e != 0.0f)
645  return (f * powf(2.f, e));
646  return f;
647 }
648 
658 RixExposure(const RtColorRGB& rgb, const RtFloat& e)
659 {
660  RtColorRGB result = rgb;
661  if (e != 0.0f)
662  {
663  float exposure = powf(2.f, e);
664  result[0] *= exposure;
665  result[1] *= exposure;
666  result[2] *= exposure;
667  }
668  return result;
669 }
670 
681 template <typename T>
683 RixExposure(const RtColorRGB& rgb, const T& e)
684 {
685  RtColorRGB result;
686  result.r = RixExposure(rgb[0], e[0]);
687  result.g = RixExposure(rgb[1], e[1]);
688  result.b = RixExposure(rgb[2], e[2]);
689  return result;
690 }
691 
701 RixGamma(const RtFloat& f, const RtFloat& g)
702 {
703  if (g != 1.0f)
704  return powf(RixMax(f, 0.f), 1.f / RixMax(g, 1e-5f));
705  return f;
706 }
707 
717 RixGamma(const RtColorRGB& rgb, const RtFloat& g)
718 {
719  RtColorRGB result = rgb;
720  if (g != 1.0f)
721  {
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);
726  }
727  return result;
728 }
729 
740 template <typename T>
742 RixGamma(const RtColorRGB& rgb, const T& g)
743 {
744  RtColorRGB result;
745  result[0] = RixGamma(rgb[0], g[0]);
746  result[1] = RixGamma(rgb[1], g[1]);
747  result[2] = RixGamma(rgb[2], g[2]);
748  return result;
749 }
750 
761 RixContrast(float f, float contrast, float pivot)
762 {
763  if (contrast == 0.f || f == pivot)
764  {
765  return f;
766  }
767 
768  float result = f;
769  float C = (RixClamp(contrast, -1.f, 1.f) * 0.5f) + 0.5f;
770  C = RixMin( C, 0.999f );
771  float power = logf(1.0f - C) / F_LOGDOTFIVE;
772  if ( f < pivot )
773  {
774  result = f / pivot;
775  result = powf(result, power);
776  result *= pivot;
777  }
778  else
779  {
780  result = (f - pivot) / (1.0f - pivot);
781  result = 1.0f - powf(1.0f - result, power);
782  result *= (1.0f - pivot) + pivot;
783  }
784  return result;
785 }
786 
798 template <typename T>
800 RixContrast(const RtColorRGB& rgb, const T& contrast, const T& pivot)
801 {
802  RtColorRGB result;
803  for (int i=0; i<3; i++)
804  result[i] = RixContrast(rgb[i], contrast[i], pivot[i]);
805  return result;
806 }
807 
820  const RtFloat& hue, const RtFloat& sat, const RtFloat& val)
821 {
822  RtColorRGB tmp, result;
823  RixRgbToHsv(rgb, tmp);
824  tmp[0] = RixFractional(tmp[0] + hue);
825  tmp[1] = RixClamp(tmp[1] * sat, 0.f, 1.f);
826  tmp[2] = RixClamp(tmp[2] * val, 0.f, 1.f);
827  RixHsvToRgb(tmp, result);
828  return result;
829 }
830 
842 template <typename T>
844 RixHsvCorrect(const RtColorRGB& rgb, const T& hsv)
845 {
846  RtColorRGB tmp, result;
847  RixRgbToHsv(rgb, tmp);
848  tmp[0] = RixFractional(tmp[0] + hsv[0]);
849  tmp[1] = RixClamp(tmp[1] * hsv[1], 0.f, 1.f);
850  tmp[2] = RixClamp(tmp[2] * hsv[2], 0.f, 1.f);
851  RixHsvToRgb(tmp, result);
852  return result;
853 }
854 
865 template <typename T>
867 RixHslCorrect(const RtColorRGB& rgb, const T& hsl)
868 {
869  RtColorRGB tmp, result;
870  RixRgbToHsl(rgb, tmp);
871  tmp[0] = RixFractional(tmp[0] + hsl[0]);
872  tmp[1] = RixClamp(tmp[1] * hsl[1], 0.f, 1.f);
873  tmp[2] = RixClamp(tmp[2] * hsl[2], 0.f, 1.f);
874  RixHslToRgb(tmp, result);
875  return result;
876 }
877 
889 template <typename T>
891 RixColorClamp(const RtColorRGB& rgb, const T& min, const T& max)
892 {
893  RtColorRGB result;
894  for (int i=0; i<3; i++)
895  result[i] = RixClamp(rgb[i], min[i], max[i]);
896  return result;
897 }
898 
911 RixSaturation(const RtColorRGB& rgb, const float saturation)
912 {
913  RtColorRGB result = rgb;
914  if (saturation != 1.f)
915  {
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);
920  }
921  return result;
922 }
923 
933 PRMAN_INLINE void
934 RixSaturation(RtColorRGB& rgb, const float saturation)
935 {
936  if (saturation != 1.f)
937  {
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);
942  }
943 }
944 
945 
946 // clang-format on
947 
948 #endif // RixColorUtils_h
PRMAN_INLINE void RixHsvToRgb(RtColorRGB const &hsv, RtColorRGB &rgb)
Definition: RixColorUtils.h:240
PRMAN_INLINE RtColorRGB RixSaturation(const RtColorRGB &rgb, const float saturation)
Return the saturation-adjusted color.
Definition: RixColorUtils.h:911
PRMAN_INLINE void RixRgbToHsv(RtColorRGB const &rgb, RtColorRGB &hsv)
Definition: RixColorUtils.h:292
virtual int GetOption(RtUString const name, void *result, int resultLength, Type *resultType, int *resultCount)=0
GetAttribute, GetOption, return the current values of the named Attribute or Option.
PRMAN_INLINE RtFloat RixOutputRange(const RtFloat &f, const RtFloat &min, const RtFloat &max)
Remap a float from [0.0, 1.0] to [min, max].
Definition: RixColorUtils.h:587
Definition: RixColorUtils.h:58
pxrcore::ColorRGB RtColorRGB
Definition: RiTypesHelper.h:520
PRMAN_INLINE void RixRgbToHsl(RtColorRGB const &rgb, RtColorRGB &hsl)
Definition: RixColorUtils.h:441
PRMAN_INLINE RenderColorSpace RixGetSceneColorSpace(RixContext const &ctx)
Definition: RixColorUtils.h:200
PRMAN_INLINE RtColorRGB RixColorClamp(const RtColorRGB &rgb, const T &min, const T &max)
Clamp color : this an extensions of RixClamp.
Definition: RixColorUtils.h:891
Rix interfaces are obtained from an RixContext.
Definition: RixInterfaces.h:172
Definition: RixColorUtils.h:50
PRMAN_INLINE RtFloat RixExposure(float const &f, float const &e)
Float exposure function.
Definition: RixColorUtils.h:642
PRMAN_INLINE void RixXyzToRgb(RtColorRGB const &xyz, RtColorRGB &rgb, RixColorSpace cs=k_sRGB)
Definition: RixColorUtils.h:498
Definition: RixColorUtils.h:53
RenderColorSpace
Definition: RixColorUtils.h:182
float RtFloat
Definition: ri.h:54
Definition: RixColorUtils.h:56
An object that can be used to print warnings, errors, or info in a thread safe way from within the re...
Definition: RixInterfaces.h:242
PRMAN_INLINE void RixRgbToXyz(RtColorRGB const &rgb, RtColorRGB &xyz, RixColorSpace cs=k_sRGB)
Definition: RixColorUtils.h:509
PRMAN_INLINE RtColorRGB RixHslCorrect(const RtColorRGB &rgb, const T &hsl)
HSL color correction.
Definition: RixColorUtils.h:867
PRMAN_INLINE RtFloat RixContrast(float f, float contrast, float pivot)
Contrast float function.
Definition: RixColorUtils.h:761
#define IFLOOR(x)
Definition: RixColorUtils.h:237
PRMAN_INLINE RtFloat RixInputRange(const RtFloat &f, const RtFloat &min, const RtFloat &max)
Remap [min, max] to [0.0 to 1.0].
Definition: RixColorUtils.h:529
Definition: RixColorUtils.h:184
PRMAN_INLINE float RixMax(float x, float y)
Definition: RixShadingUtils.h:201
char * RtString
Definition: ri.h:68
Id for RixMessages interface.
Definition: RixInterfaces.h:98
virtual void Error(const char *format,...)=0
Report error/warning/info, with printf-style formatting.
virtual RixInterface * GetRixInterface(RixInterfaceId id) const =0
Get the specified interface from this context.
PRMAN_INLINE float rixValue(float n1, float n2, float hue)
Definition: RixColorUtils.h:399
#define PRMAN_INLINE
Definition: prmanapi.h:99
Definition: RixColorUtils.h:51
Definition: RixColorUtils.h:186
An interface for discovering the current state of the renderer.
Definition: RixInterfaces.h:777
Id for RixRenderState interface.
Definition: RixInterfaces.h:109
Definition: RixColorUtils.h:55
Definition: RixColorUtils.h:185
Definition: RixColorUtils.h:187
pxrcore::Matrix4x4 RtMatrix4x4
Definition: RiTypesHelper.h:74
Definition: RixColorUtils.h:57
PRMAN_INLINE RtColorRGB RixHsvCorrect(const RtColorRGB &rgb, const RtFloat &hue, const RtFloat &sat, const RtFloat &val)
HSV color correction.
Definition: RixColorUtils.h:819
PRMAN_INLINE void RixHslToRgb(RtColorRGB const &hsl, RtColorRGB &rgb)
Definition: RixColorUtils.h:413
pxrcore::UString RtUString
Definition: RiTypesHelper.h:682
Definition: RixColorUtils.h:54
PRMAN_INLINE RtColorRGB RixToColorSpace(const RenderColorSpace &from, const RenderColorSpace &to, const RtColorRGB &rgb)
Definition: RixColorUtils.h:191
PRMAN_INLINE float RixMin(float x, float y)
Definition: RixShadingUtils.h:181
PRMAN_INLINE float RixFractional(float x)
Definition: RixShadingUtils.h:241
Type
Definition: RixInterfaces.h:140
RtFloat3 RtVector3
Definition: RiTypesHelper.h:72
PRMAN_INLINE RtFloat RixGamma(const RtFloat &f, const RtFloat &g)
Float gamma correction.
Definition: RixColorUtils.h:701
Definition: RixColorUtils.h:52
#define F_LOGDOTFIVE
Definition: RixColorUtils.h:45
PRMAN_INLINE float RixClamp(float x, float min, float max)
Definition: RixShadingUtils.h:221
RixColorSpace
Definition: RixColorUtils.h:48