File: color.effect

package info (click to toggle)
obs-studio 29.0.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 35,920 kB
  • sloc: ansic: 182,921; cpp: 98,959; sh: 1,591; python: 945; makefile: 858; javascript: 19
file content (173 lines) | stat: -rw-r--r-- 5,395 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
float srgb_linear_to_nonlinear_channel(float u)
{
	return (u <= 0.0031308) ? (12.92 * u) : ((1.055 * pow(u, 1. / 2.4)) - 0.055);
}

float3 srgb_linear_to_nonlinear(float3 v)
{
	return float3(srgb_linear_to_nonlinear_channel(v.r), srgb_linear_to_nonlinear_channel(v.g), srgb_linear_to_nonlinear_channel(v.b));
}

float srgb_nonlinear_to_linear_channel(float u)
{
	return (u <= 0.04045) ? (u / 12.92) : pow((u + 0.055) / 1.055, 2.4);
}

float3 srgb_nonlinear_to_linear(float3 v)
{
	return float3(srgb_nonlinear_to_linear_channel(v.r), srgb_nonlinear_to_linear_channel(v.g), srgb_nonlinear_to_linear_channel(v.b));
}

float3 rec709_to_rec2020(float3 v)
{
	float r = dot(v, float3(0.62740389593469903, 0.32928303837788370, 0.043313065687417225));
	float g = dot(v, float3(0.069097289358232075, 0.91954039507545871, 0.011362315566309178));
	float b = dot(v, float3(0.016391438875150280, 0.088013307877225749, 0.89559525324762401));
	return float3(r, g, b);
}

float3 d65p3_to_rec709(float3 v)
{
	float r = dot(v, float3(1.2249401762805598, -0.22494017628055996, 0.));
	float g = dot(v, float3(-0.042056954709688163, 1.0420569547096881, 0.));
	float b = dot(v, float3(-0.019637554590334432, -0.078636045550631889, 1.0982736001409663));
	return float3(r, g, b);
}

float3 rec2020_to_rec709(float3 v)
{
	float r = dot(v, float3(1.6604910021084345, -0.58764113878854951, -0.072849863319884883));
	float g = dot(v, float3(-0.12455047452159074, 1.1328998971259603, -0.0083494226043694768));
	float b = dot(v, float3(-0.018150763354905303, -0.10057889800800739, 1.1187296613629127));
	return float3(r, g, b);
}

float reinhard_channel(float x)
{
	return x / (x + 1.);
}

float3 reinhard(float3 rgb)
{
	return float3(reinhard_channel(rgb.r), reinhard_channel(rgb.g), reinhard_channel(rgb.b));
}

float linear_to_st2084_channel(float x)
{
	float c = pow(abs(x), 0.1593017578);
	return pow((0.8359375 + 18.8515625 * c) / (1. + 18.6875 * c), 78.84375);
}

float3 linear_to_st2084(float3 rgb)
{
	return float3(linear_to_st2084_channel(rgb.r), linear_to_st2084_channel(rgb.g), linear_to_st2084_channel(rgb.b));
}

float st2084_to_linear_channel(float u)
{
	float c = pow(abs(u), 1. / 78.84375);
	return pow(abs(max(c - 0.8359375, 0.) / (18.8515625 - 18.6875 * c)), 1. / 0.1593017578);
}

float3 st2084_to_linear(float3 rgb)
{
	return float3(st2084_to_linear_channel(rgb.r), st2084_to_linear_channel(rgb.g), st2084_to_linear_channel(rgb.b));
}

float eetf_0_Lmax(float maxRGB1_pq, float Lw, float Lmax)
{
	float Lw_pq = linear_to_st2084_channel(Lw / 10000.);
	float E1 = saturate(maxRGB1_pq / Lw_pq); // Ensure normalization in case Lw is a lie
	float maxLum = linear_to_st2084_channel(Lmax / 10000.) / Lw_pq;
	float KS = (1.5 * maxLum) - 0.5;
	float E2 = E1;
	if (E1 > KS)
	{
		float T = (E1 - KS) / (1. - KS);
		float Tsquared = T * T;
		float Tcubed = Tsquared * T;
		float P = (2. * Tcubed - 3. * Tsquared + 1.) * KS + (Tcubed - 2. * Tsquared + T) * (1. - KS) + (-2. * Tcubed + 3. * Tsquared) * maxLum;
		E2 = P;
	}
	float E3 = E2;
	float E4 = E3 * Lw_pq;
	return E4;
}

float3 maxRGB_eetf_internal(float3 rgb_linear, float maxRGB1_linear, float maxRGB1_pq, float Lw, float Lmax)
{
	float maxRGB2_pq = eetf_0_Lmax(maxRGB1_pq, Lw, Lmax);
	float maxRGB2_linear = st2084_to_linear_channel(maxRGB2_pq);

	// avoid divide-by-zero possibility
	maxRGB1_linear = max(6.10352e-5, maxRGB1_linear);

	rgb_linear *= maxRGB2_linear / maxRGB1_linear;
	return rgb_linear;
}

float3 maxRGB_eetf_pq_to_linear(float3 rgb_pq, float Lw, float Lmax)
{
	float3 rgb_linear = st2084_to_linear(rgb_pq);
	float maxRGB1_linear = max(max(rgb_linear.r, rgb_linear.g), rgb_linear.b);
	float maxRGB1_pq = max(max(rgb_pq.r, rgb_pq.g), rgb_pq.b);
	return maxRGB_eetf_internal(rgb_linear, maxRGB1_linear, maxRGB1_pq, Lw, Lmax);
}

float3 maxRGB_eetf_linear_to_linear(float3 rgb_linear, float Lw, float Lmax)
{
	float maxRGB1_linear = max(max(rgb_linear.r, rgb_linear.g), rgb_linear.b);
	float maxRGB1_pq = linear_to_st2084_channel(maxRGB1_linear);
	return maxRGB_eetf_internal(rgb_linear, maxRGB1_linear, maxRGB1_pq, Lw, Lmax);
}

float3 st2084_to_linear_eetf(float3 rgb, float Lw, float Lmax)
{
	return (Lw > Lmax) ? maxRGB_eetf_pq_to_linear(rgb, Lw, Lmax) : st2084_to_linear(rgb);
}

float linear_to_hlg_channel(float u)
{
	float ln2_i = 1. / log(2.);
	float m = 0.17883277 / ln2_i;
	return (u <= (1. / 12.)) ? sqrt(3. * u) : ((log2((12. * u) - 0.28466892) * m) + 0.55991073);
}

float3 linear_to_hlg(float3 rgb, float Lw)
{
	rgb = saturate(rgb);

	if (Lw > 1000.)
	{
		rgb = maxRGB_eetf_linear_to_linear(rgb, Lw, 1000.);
		rgb *= 10000. / Lw;
	}
	else
	{
		rgb *= 10.;
	}

	float Yd = dot(rgb, float3(0.2627, 0.678, 0.0593));

	// pow(0., exponent) can lead to NaN, use smallest positive normal number
	Yd = max(6.10352e-5, Yd);

	rgb *= pow(Yd, -1. / 6.);
	return float3(linear_to_hlg_channel(rgb.r), linear_to_hlg_channel(rgb.g), linear_to_hlg_channel(rgb.b));
}

float hlg_to_linear_channel(float u)
{
	float ln2_i = 1. / log(2.);
	float m = ln2_i / 0.17883277;
	float a = -ln2_i * 0.55991073 / 0.17883277;
	return (u <= 0.5) ? ((u * u) / 3.) : ((exp2(u * m + a) + 0.28466892) / 12.);
}

float3 hlg_to_linear(float3 v, float exponent)
{
	float3 rgb = float3(hlg_to_linear_channel(v.r), hlg_to_linear_channel(v.g), hlg_to_linear_channel(v.b));
	float Ys = dot(rgb, float3(0.2627, 0.678, 0.0593));
	rgb *= pow(Ys, exponent);
	return rgb;
}