bicubic_scale.effect 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * bicubic sharper (better for downscaling)
  3. * note - this shader is adapted from the GPL bsnes shader, very good stuff
  4. * there.
  5. */
  6. uniform float4x4 ViewProj;
  7. uniform texture2d image;
  8. uniform float4x4 color_matrix;
  9. uniform float3 color_range_min = {0.0, 0.0, 0.0};
  10. uniform float3 color_range_max = {1.0, 1.0, 1.0};
  11. uniform float2 base_dimension_i;
  12. sampler_state textureSampler {
  13. Filter = Linear;
  14. AddressU = Clamp;
  15. AddressV = Clamp;
  16. };
  17. struct VertData {
  18. float4 pos : POSITION;
  19. float2 uv : TEXCOORD0;
  20. };
  21. VertData VSDefault(VertData v_in)
  22. {
  23. VertData vert_out;
  24. vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
  25. vert_out.uv = v_in.uv;
  26. return vert_out;
  27. }
  28. float weight(float x)
  29. {
  30. float ax = abs(x);
  31. /* Sharper version. May look better in some cases. */
  32. const float B = 0.0;
  33. const float C = 0.75;
  34. if (ax < 1.0)
  35. return (pow(x, 2.0) *
  36. ((12.0 - 9.0 * B - 6.0 * C) * ax +
  37. (-18.0 + 12.0 * B + 6.0 * C)) +
  38. (6.0 - 2.0 * B))
  39. / 6.0;
  40. else if ((ax >= 1.0) && (ax < 2.0))
  41. return (pow(x, 2.0) *
  42. ((-B - 6.0 * C) * ax + (6.0 * B + 30.0 * C)) +
  43. (-12.0 * B - 48.0 * C) * ax +
  44. (8.0 * B + 24.0 * C))
  45. / 6.0;
  46. else
  47. return 0.0;
  48. }
  49. float4 weight4(float x)
  50. {
  51. return float4(
  52. weight(x - 2.0),
  53. weight(x - 1.0),
  54. weight(x),
  55. weight(x + 1.0));
  56. }
  57. float4 pixel(float xpos, float ypos)
  58. {
  59. return image.Sample(textureSampler, float2(xpos, ypos));
  60. }
  61. float4 get_line(float ypos, float4 xpos, float4 linetaps)
  62. {
  63. return
  64. pixel(xpos.r, ypos) * linetaps.r +
  65. pixel(xpos.g, ypos) * linetaps.g +
  66. pixel(xpos.b, ypos) * linetaps.b +
  67. pixel(xpos.a, ypos) * linetaps.a;
  68. }
  69. float4 DrawBicubic(VertData v_in)
  70. {
  71. float2 stepxy = base_dimension_i;
  72. float2 pos = v_in.uv + stepxy * 0.5;
  73. float2 f = frac(pos / stepxy);
  74. float4 rowtaps = weight4(1.0 - f.x);
  75. float4 coltaps = weight4(1.0 - f.y);
  76. /* make sure all taps added together is exactly 1.0, otherwise some
  77. * (very small) distortion can occur */
  78. rowtaps /= rowtaps.r + rowtaps.g + rowtaps.b + rowtaps.a;
  79. coltaps /= coltaps.r + coltaps.g + coltaps.b + coltaps.a;
  80. float2 xystart = (-1.5 - f) * stepxy + pos;
  81. float4 xpos = float4(
  82. xystart.x,
  83. xystart.x + stepxy.x,
  84. xystart.x + stepxy.x * 2.0,
  85. xystart.x + stepxy.x * 3.0
  86. );
  87. return
  88. get_line(xystart.y , xpos, rowtaps) * coltaps.r +
  89. get_line(xystart.y + stepxy.y , xpos, rowtaps) * coltaps.g +
  90. get_line(xystart.y + stepxy.y * 2.0, xpos, rowtaps) * coltaps.b +
  91. get_line(xystart.y + stepxy.y * 3.0, xpos, rowtaps) * coltaps.a;
  92. }
  93. float4 PSDrawBicubicRGBA(VertData v_in) : TARGET
  94. {
  95. return DrawBicubic(v_in);
  96. }
  97. float4 PSDrawBicubicMatrix(VertData v_in) : TARGET
  98. {
  99. float4 rgba = DrawBicubic(v_in);
  100. float4 yuv;
  101. yuv.xyz = clamp(rgba.xyz, color_range_min, color_range_max);
  102. return saturate(mul(float4(yuv.xyz, 1.0), color_matrix));
  103. }
  104. technique Draw
  105. {
  106. pass
  107. {
  108. vertex_shader = VSDefault(v_in);
  109. pixel_shader = PSDrawBicubicRGBA(v_in);
  110. }
  111. }
  112. technique DrawMatrix
  113. {
  114. pass
  115. {
  116. vertex_shader = VSDefault(v_in);
  117. pixel_shader = PSDrawBicubicMatrix(v_in);
  118. }
  119. }