VULKAN_PixelShader_Common.hlsli 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. SamplerState sampler0 : register(s0);
  2. Texture2D texture0 : register(t0);
  3. struct PixelShaderInput
  4. {
  5. float4 pos : SV_POSITION;
  6. float2 tex : TEXCOORD0;
  7. float4 color : COLOR0;
  8. };
  9. // These should mirror the definitions in SDL_render_vulkan.c
  10. static const float TONEMAP_NONE = 0;
  11. static const float TONEMAP_LINEAR = 1;
  12. static const float TONEMAP_CHROME = 2;
  13. static const float INPUTTYPE_UNSPECIFIED = 0;
  14. static const float INPUTTYPE_SRGB = 1;
  15. static const float INPUTTYPE_SCRGB = 2;
  16. static const float INPUTTYPE_HDR10 = 3;
  17. cbuffer Constants : register(b1)
  18. {
  19. float scRGB_output;
  20. float input_type;
  21. float color_scale;
  22. float unused_pad0;
  23. float tonemap_method;
  24. float tonemap_factor1;
  25. float tonemap_factor2;
  26. float sdr_white_point;
  27. };
  28. static const float3x3 mat709to2020 = {
  29. { 0.627404, 0.329283, 0.043313 },
  30. { 0.069097, 0.919541, 0.011362 },
  31. { 0.016391, 0.088013, 0.895595 }
  32. };
  33. static const float3x3 mat2020to709 = {
  34. { 1.660496, -0.587656, -0.072840 },
  35. { -0.124547, 1.132895, -0.008348 },
  36. { -0.018154, -0.100597, 1.118751 }
  37. };
  38. float sRGBtoLinear(float v)
  39. {
  40. if (v <= 0.04045) {
  41. v = (v / 12.92);
  42. } else {
  43. v = pow(abs(v + 0.055) / 1.055, 2.4);
  44. }
  45. return v;
  46. }
  47. float sRGBfromLinear(float v)
  48. {
  49. if (v <= 0.0031308) {
  50. v = (v * 12.92);
  51. } else {
  52. v = (pow(abs(v), 1.0 / 2.4) * 1.055 - 0.055);
  53. }
  54. return v;
  55. }
  56. float3 PQtoLinear(float3 v)
  57. {
  58. const float c1 = 0.8359375;
  59. const float c2 = 18.8515625;
  60. const float c3 = 18.6875;
  61. const float oo_m1 = 1.0 / 0.1593017578125;
  62. const float oo_m2 = 1.0 / 78.84375;
  63. float3 num = max(pow(abs(v), oo_m2) - c1, 0.0);
  64. float3 den = c2 - c3 * pow(abs(v), oo_m2);
  65. return (10000.0 * pow(abs(num / den), oo_m1) / sdr_white_point);
  66. }
  67. float3 ApplyTonemap(float3 v)
  68. {
  69. if (tonemap_method == TONEMAP_LINEAR) {
  70. v *= tonemap_factor1;
  71. } else if (tonemap_method == TONEMAP_CHROME) {
  72. if (input_type == INPUTTYPE_SCRGB) {
  73. // Convert to BT.2020 colorspace for tone mapping
  74. v = mul(mat709to2020, v);
  75. }
  76. float vmax = max(v.r, max(v.g, v.b));
  77. if (vmax > 0.0) {
  78. float scale = (1.0 + tonemap_factor1 * vmax) / (1.0 + tonemap_factor2 * vmax);
  79. v *= scale;
  80. }
  81. if (input_type == INPUTTYPE_SCRGB) {
  82. // Convert to BT.709 colorspace after tone mapping
  83. v = mul(mat2020to709, v);
  84. }
  85. }
  86. return v;
  87. }
  88. float4 GetInputColor(PixelShaderInput input)
  89. {
  90. float4 rgba;
  91. rgba = texture0.Sample(sampler0, input.tex).rgba;
  92. return rgba;
  93. }
  94. float4 GetOutputColor(float4 rgba)
  95. {
  96. float4 output;
  97. output.rgb = rgba.rgb * color_scale;
  98. output.a = rgba.a;
  99. return output;
  100. }
  101. float3 GetOutputColorFromSRGB(float3 rgb)
  102. {
  103. float3 output;
  104. if (scRGB_output) {
  105. rgb.r = sRGBtoLinear(rgb.r);
  106. rgb.g = sRGBtoLinear(rgb.g);
  107. rgb.b = sRGBtoLinear(rgb.b);
  108. }
  109. output.rgb = rgb * color_scale;
  110. return output;
  111. }
  112. float3 GetOutputColorFromLinear(float3 rgb)
  113. {
  114. float3 output;
  115. output.rgb = rgb * color_scale;
  116. if (!scRGB_output) {
  117. output.r = sRGBfromLinear(output.r);
  118. output.g = sRGBfromLinear(output.g);
  119. output.b = sRGBfromLinear(output.b);
  120. output.rgb = saturate(output.rgb);
  121. }
  122. return output;
  123. }
  124. float4 AdvancedPixelShader(PixelShaderInput input)
  125. {
  126. float4 rgba = GetInputColor(input);
  127. float4 output;
  128. if (input_type == INPUTTYPE_HDR10) {
  129. rgba.rgb = PQtoLinear(rgba.rgb);
  130. }
  131. if (tonemap_method != TONEMAP_NONE) {
  132. rgba.rgb = ApplyTonemap(rgba.rgb);
  133. }
  134. if (input_type == INPUTTYPE_SRGB) {
  135. output.rgb = GetOutputColorFromSRGB(rgba.rgb);
  136. output.a = rgba.a;
  137. } else if (input_type == INPUTTYPE_SCRGB) {
  138. output.rgb = GetOutputColorFromLinear(rgba.rgb);
  139. output.a = rgba.a;
  140. } else if (input_type == INPUTTYPE_HDR10) {
  141. rgba.rgb = mul(mat2020to709, rgba.rgb);
  142. output.rgb = GetOutputColorFromLinear(rgba.rgb);
  143. output.a = rgba.a;
  144. } else {
  145. output = GetOutputColor(rgba);
  146. }
  147. return output * input.color;
  148. }