OSDN Git Service

Added Assets for main menu
[mindgames/Mindgames_main.git] / Mindgames / Library / PackageCache / com.unity.render-pipelines.core@6.9.0 / ShaderLibrary / Color.hlsl
1 #ifndef UNITY_COLOR_INCLUDED
2 #define UNITY_COLOR_INCLUDED
3
4 #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ACES.hlsl"
5
6 //-----------------------------------------------------------------------------
7 // Gamma space - Assume positive values
8 //-----------------------------------------------------------------------------
9
10 // Gamma20
11 real Gamma20ToLinear(real c)
12 {
13     return c * c;
14 }
15
16 real3 Gamma20ToLinear(real3 c)
17 {
18     return c.rgb * c.rgb;
19 }
20
21 real4 Gamma20ToLinear(real4 c)
22 {
23     return real4(Gamma20ToLinear(c.rgb), c.a);
24 }
25
26 real LinearToGamma20(real c)
27 {
28     return sqrt(c);
29 }
30
31 real3 LinearToGamma20(real3 c)
32 {
33     return sqrt(c.rgb);
34 }
35
36 real4 LinearToGamma20(real4 c)
37 {
38     return real4(LinearToGamma20(c.rgb), c.a);
39 }
40
41 // Gamma22
42 real Gamma22ToLinear(real c)
43 {
44     return PositivePow(c, 2.2);
45 }
46
47 real3 Gamma22ToLinear(real3 c)
48 {
49     return PositivePow(c.rgb, real3(2.2, 2.2, 2.2));
50 }
51
52 real4 Gamma22ToLinear(real4 c)
53 {
54     return real4(Gamma22ToLinear(c.rgb), c.a);
55 }
56
57 real LinearToGamma22(real c)
58 {
59     return PositivePow(c, 0.454545454545455);
60 }
61
62 real3 LinearToGamma22(real3 c)
63 {
64     return PositivePow(c.rgb, real3(0.454545454545455, 0.454545454545455, 0.454545454545455));
65 }
66
67 real4 LinearToGamma22(real4 c)
68 {
69     return real4(LinearToGamma22(c.rgb), c.a);
70 }
71
72 // sRGB
73 real SRGBToLinear(real c)
74 {
75     real linearRGBLo  = c / 12.92;
76     real linearRGBHi  = PositivePow((c + 0.055) / 1.055, 2.4);
77     real linearRGB    = (c <= 0.04045) ? linearRGBLo : linearRGBHi;
78     return linearRGB;
79 }
80
81 real2 SRGBToLinear(real2 c)
82 {
83     real2 linearRGBLo  = c / 12.92;
84     real2 linearRGBHi  = PositivePow((c + 0.055) / 1.055, real2(2.4, 2.4));
85     real2 linearRGB    = (c <= 0.04045) ? linearRGBLo : linearRGBHi;
86     return linearRGB;
87 }
88
89 real3 SRGBToLinear(real3 c)
90 {
91     real3 linearRGBLo  = c / 12.92;
92     real3 linearRGBHi  = PositivePow((c + 0.055) / 1.055, real3(2.4, 2.4, 2.4));
93     real3 linearRGB    = (c <= 0.04045) ? linearRGBLo : linearRGBHi;
94     return linearRGB;
95 }
96
97 real4 SRGBToLinear(real4 c)
98 {
99     return real4(SRGBToLinear(c.rgb), c.a);
100 }
101
102 real LinearToSRGB(real c)
103 {
104     real sRGBLo = c * 12.92;
105     real sRGBHi = (PositivePow(c, 1.0/2.4) * 1.055) - 0.055;
106     real sRGB   = (c <= 0.0031308) ? sRGBLo : sRGBHi;
107     return sRGB;
108 }
109
110 real2 LinearToSRGB(real2 c)
111 {
112     real2 sRGBLo = c * 12.92;
113     real2 sRGBHi = (PositivePow(c, real2(1.0/2.4, 1.0/2.4)) * 1.055) - 0.055;
114     real2 sRGB   = (c <= 0.0031308) ? sRGBLo : sRGBHi;
115     return sRGB;
116 }
117
118 real3 LinearToSRGB(real3 c)
119 {
120     real3 sRGBLo = c * 12.92;
121     real3 sRGBHi = (PositivePow(c, real3(1.0/2.4, 1.0/2.4, 1.0/2.4)) * 1.055) - 0.055;
122     real3 sRGB   = (c <= 0.0031308) ? sRGBLo : sRGBHi;
123     return sRGB;
124 }
125
126 real4 LinearToSRGB(real4 c)
127 {
128     return real4(LinearToSRGB(c.rgb), c.a);
129 }
130
131 // TODO: Seb - To verify and refit!
132 // Ref: http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
133 real FastSRGBToLinear(real c)
134 {
135     return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878);
136 }
137
138 real2 FastSRGBToLinear(real2 c)
139 {
140     return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878);
141 }
142
143 real3 FastSRGBToLinear(real3 c)
144 {
145     return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878);
146 }
147
148 real4 FastSRGBToLinear(real4 c)
149 {
150     return real4(FastSRGBToLinear(c.rgb), c.a);
151 }
152
153 real FastLinearToSRGB(real c)
154 {
155     return saturate(1.055 * PositivePow(c, 0.416666667) - 0.055);
156 }
157
158 real2 FastLinearToSRGB(real2 c)
159 {
160     return saturate(1.055 * PositivePow(c, 0.416666667) - 0.055);
161 }
162
163 real3 FastLinearToSRGB(real3 c)
164 {
165     return saturate(1.055 * PositivePow(c, 0.416666667) - 0.055);
166 }
167
168 real4 FastLinearToSRGB(real4 c)
169 {
170     return real4(FastLinearToSRGB(c.rgb), c.a);
171 }
172
173 //-----------------------------------------------------------------------------
174 // Color space
175 //-----------------------------------------------------------------------------
176
177 // Convert rgb to luminance
178 // with rgb in linear space with sRGB primaries and D65 white point
179 real Luminance(real3 linearRgb)
180 {
181     return dot(linearRgb, real3(0.2126729, 0.7151522, 0.0721750));
182 }
183
184 real Luminance(real4 linearRgba)
185 {
186     return Luminance(linearRgba.rgb);
187 }
188
189 real AcesLuminance(real3 linearRgb)
190 {
191     return dot(linearRgb, AP1_RGB2Y);
192 }
193
194 real AcesLuminance(real4 linearRgba)
195 {
196     return AcesLuminance(linearRgba.rgb);
197 }
198
199 // Scotopic luminance approximation - input is in XYZ space
200 // Note: the range of values returned is approximately [0;4]
201 // "A spatial postprocessing algorithm for images of night scenes"
202 // William B. Thompson, Peter Shirley, and James A. Ferwerda
203 real ScotopicLuminance(real3 xyzRgb)
204 {
205     float X = xyzRgb.x;
206     float Y = xyzRgb.y;
207     float Z = xyzRgb.z;
208     return Y * (1.33 * (1.0 + (Y + Z) / X) - 1.68);
209 }
210
211 real ScotopicLuminance(real4 xyzRgba)
212 {
213     return ScotopicLuminance(xyzRgba.rgb);
214 }
215
216 // This function take a rgb color (best is to provide color in sRGB space)
217 // and return a YCoCg color in [0..1] space for 8bit (An offset is apply in the function)
218 // Ref: http://www.nvidia.com/object/real-time-ycocg-dxt-compression.html
219 #define YCOCG_CHROMA_BIAS (128.0 / 255.0)
220 real3 RGBToYCoCg(real3 rgb)
221 {
222     real3 YCoCg;
223     YCoCg.x = dot(rgb, real3(0.25, 0.5, 0.25));
224     YCoCg.y = dot(rgb, real3(0.5, 0.0, -0.5)) + YCOCG_CHROMA_BIAS;
225     YCoCg.z = dot(rgb, real3(-0.25, 0.5, -0.25)) + YCOCG_CHROMA_BIAS;
226
227     return YCoCg;
228 }
229
230 real3 YCoCgToRGB(real3 YCoCg)
231 {
232     real Y = YCoCg.x;
233     real Co = YCoCg.y - YCOCG_CHROMA_BIAS;
234     real Cg = YCoCg.z - YCOCG_CHROMA_BIAS;
235
236     real3 rgb;
237     rgb.r = Y + Co - Cg;
238     rgb.g = Y + Cg;
239     rgb.b = Y - Co - Cg;
240
241     return rgb;
242 }
243
244 // Following function can be use to reconstruct chroma component for a checkboard YCoCg pattern
245 // Reference: The Compact YCoCg Frame Buffer
246 real YCoCgCheckBoardEdgeFilter(real centerLum, real2 a0, real2 a1, real2 a2, real2 a3)
247 {
248     real4 lum = real4(a0.x, a1.x, a2.x, a3.x);
249     // Optimize: real4 w = 1.0 - step(30.0 / 255.0, abs(lum - centerLum));
250     real4 w = 1.0 - saturate((abs(lum.xxxx - centerLum) - 30.0 / 255.0) * HALF_MAX);
251     real W = w.x + w.y + w.z + w.w;
252     // handle the special case where all the weights are zero.
253     return  (W == 0.0) ? a0.y : (w.x * a0.y + w.y* a1.y + w.z* a2.y + w.w * a3.y) / W;
254 }
255
256 // Converts linear RGB to LMS
257 real3 LinearToLMS(real3 x)
258 {
259     const real3x3 LIN_2_LMS_MAT = {
260         3.90405e-1, 5.49941e-1, 8.92632e-3,
261         7.08416e-2, 9.63172e-1, 1.35775e-3,
262         2.31082e-2, 1.28021e-1, 9.36245e-1
263     };
264
265     return mul(LIN_2_LMS_MAT, x);
266 }
267
268 real3 LMSToLinear(real3 x)
269 {
270     const real3x3 LMS_2_LIN_MAT = {
271         2.85847e+0, -1.62879e+0, -2.48910e-2,
272         -2.10182e-1,  1.15820e+0,  3.24281e-4,
273         -4.18120e-2, -1.18169e-1,  1.06867e+0
274     };
275
276     return mul(LMS_2_LIN_MAT, x);
277 }
278
279 // Hue, Saturation, Value
280 // Ranges:
281 //  Hue [0.0, 1.0]
282 //  Sat [0.0, 1.0]
283 //  Lum [0.0, HALF_MAX]
284 real3 RgbToHsv(real3 c)
285 {
286     const real4 K = real4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
287     real4 p = lerp(real4(c.bg, K.wz), real4(c.gb, K.xy), step(c.b, c.g));
288     real4 q = lerp(real4(p.xyw, c.r), real4(c.r, p.yzx), step(p.x, c.r));
289     real d = q.x - min(q.w, q.y);
290     const real e = 1.0e-4;
291     return real3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
292 }
293
294 real3 HsvToRgb(real3 c)
295 {
296     const real4 K = real4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
297     real3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
298     return c.z * lerp(K.xxx, saturate(p - K.xxx), c.y);
299 }
300
301 real RotateHue(real value, real low, real hi)
302 {
303     return (value < low)
304             ? value + hi
305             : (value > hi)
306                 ? value - hi
307                 : value;
308 }
309
310 // SMPTE ST.2084 (PQ) transfer functions
311 // 1.0 = 100nits, 100.0 = 10knits
312 #define DEFAULT_MAX_PQ 100.0
313
314 struct ParamsPQ
315 {
316     real N, M;
317     real C1, C2, C3;
318 };
319
320 static const ParamsPQ PQ =
321 {
322     2610.0 / 4096.0 / 4.0,   // N
323     2523.0 / 4096.0 * 128.0, // M
324     3424.0 / 4096.0,         // C1
325     2413.0 / 4096.0 * 32.0,  // C2
326     2392.0 / 4096.0 * 32.0,  // C3
327 };
328
329 real3 LinearToPQ(real3 x, real maxPQValue)
330 {
331     x = PositivePow(x / maxPQValue, PQ.N);
332     real3 nd = (PQ.C1 + PQ.C2 * x) / (1.0 + PQ.C3 * x);
333     return PositivePow(nd, PQ.M);
334 }
335
336 real3 LinearToPQ(real3 x)
337 {
338     return LinearToPQ(x, DEFAULT_MAX_PQ);
339 }
340
341 real3 PQToLinear(real3 x, real maxPQValue)
342 {
343     x = PositivePow(x, rcp(PQ.M));
344     real3 nd = max(x - PQ.C1, 0.0) / (PQ.C2 - (PQ.C3 * x));
345     return PositivePow(nd, rcp(PQ.N)) * maxPQValue;
346 }
347
348 real3 PQToLinear(real3 x)
349 {
350     return PQToLinear(x, DEFAULT_MAX_PQ);
351 }
352
353 // Alexa LogC converters (El 1000)
354 // See http://www.vocas.nl/webfm_send/964
355 // Max range is ~58.85666
356
357 // Set to 1 to use more precise but more expensive log/linear conversions. I haven't found a proper
358 // use case for the high precision version yet so I'm leaving this to 0.
359 #define USE_PRECISE_LOGC 0
360
361 struct ParamsLogC
362 {
363     real cut;
364     real a, b, c, d, e, f;
365 };
366
367 static const ParamsLogC LogC =
368 {
369     0.011361, // cut
370     5.555556, // a
371     0.047996, // b
372     0.244161, // c
373     0.386036, // d
374     5.301883, // e
375     0.092819  // f
376 };
377
378 real LinearToLogC_Precise(real x)
379 {
380     real o;
381     if (x > LogC.cut)
382         o = LogC.c * log10(LogC.a * x + LogC.b) + LogC.d;
383     else
384         o = LogC.e * x + LogC.f;
385     return o;
386 }
387
388 real3 LinearToLogC(real3 x)
389 {
390 #if USE_PRECISE_LOGC
391     return real3(
392         LinearToLogC_Precise(x.x),
393         LinearToLogC_Precise(x.y),
394         LinearToLogC_Precise(x.z)
395     );
396 #else
397     return LogC.c * log10(LogC.a * x + LogC.b) + LogC.d;
398 #endif
399 }
400
401 real LogCToLinear_Precise(real x)
402 {
403     real o;
404     if (x > LogC.e * LogC.cut + LogC.f)
405         o = (pow(10.0, (x - LogC.d) / LogC.c) - LogC.b) / LogC.a;
406     else
407         o = (x - LogC.f) / LogC.e;
408     return o;
409 }
410
411 real3 LogCToLinear(real3 x)
412 {
413 #if USE_PRECISE_LOGC
414     return real3(
415         LogCToLinear_Precise(x.x),
416         LogCToLinear_Precise(x.y),
417         LogCToLinear_Precise(x.z)
418     );
419 #else
420     return (pow(10.0, (x - LogC.d) / LogC.c) - LogC.b) / LogC.a;
421 #endif
422 }
423
424 //-----------------------------------------------------------------------------
425 // Utilities
426 //-----------------------------------------------------------------------------
427
428 // Fast reversible tonemapper
429 // http://gpuopen.com/optimized-reversible-tonemapper-for-resolve/
430 real FastTonemapPerChannel(real c)
431 {
432     return c * rcp(c + 1.0);
433 }
434
435 real2 FastTonemapPerChannel(real2 c)
436 {
437     return c * rcp(c + 1.0);
438 }
439
440 real3 FastTonemap(real3 c)
441 {
442     return c * rcp(Max3(c.r, c.g, c.b) + 1.0);
443 }
444
445 real4 FastTonemap(real4 c)
446 {
447     return real4(FastTonemap(c.rgb), c.a);
448 }
449
450 real3 FastTonemap(real3 c, real w)
451 {
452     return c * (w * rcp(Max3(c.r, c.g, c.b) + 1.0));
453 }
454
455 real4 FastTonemap(real4 c, real w)
456 {
457     return real4(FastTonemap(c.rgb, w), c.a);
458 }
459
460 real FastTonemapPerChannelInvert(real c)
461 {
462     return c * rcp(1.0 - c);
463 }
464
465 real2 FastTonemapPerChannelInvert(real2 c)
466 {
467     return c * rcp(1.0 - c);
468 }
469
470 real3 FastTonemapInvert(real3 c)
471 {
472     return c * rcp(1.0 - Max3(c.r, c.g, c.b));
473 }
474
475 real4 FastTonemapInvert(real4 c)
476 {
477     return real4(FastTonemapInvert(c.rgb), c.a);
478 }
479
480 #ifndef SHADER_API_GLES
481 // 3D LUT grading
482 // scaleOffset = (1 / lut_size, lut_size - 1)
483 real3 ApplyLut3D(TEXTURE3D_PARAM(tex, samplerTex), real3 uvw, real2 scaleOffset)
484 {    
485     uvw.xyz = uvw.xyz * scaleOffset.yyy * scaleOffset.xxx + scaleOffset.xxx * 0.5;
486     return SAMPLE_TEXTURE3D_LOD(tex, samplerTex, uvw, 0.0).rgb;
487 }
488 #endif
489
490 // 2D LUT grading
491 // scaleOffset = (1 / lut_width, 1 / lut_height, lut_height - 1)
492 real3 ApplyLut2D(TEXTURE2D_PARAM(tex, samplerTex), real3 uvw, real3 scaleOffset)
493 {
494     // Strip format where `height = sqrt(width)`
495     uvw.z *= scaleOffset.z;
496     real shift = floor(uvw.z);
497     uvw.xy = uvw.xy * scaleOffset.z * scaleOffset.xy + scaleOffset.xy * 0.5;
498     uvw.x += shift * scaleOffset.y;
499     uvw.xyz = lerp(
500         SAMPLE_TEXTURE2D_LOD(tex, samplerTex, uvw.xy, 0.0).rgb,
501         SAMPLE_TEXTURE2D_LOD(tex, samplerTex, uvw.xy + real2(scaleOffset.y, 0.0), 0.0).rgb,
502         uvw.z - shift
503     );
504     return uvw;
505 }
506
507 // Returns the default value for a given position on a 2D strip-format color lookup table
508 // params = (lut_height, 0.5 / lut_width, 0.5 / lut_height, lut_height / lut_height - 1)
509 real3 GetLutStripValue(real2 uv, real4 params)
510 {
511     uv -= params.yz;
512     real3 color;
513     color.r = frac(uv.x * params.x);
514     color.b = uv.x - color.r / params.x;
515     color.g = uv.y;
516     return color * params.w;
517 }
518
519 // Neutral tonemapping (Hable/Hejl/Frostbite)
520 // Input is linear RGB
521 real3 NeutralCurve(real3 x, real a, real b, real c, real d, real e, real f)
522 {
523     return ((x * (a * x + c * b) + d * e) / (x * (a * x + b) + d * f)) - e / f;
524 }
525
526 real3 NeutralTonemap(real3 x)
527 {
528     // Tonemap
529     const real a = 0.2;
530     const real b = 0.29;
531     const real c = 0.24;
532     const real d = 0.272;
533     const real e = 0.02;
534     const real f = 0.3;
535     const real whiteLevel = 5.3;
536     const real whiteClip = 1.0;
537
538     real3 whiteScale = (1.0).xxx / NeutralCurve(whiteLevel, a, b, c, d, e, f);
539     x = NeutralCurve(x * whiteScale, a, b, c, d, e, f);
540     x *= whiteScale;
541
542     // Post-curve white point adjustment
543     x /= whiteClip.xxx;
544
545     return x;
546 }
547
548 // Raw, unoptimized version of John Hable's artist-friendly tone curve
549 // Input is linear RGB
550 real EvalCustomSegment(real x, real4 segmentA, real2 segmentB)
551 {
552     const real kOffsetX = segmentA.x;
553     const real kOffsetY = segmentA.y;
554     const real kScaleX  = segmentA.z;
555     const real kScaleY  = segmentA.w;
556     const real kLnA     = segmentB.x;
557     const real kB       = segmentB.y;
558
559     real x0 = (x - kOffsetX) * kScaleX;
560     real y0 = (x0 > 0.0) ? exp(kLnA + kB * log(x0)) : 0.0;
561     return y0 * kScaleY + kOffsetY;
562 }
563
564 real EvalCustomCurve(real x, real3 curve, real4 toeSegmentA, real2 toeSegmentB, real4 midSegmentA, real2 midSegmentB, real4 shoSegmentA, real2 shoSegmentB)
565 {
566     real4 segmentA;
567     real2 segmentB;
568
569     if (x < curve.y)
570     {
571         segmentA = toeSegmentA;
572         segmentB = toeSegmentB;
573     }
574     else if (x < curve.z)
575     {
576         segmentA = midSegmentA;
577         segmentB = midSegmentB;
578     }
579     else
580     {
581         segmentA = shoSegmentA;
582         segmentB = shoSegmentB;
583     }
584
585     return EvalCustomSegment(x, segmentA, segmentB);
586 }
587
588 // curve: x: inverseWhitePoint, y: x0, z: x1
589 real3 CustomTonemap(real3 x, real3 curve, real4 toeSegmentA, real2 toeSegmentB, real4 midSegmentA, real2 midSegmentB, real4 shoSegmentA, real2 shoSegmentB)
590 {
591     real3 normX = x * curve.x;
592     real3 ret;
593     ret.x = EvalCustomCurve(normX.x, curve, toeSegmentA, toeSegmentB, midSegmentA, midSegmentB, shoSegmentA, shoSegmentB);
594     ret.y = EvalCustomCurve(normX.y, curve, toeSegmentA, toeSegmentB, midSegmentA, midSegmentB, shoSegmentA, shoSegmentB);
595     ret.z = EvalCustomCurve(normX.z, curve, toeSegmentA, toeSegmentB, midSegmentA, midSegmentB, shoSegmentA, shoSegmentB);
596     return ret;
597 }
598
599 // Filmic tonemapping (ACES fitting, unless TONEMAPPING_USE_FULL_ACES is set to 1)
600 // Input is ACES2065-1 (AP0 w/ linear encoding)
601 #define TONEMAPPING_USE_FULL_ACES 0
602
603 float3 AcesTonemap(float3 aces)
604 {
605 #if TONEMAPPING_USE_FULL_ACES
606
607     float3 oces = RRT(aces);
608     float3 odt = ODT_RGBmonitor_100nits_dim(oces);
609     return odt;
610
611 #else
612
613     // --- Glow module --- //
614     float saturation = rgb_2_saturation(aces);
615     float ycIn = rgb_2_yc(aces);
616     float s = sigmoid_shaper((saturation - 0.4) / 0.2);
617     float addedGlow = 1.0 + glow_fwd(ycIn, RRT_GLOW_GAIN * s, RRT_GLOW_MID);
618     aces *= addedGlow;
619
620     // --- Red modifier --- //
621     float hue = rgb_2_hue(aces);
622     float centeredHue = center_hue(hue, RRT_RED_HUE);
623     float hueWeight;
624     {
625         //hueWeight = cubic_basis_shaper(centeredHue, RRT_RED_WIDTH);
626         hueWeight = smoothstep(0.0, 1.0, 1.0 - abs(2.0 * centeredHue / RRT_RED_WIDTH));
627         hueWeight *= hueWeight;
628     }
629
630     aces.r += hueWeight * saturation * (RRT_RED_PIVOT - aces.r) * (1.0 - RRT_RED_SCALE);
631
632     // --- ACES to RGB rendering space --- //
633     float3 acescg = max(0.0, ACES_to_ACEScg(aces));
634
635     // --- Global desaturation --- //
636     //acescg = mul(RRT_SAT_MAT, acescg);
637     acescg = lerp(dot(acescg, AP1_RGB2Y).xxx, acescg, RRT_SAT_FACTOR.xxx);
638
639     // Luminance fitting of *RRT.a1.0.3 + ODT.Academy.RGBmonitor_100nits_dim.a1.0.3*.
640     // https://github.com/colour-science/colour-unity/blob/master/Assets/Colour/Notebooks/CIECAM02_Unity.ipynb
641     // RMSE: 0.0012846272106
642     const float a = 278.5085;
643     const float b = 10.7772;
644     const float c = 293.6045;
645     const float d = 88.7122;
646     const float e = 80.6889;
647     float3 x = acescg;
648     float3 rgbPost = (x * (a * x + b)) / (x * (c * x + d) + e);
649
650     // Scale luminance to linear code value
651     // float3 linearCV = Y_2_linCV(rgbPost, CINEMA_WHITE, CINEMA_BLACK);
652
653     // Apply gamma adjustment to compensate for dim surround
654     float3 linearCV = darkSurround_to_dimSurround(rgbPost);
655
656     // Apply desaturation to compensate for luminance difference
657     //linearCV = mul(ODT_SAT_MAT, color);
658     linearCV = lerp(dot(linearCV, AP1_RGB2Y).xxx, linearCV, ODT_SAT_FACTOR.xxx);
659
660     // Convert to display primary encoding
661     // Rendering space RGB to XYZ
662     float3 XYZ = mul(AP1_2_XYZ_MAT, linearCV);
663
664     // Apply CAT from ACES white point to assumed observer adapted white point
665     XYZ = mul(D60_2_D65_CAT, XYZ);
666
667     // CIE XYZ to display primaries
668     linearCV = mul(XYZ_2_REC709_MAT, XYZ);
669
670     return linearCV;
671
672 #endif
673 }
674
675 #endif // UNITY_COLOR_INCLUDED