common.sh 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright 2011-2019 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include <bgfx_shader.sh>
  6. uniform vec4 u_params0;
  7. #define u_textureLod u_params0.x
  8. #define u_textureLayer u_params0.y
  9. #define u_inLinear u_params0.z
  10. #define u_ev u_params0.w
  11. uniform vec4 u_params1;
  12. #define u_outputFormat u_params1.x
  13. #define u_sdrWhiteNits u_params1.y
  14. vec3 toLinear(vec3 _rgb)
  15. {
  16. return pow(abs(_rgb), vec3_splat(2.2) );
  17. }
  18. vec3 toGamma(vec3 _rgb)
  19. {
  20. return pow(abs(_rgb), vec3_splat(1.0/2.2) );
  21. }
  22. vec3 applyExposure(vec3 _rgb)
  23. {
  24. vec3 rgb = mix(toLinear(_rgb.xyz), _rgb.xyz, u_inLinear);
  25. return (rgb * pow(2.0, u_ev) );
  26. }
  27. vec4 toEv(vec4 _color)
  28. {
  29. return vec4(toGamma(applyExposure(_color.xyz) ), _color.w);
  30. }
  31. float toSrgbGamma(float _val)
  32. {
  33. if (_val <= 0.0031308)
  34. {
  35. return 12.92 * _val;
  36. }
  37. else
  38. {
  39. return 1.055 * pow(_val, (1.0/2.4) ) - 0.055;
  40. }
  41. }
  42. vec3 toSrgbGamma(vec3 _rgb)
  43. {
  44. _rgb.x = toSrgbGamma(_rgb.x);
  45. _rgb.y = toSrgbGamma(_rgb.y);
  46. _rgb.z = toSrgbGamma(_rgb.z);
  47. return _rgb;
  48. }
  49. vec3 toXyzFromSrgb(vec3 _rgb)
  50. {
  51. mat3 toXYZ = mat3(
  52. 0.4125564, 0.3575761, 0.1804375,
  53. 0.2126729, 0.7151522, 0.0721750,
  54. 0.0193339, 0.1191920, 0.9503041
  55. );
  56. return mul(toXYZ, _rgb);
  57. }
  58. vec3 toRec2020FromXyz(vec3 _xyz)
  59. {
  60. mat3 toRec2020 = mat3(
  61. 1.7166512, -0.3556708, -0.2533663,
  62. -0.6666844, 1.6164812, 0.0157685,
  63. 0.0176399, -0.0427706, 0.9421031
  64. );
  65. return mul(toRec2020, _xyz);
  66. }
  67. vec3 toPqOetf(vec3 _color)
  68. {
  69. // reference PQ OETF will yield reference OOTF when
  70. // displayed on a reference monitor employing EOTF
  71. float m1 = 0.1593017578125;
  72. float m2 = 78.84375;
  73. float c1 = 0.8359375;
  74. float c2 = 18.8515625;
  75. float c3 = 18.6875;
  76. vec3 Ym1 = pow(_color.xyz * (1.0/10000.0), vec3_splat(m1) );
  77. _color = pow((c1 + c2*Ym1) / (vec3_splat(1.0) + c3*Ym1), vec3_splat(m2) );
  78. return _color;
  79. }
  80. vec4 toOutput(vec4 _color, float _outputFormat, float _sdrWhiteNits)
  81. {
  82. // assumed that _color is linear with sRGB/rec709 primaries
  83. // and 1.0 is SDR white point
  84. vec3 outColor = vec3_splat(0.0);
  85. if (_outputFormat < 0.5)
  86. {
  87. // output == 0 -> sRGB/rec709, apply gamma
  88. // values over 1.0 will saturate
  89. outColor = toSrgbGamma(saturate(_color.xyz));
  90. }
  91. else if (_outputFormat < 1.5)
  92. {
  93. // output == 1 -> scRGB, remains linear.
  94. // values over 1.0 will appear as HDR
  95. outColor = _color.xyz;
  96. }
  97. else if (_outputFormat < 2.5)
  98. {
  99. // output == 2 -> PQ
  100. // change primaries from sRGB/rec709 to rec2020
  101. vec3 _xyz = toXyzFromSrgb(_color.xyz);
  102. outColor = toRec2020FromXyz(_xyz);
  103. // if 1.0 is SDR white, should map to 80 nits
  104. // but that could lead to dim results as SDR
  105. // monitors tend to be brighter than standard
  106. outColor = toPqOetf(outColor * _sdrWhiteNits);
  107. }
  108. return vec4(outColor, _color.w);
  109. }