2#include <Video/VideoInterface.hpp>
33#define SCORE_GFX_RGB_MATRIX \
44#define SCORE_GFX_BT601_LIMITED_MATRIX \
46 1.164383561643836, 1.164383561643836, 1.164383561643836, 0.0,\n\
47 0.000000000000000, -0.391762290094914, 2.017232142857143, 0.0,\n\
48 1.596026785714286, -0.812967647237771, 0.000000000000000, 0.0,\n\
49 -0.874202217873451, 0.531667823499146, -1.085630789302022, 1.0)\n"
51#define SCORE_GFX_BT601_FULL_MATRIX \
53 1.000000000000000, 1.000000000000000, 1.000000000000000, 0.0,\n\
54 0.000000000000000, -0.344136286201022, 1.772000000000000, 0.0,\n\
55 1.402000000000000, -0.714136286201022, 0.000000000000000, 0.0,\n\
56 -0.701000000000000, 0.529136286201022, -0.886000000000000, 1.0)\n"
59#define SCORE_GFX_BT601_MATRIX SCORE_GFX_BT601_LIMITED_MATRIX
65#define SCORE_GFX_BT709_LIMITED_MATRIX \
67 1.164383561643836, 1.164383561643836, 1.164383561643836, 0.0,\n\
68 0.000000000000000, -0.213248614273730, 2.112401785714286, 0.0,\n\
69 1.792741071428571, -0.532909328559444, 0.000000000000000, 0.0,\n\
70 -0.972945075016308, 0.301482665475862, -1.133402217873451, 1.0)\n"
72#define SCORE_GFX_BT709_FULL_MATRIX \
74 1.000000000000000, 1.000000000000000, 1.000000000000000, 0.0,\n\
75 0.000000000000000, -0.187324272930649, 1.855600000000000, 0.0,\n\
76 1.574800000000000, -0.468124272930649, 0.000000000000000, 0.0,\n\
77 -0.787400000000000, 0.327724272930649, -0.927800000000000, 1.0)\n"
80#define SCORE_GFX_BT709_MATRIX SCORE_GFX_BT709_LIMITED_MATRIX
86#define SCORE_GFX_SMPTE240M_LIMITED_MATRIX \
88 1.164383561643836, 1.164383561643836, 1.164383561643836, 0.0,\n\
89 0.000000000000000, -0.256532845251675, 2.079843750000000, 0.0,\n\
90 1.793651785714286, -0.542724809537390, 0.000000000000000, 0.0,\n\
91 -0.973402217873451, 0.328136638536074, -1.117059360730594, 1.0)\n"
93#define SCORE_GFX_SMPTE240M_FULL_MATRIX \
95 1.000000000000000, 1.000000000000000, 1.000000000000000, 0.0,\n\
96 0.000000000000000, -0.225346499358335, 1.827000000000000, 0.0,\n\
97 1.575600000000000, -0.476746499358335, 0.000000000000000, 0.0,\n\
98 -0.787800000000000, 0.351046499358335, -0.913500000000000, 1.0)\n"
104#define SCORE_GFX_FCC_LIMITED_MATRIX \
106 1.164383561643836, 1.164383561643836, 1.164383561643836, 0.0,\n\
107 0.000000000000000, -0.377792070217918, 2.026339285714286, 0.0,\n\
108 1.593750000000000, -0.810381355932203, 0.000000000000000, 0.0,\n\
109 -0.873059360730594, 0.523357104160448, -1.090202217873451, 1.0)\n"
111#define SCORE_GFX_FCC_FULL_MATRIX \
113 1.000000000000000, 1.000000000000000, 1.000000000000000, 0.0,\n\
114 0.000000000000000, -0.331864406779661, 1.780000000000000, 0.0,\n\
115 1.400000000000000, -0.711864406779661, 0.000000000000000, 0.0,\n\
116 -0.700000000000000, 0.521864406779661, -0.890000000000000, 1.0)\n"
124#define SCORE_GFX_YCGCO_LIMITED_MATRIX \
126 1.164383561643836, 1.164383561643836, 1.164383561643836, 0.0,\n\
127 -1.138392857142857, 1.138392857142857, -1.138392857142857, 0.0,\n\
128 1.138392857142857, 0.000000000000000, -1.138392857142857, 0.0,\n\
129 -0.073059360730594, -0.644487932159165, 1.069797782126549, 1.0)\n"
131#define SCORE_GFX_YCGCO_FULL_MATRIX \
133 1.0, 1.0, 1.0, 0.0,\n\
134 -1.0, 1.0, -1.0, 0.0,\n\
135 1.0, 0.0, -1.0, 0.0,\n\
136 0.0, -0.5, 0.5, 1.0)\n"
144#define SCORE_GFX_BT2020_LIMITED_MATRIX \
146 1.164383561643836, 1.164383561643836, 1.164383561643836, 0.0,\n\
147 0.000000000000000, -0.187326104219343, 2.141772321428571, 0.0,\n\
148 1.678674107142857, -0.650424318505057, 0.000000000000000, 0.0,\n\
149 -0.915687932159165, 0.347458498519301, -1.148145075016308, 1.0)\n"
151#define SCORE_GFX_BT2020_FULL_MATRIX \
153 1.000000000000000, 1.000000000000000, 1.000000000000000, 0.0,\n\
154 0.000000000000000, -0.164553126843658, 1.881400000000000, 0.0,\n\
155 1.474600000000000, -0.571353126843658, 0.000000000000000, 0.0,\n\
156 -0.737300000000000, 0.367953126843658, -0.940700000000000, 1.0)\n"
163#define SCORE_GFX_CONVERT_BT601_LIMITED_TO_RGB \
164 "const mat4 conversion_matrix = " SCORE_GFX_BT601_LIMITED_MATRIX ";\n" \
165 "vec4 convert_to_rgb(vec4 tex) { return conversion_matrix * tex; }\n"
167#define SCORE_GFX_CONVERT_BT601_FULL_TO_RGB \
168 "const mat4 conversion_matrix = " SCORE_GFX_BT601_FULL_MATRIX ";\n" \
169 "vec4 convert_to_rgb(vec4 tex) { return conversion_matrix * tex; }\n"
172#define SCORE_GFX_CONVERT_BT709_LIMITED_TO_RGB \
173 "const mat4 conversion_matrix = " SCORE_GFX_BT709_LIMITED_MATRIX ";\n" \
174 "vec4 convert_to_rgb(vec4 tex) { return conversion_matrix * tex; }\n"
176#define SCORE_GFX_CONVERT_BT709_FULL_TO_RGB \
177 "const mat4 conversion_matrix = " SCORE_GFX_BT709_FULL_MATRIX ";\n" \
178 "vec4 convert_to_rgb(vec4 tex) { return conversion_matrix * tex; }\n"
181#define SCORE_GFX_CONVERT_SMPTE240M_LIMITED_TO_RGB \
182 "const mat4 conversion_matrix = " SCORE_GFX_SMPTE240M_LIMITED_MATRIX ";\n"\
183 "vec4 convert_to_rgb(vec4 tex) { return conversion_matrix * tex; }\n"
185#define SCORE_GFX_CONVERT_SMPTE240M_FULL_TO_RGB \
186 "const mat4 conversion_matrix = " SCORE_GFX_SMPTE240M_FULL_MATRIX ";\n" \
187 "vec4 convert_to_rgb(vec4 tex) { return conversion_matrix * tex; }\n"
190#define SCORE_GFX_CONVERT_FCC_LIMITED_TO_RGB \
191 "const mat4 conversion_matrix = " SCORE_GFX_FCC_LIMITED_MATRIX ";\n" \
192 "vec4 convert_to_rgb(vec4 tex) { return conversion_matrix * tex; }\n"
194#define SCORE_GFX_CONVERT_FCC_FULL_TO_RGB \
195 "const mat4 conversion_matrix = " SCORE_GFX_FCC_FULL_MATRIX ";\n" \
196 "vec4 convert_to_rgb(vec4 tex) { return conversion_matrix * tex; }\n"
199#define SCORE_GFX_CONVERT_YCGCO_LIMITED_TO_RGB \
200 "const mat4 conversion_matrix = " SCORE_GFX_YCGCO_LIMITED_MATRIX ";\n" \
201 "vec4 convert_to_rgb(vec4 tex) { return conversion_matrix * tex; }\n"
203#define SCORE_GFX_CONVERT_YCGCO_FULL_TO_RGB \
204 "const mat4 conversion_matrix = " SCORE_GFX_YCGCO_FULL_MATRIX ";\n" \
205 "vec4 convert_to_rgb(vec4 tex) { return conversion_matrix * tex; }\n"
208#define SCORE_GFX_CONVERT_BT601_TO_RGB SCORE_GFX_CONVERT_BT601_LIMITED_TO_RGB
209#define SCORE_GFX_CONVERT_BT709_TO_RGB SCORE_GFX_CONVERT_BT709_LIMITED_TO_RGB
215#define SCORE_GFX_BT2020_TO_709_MATRIX \
217 1.660491, -0.587641, -0.072850, 0.000000,\n\
218 -0.124550, 1.132900, -0.008349, 0.000000,\n\
219 -0.018151, -0.100579, 1.118730, 0.000000,\n\
220 0.000000, 0.000000, 0.000000, 1.000000\n\
223#define SCORE_GFX_BT2020_MATRIX SCORE_GFX_BT709_MATRIX
229static constexpr auto SCORE_GFX_CONVERT_BT2020_TO_RGB_HEADER = R
"_(
230const int COLOR_TRANSFER_LINEAR = 1;
231const int COLOR_TRANSFER_GAMMA_2_2 = 10;
232const int COLOR_TRANSFER_ST2084 = 6;
233const int COLOR_TRANSFER_HLG = 7;
236static constexpr auto SCORE_GFX_CONVERT_BT2020_TO_RGB_HEADER_LIMITED_RANGE = R
"_(
237const mat3 uYuvToRgbColorTransform = mat3(
238 1.1689f, 1.1689f, 1.1689f,
239 0.0000f, -0.1881f, 2.1502f,
240 1.6853f, -0.6530f, 0.0000f
243static constexpr auto SCORE_GFX_CONVERT_BT2020_TO_RGB_HEADER_FULL_RANGE = R
"_(
244const mat3 uYuvToRgbColorTransform = mat3(
245 1.0000f, 1.0000f, 1.0000f,
246 0.0000f, -0.1646f, 1.8814f,
247 1.4746f, -0.5714f, 0.0000f
250static constexpr auto SCORE_GFX_CONVERT_BT2020_TO_RGB = R
"_(
252const int uApplyHdrToSdrToneMapping = 1;
255// BT.2100 / BT.2020 HLG EOTF for one channel.
256float hlgEotfSingleChannel(float hlgChannel) {
257 const float a = 0.17883277;
258 const float b = 0.28466892;
259 const float c = 0.55991073;
260 return hlgChannel <= 0.5 ? hlgChannel * hlgChannel / 3.0
261 : (b + exp((hlgChannel - c) / a)) / 12.0;
264// BT.2100 / BT.2020 HLG EOTF.
265vec3 hlgEotf(vec3 hlgColor) {
266 return vec3(hlgEotfSingleChannel(hlgColor.r),
267 hlgEotfSingleChannel(hlgColor.g),
268 hlgEotfSingleChannel(hlgColor.b));
271// BT.2100 / BT.2020 PQ EOTF.
272vec3 pqEotf(vec3 pqColor) {
273 const float m1 = (2610.0 / 16384.0);
274 const float m2 = (2523.0 / 4096.0) * 128.0;
275 const float c1 = (3424.0 / 4096.0);
276 const float c2 = (2413.0 / 4096.0) * 32.0;
277 const float c3 = (2392.0 / 4096.0) * 32.0;
279 vec3 temp = pow(clamp(pqColor, 0.0, 1.0), 1.0 / vec3(m2));
280 temp = max(temp - c1, 0.0) / (c2 - c3 * temp);
281 return pow(temp, 1.0 / vec3(m1));
284// Applies the appropriate EOTF to convert nonlinear electrical values to linear
285// optical values. Input and output are both normalized to [0, 1].
286vec3 applyEotf(vec3 electricalColor) {
287 if (uInputColorTransfer == COLOR_TRANSFER_ST2084) {
288 return pqEotf(electricalColor);
289 } else if (uInputColorTransfer == COLOR_TRANSFER_HLG) {
290 return hlgEotf(electricalColor);
292 // Output red as an obviously visible error.
293 return vec3(1.0, 0.0, 0.0);
297// Apply the HLG BT2020 to BT709 OOTF.
298vec3 applyHlgBt2020ToBt709Ootf(vec3 linearRgbBt2020) {
299 const mat3 RGB_TO_XYZ_BT2020 =
300 mat3(0.63695805f, 0.26270021f, 0.00000000f, 0.14461690f, 0.67799807f,
301 0.02807269f, 0.16888098f, 0.05930172f, 1.06098506f);
302 const mat3 XYZ_TO_RGB_BT709 =
303 mat3(3.24096994f, -0.96924364f, 0.05563008f, -1.53738318f, 1.87596750f,
304 -0.20397696f, -0.49861076f, 0.04155506f, 1.05697151f);
305 const float hlgGamma = 1.0735674018211279;
307 vec3 linearXyzBt2020 = RGB_TO_XYZ_BT2020 * linearRgbBt2020;
308 vec3 linearXyzBt709 =
309 linearXyzBt2020 * pow(linearXyzBt2020[1], hlgGamma - 1.0);
310 vec3 linearRgbBt709 = clamp((XYZ_TO_RGB_BT709 * linearXyzBt709), 0.0, 1.0);
311 return linearRgbBt709;
314// Apply the PQ BT2020 to BT709 OOTF.
315vec3 applyPqBt2020ToBt709Ootf(vec3 linearRgbBt2020) {
316 float pqPeakLuminance = 10000.0;
317 float sdrPeakLuminance = 500.0;
319 return linearRgbBt2020 * pqPeakLuminance / sdrPeakLuminance;
322vec3 applyBt2020ToBt709Ootf(vec3 linearRgbBt2020) {
323 if (uInputColorTransfer == COLOR_TRANSFER_ST2084) {
324 return applyPqBt2020ToBt709Ootf(linearRgbBt2020);
325 } else if (uInputColorTransfer == COLOR_TRANSFER_HLG) {
326 return applyHlgBt2020ToBt709Ootf(linearRgbBt2020);
328 // Output green as an obviously visible error.
329 return vec3(0.0, 1.0, 0.0);
333// BT.2100 / BT.2020 HLG OETF for one channel.
334float hlgOetfSingleChannel(float linearChannel) {
335 const float a = 0.17883277;
336 const float b = 0.28466892;
337 const float c = 0.55991073;
339 return linearChannel <= 1.0 / 12.0 ? sqrt(3.0 * linearChannel)
340 : a * log(12.0 * linearChannel - b) + c;
343// BT.2100 / BT.2020 HLG OETF.
344vec3 hlgOetf(vec3 linearColor) {
345 return vec3(hlgOetfSingleChannel(linearColor.r),
346 hlgOetfSingleChannel(linearColor.g),
347 hlgOetfSingleChannel(linearColor.b));
350// BT.2100 / BT.2020, PQ / ST2084 OETF.
351vec3 pqOetf(vec3 linearColor) {
352 const float m1 = (2610.0 / 16384.0);
353 const float m2 = (2523.0 / 4096.0) * 128.0;
354 const float c1 = (3424.0 / 4096.0);
355 const float c2 = (2413.0 / 4096.0) * 32.0;
356 const float c3 = (2392.0 / 4096.0) * 32.0;
358 vec3 temp = pow(linearColor, vec3(m1));
359 temp = (c1 + c2 * temp) / (1.0 + c3 * temp);
360 return pow(temp, vec3(m2));
363// BT.709 gamma 2.2 OETF for one channel.
364float gamma22OetfSingleChannel(float linearChannel) {
365 return pow(linearChannel, (1.0 / 2.2));
368// BT.709 gamma 2.2 OETF.
369vec3 gamma22Oetf(vec3 linearColor) {
370 return vec3(gamma22OetfSingleChannel(linearColor.r),
371 gamma22OetfSingleChannel(linearColor.g),
372 gamma22OetfSingleChannel(linearColor.b));
375// Applies the appropriate OETF to convert linear optical signals to nonlinear
376// electrical signals. Input and output are both normalized to [0, 1].
377vec3 applyOetf(vec3 linearColor) {
378 if (uOutputColorTransfer == COLOR_TRANSFER_ST2084) {
379 return pqOetf(linearColor);
380 } else if (uOutputColorTransfer == COLOR_TRANSFER_HLG) {
381 return hlgOetf(linearColor);
382 } else if (uOutputColorTransfer == COLOR_TRANSFER_GAMMA_2_2) {
383 return gamma22Oetf(linearColor);
384 } else if (uOutputColorTransfer == COLOR_TRANSFER_LINEAR) {
387 // Output blue as an obviously visible error.
388 return vec3(0.0, 0.0, 1.0);
392vec3 yuvToRgb(vec3 yuv) {
393 const vec3 yuvOffset = vec3(0.0625, 0.5, 0.5);
394 return clamp(uYuvToRgbColorTransform * (yuv - yuvOffset), 0.0, 1.0);
397vec4 convert_to_rgb(vec4 tex) {
398 vec3 srcYuv = tex.xyz;
399 vec3 opticalColorBt2020 = applyEotf(yuvToRgb(srcYuv));
401 (uApplyHdrToSdrToneMapping == 1)
402 ? vec4(applyBt2020ToBt709Ootf(opticalColorBt2020), 1.0)
403 : vec4(opticalColorBt2020, 1.0);
404 vec4 transformedColors = opticalColor;
405 return vec4(applyOetf(transformedColors.rgb), 1.0);
411 shader.reserve(8000);
413 shader += SCORE_GFX_CONVERT_BT2020_TO_RGB_HEADER;
414 if(d.color_range == AVCOL_RANGE_MPEG)
415 shader += SCORE_GFX_CONVERT_BT2020_TO_RGB_HEADER_LIMITED_RANGE;
417 shader += SCORE_GFX_CONVERT_BT2020_TO_RGB_HEADER_FULL_RANGE;
419 if(d.color_trc == AVCOL_TRC_SMPTE2084)
420 shader +=
"const int uInputColorTransfer = COLOR_TRANSFER_ST2084; \n";
421 else if(d.color_trc == AVCOL_TRC_GAMMA22)
422 shader +=
"const int uInputColorTransfer = COLOR_TRANSFER_GAMMA_2_2; \n";
423 else if(d.color_trc == AVCOL_TRC_LINEAR)
424 shader +=
"const int uInputColorTransfer = COLOR_TRANSFER_LINEAR; \n";
425 else if(d.color_trc == AVCOL_TRC_ARIB_STD_B67)
426 shader +=
"const int uInputColorTransfer = COLOR_TRANSFER_HLG; \n";
428 shader +=
"const int uInputColorTransfer = COLOR_TRANSFER_GAMMA_2_2; \n";
430 shader +=
"const int uOutputColorTransfer = COLOR_TRANSFER_GAMMA_2_2; \n";
432 shader += SCORE_GFX_CONVERT_BT2020_TO_RGB;
443 const bool full_range = (d.color_range == AVCOL_RANGE_JPEG);
445 switch(d.color_space)
448 return "vec4 convert_to_rgb(vec4 tex) { return tex; }";
450 case AVCOL_SPC_BT709:
451 return full_range ? SCORE_GFX_CONVERT_BT709_FULL_TO_RGB
452 : SCORE_GFX_CONVERT_BT709_LIMITED_TO_RGB;
455 return full_range ? SCORE_GFX_CONVERT_FCC_FULL_TO_RGB
456 : SCORE_GFX_CONVERT_FCC_LIMITED_TO_RGB;
458 case AVCOL_SPC_BT470BG:
459 case AVCOL_SPC_SMPTE170M:
460 return full_range ? SCORE_GFX_CONVERT_BT601_FULL_TO_RGB
461 : SCORE_GFX_CONVERT_BT601_LIMITED_TO_RGB;
463 case AVCOL_SPC_SMPTE240M:
464 return full_range ? SCORE_GFX_CONVERT_SMPTE240M_FULL_TO_RGB
465 : SCORE_GFX_CONVERT_SMPTE240M_LIMITED_TO_RGB;
467 case AVCOL_SPC_YCGCO:
468 return full_range ? SCORE_GFX_CONVERT_YCGCO_FULL_TO_RGB
469 : SCORE_GFX_CONVERT_YCGCO_LIMITED_TO_RGB;
471 case AVCOL_SPC_BT2020_NCL:
472 return bt2020shader(d);
473 case AVCOL_SPC_BT2020_CL:
477 return bt2020shader(d);
478 case AVCOL_SPC_SMPTE2085:
479 return bt2020shader(d);
480 case AVCOL_SPC_CHROMA_DERIVED_NCL:
481 return bt2020shader(d);
482 case AVCOL_SPC_CHROMA_DERIVED_CL:
483 return bt2020shader(d);
484 case AVCOL_SPC_ICTCP:
485 return bt2020shader(d);
489 case AVCOL_SPC_UNSPECIFIED:
490 case AVCOL_SPC_RESERVED:
496 return full_range ? SCORE_GFX_CONVERT_BT709_FULL_TO_RGB
497 : SCORE_GFX_CONVERT_BT709_LIMITED_TO_RGB;
499 return full_range ? SCORE_GFX_CONVERT_BT601_FULL_TO_RGB
500 : SCORE_GFX_CONVERT_BT601_LIMITED_TO_RGB;
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:12