deinterlace_base.effect 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*
  2. * Copyright (c) 2015 Ruwen Hahn <[email protected]>
  3. * John R. Bradley <[email protected]>
  4. * Hugh Bailey "Jim" <[email protected]>
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. uniform float4x4 ViewProj;
  19. uniform texture2d image;
  20. uniform texture2d previous_image;
  21. uniform float2 dimensions;
  22. uniform int field_order;
  23. uniform bool frame2;
  24. sampler_state textureSampler {
  25. Filter = Linear;
  26. AddressU = Clamp;
  27. AddressV = Clamp;
  28. };
  29. struct VertData {
  30. float4 pos : POSITION;
  31. float2 uv : TEXCOORD0;
  32. };
  33. int3 select(int2 texel, int x, int y)
  34. {
  35. return int3(texel + int2(x, y), 0);
  36. }
  37. float4 load_at_prev(int2 texel, int x, int y)
  38. {
  39. return previous_image.Load(select(texel, x, y));
  40. }
  41. float4 load_at_image(int2 texel, int x, int y)
  42. {
  43. return image.Load(select(texel, x, y));
  44. }
  45. float4 load_at(int2 texel, int x, int y, int field)
  46. {
  47. if(field == 0)
  48. return load_at_image(texel, x, y);
  49. else
  50. return load_at_prev(texel, x, y);
  51. }
  52. #define YADIF_UPDATE(c, level) \
  53. if(score.c < spatial_score.c) \
  54. { \
  55. spatial_score.c = score.c; \
  56. spatial_pred.c = (load_at(texel, level, -1, field) + load_at(texel, -level, 1, field)).c / 2; \
  57. #define YADIF_CHECK_ONE(level, c) \
  58. { \
  59. float4 score = abs(load_at(texel, -1 + level, 1, field) - load_at(texel, -1 - level, -1, field)) + \
  60. abs(load_at(texel, level, 1, field) - load_at(texel, -level, -1, field)) + \
  61. abs(load_at(texel, 1 + level, 1, field) - load_at(texel, 1 - level, -1, field)); \
  62. YADIF_UPDATE(c, level) } \
  63. }
  64. #define YADIF_CHECK(level) \
  65. { \
  66. float4 score = abs(load_at(texel, -1 + level, 1, field) - load_at(texel, -1 - level, -1, field)) + \
  67. abs(load_at(texel, level, 1, field) - load_at(texel, -level, -1, field)) + \
  68. abs(load_at(texel, 1 + level, 1, field) - load_at(texel, 1 - level, -1, field)); \
  69. YADIF_UPDATE(r, level) YADIF_CHECK_ONE(level * 2, r) } \
  70. YADIF_UPDATE(g, level) YADIF_CHECK_ONE(level * 2, g) } \
  71. YADIF_UPDATE(b, level) YADIF_CHECK_ONE(level * 2, b) } \
  72. YADIF_UPDATE(a, level) YADIF_CHECK_ONE(level * 2, a) } \
  73. }
  74. float4 texel_at_yadif(int2 texel, int field, bool mode0)
  75. {
  76. if((texel.y % 2) == field)
  77. return load_at(texel, 0, 0, field);
  78. #define YADIF_AVG(x_off, y_off) ((load_at_prev(texel, x_off, y_off) + load_at_image(texel, x_off, y_off))/2)
  79. float4 c = load_at(texel, 0, 1, field),
  80. d = YADIF_AVG(0, 0),
  81. e = load_at(texel, 0, -1, field);
  82. float4 temporal_diff0 = (abs(load_at_prev(texel, 0, 0) - load_at_image(texel, 0, 0))) / 2,
  83. temporal_diff1 = (abs(load_at_prev(texel, 0, 1) - c) + abs(load_at_prev(texel, 0, -1) - e)) / 2,
  84. temporal_diff2 = (abs(load_at_image(texel, 0, 1) - c) + abs(load_at_image(texel, 0, -1) - e)) / 2,
  85. diff = max(temporal_diff0, max(temporal_diff1, temporal_diff2));
  86. float4 spatial_pred = (c + e) / 2,
  87. spatial_score = abs(load_at(texel, -1, 1, field) - load_at(texel, -1, -1, field)) +
  88. abs(c - e) +
  89. abs(load_at(texel, 1, 1, field) - load_at(texel, 1, -1, field)) - 1;
  90. YADIF_CHECK(-1)
  91. YADIF_CHECK(1)
  92. if (mode0) {
  93. float4 b = YADIF_AVG(0, 2),
  94. f = YADIF_AVG(0, -2);
  95. float4 max_ = max(d - e, max(d - c, min(b - c, f - e))),
  96. min_ = min(d - e, min(d - c, max(b - c, f - e)));
  97. diff = max(diff, max(min_, -max_));
  98. } else {
  99. diff = max(diff, max(min(d - e, d - c), -max(d - e, d - c)));
  100. }
  101. #define YADIF_SPATIAL(c) \
  102. { \
  103. if(spatial_pred.c > d.c + diff.c) \
  104. spatial_pred.c = d.c + diff.c; \
  105. else if(spatial_pred.c < d.c - diff.c) \
  106. spatial_pred.c = d.c - diff.c; \
  107. }
  108. YADIF_SPATIAL(r)
  109. YADIF_SPATIAL(g)
  110. YADIF_SPATIAL(b)
  111. YADIF_SPATIAL(a)
  112. return spatial_pred;
  113. }
  114. float4 texel_at_yadif_2x(int2 texel, int field, bool mode0)
  115. {
  116. field = frame2 ? (1 - field) : field;
  117. return texel_at_yadif(texel, field, mode0);
  118. }
  119. float4 texel_at_discard(int2 texel, int field)
  120. {
  121. texel.y = texel.y / 2 * 2;
  122. return load_at_image(texel, 0, field);
  123. }
  124. float4 texel_at_discard_2x(int2 texel, int field)
  125. {
  126. field = frame2 ? field : (1 - field);
  127. return texel_at_discard(texel, field);
  128. }
  129. float4 texel_at_blend(int2 texel, int field)
  130. {
  131. return (load_at_image(texel, 0, 0) + load_at_image(texel, 0, 1)) / 2;
  132. }
  133. float4 texel_at_blend_2x(int2 texel, int field)
  134. {
  135. if (!frame2)
  136. return (load_at_image(texel, 0, 0) +
  137. load_at_prev(texel, 0, 1)) / 2;
  138. else
  139. return (load_at_image(texel, 0, 0) +
  140. load_at_image(texel, 0, 1)) / 2;
  141. }
  142. float4 texel_at_linear(int2 texel, int field)
  143. {
  144. if ((texel.y % 2) == field)
  145. return load_at_image(texel, 0, 0);
  146. return (load_at_image(texel, 0, -1) + load_at_image(texel, 0, 1)) / 2;
  147. }
  148. float4 texel_at_linear_2x(int2 texel, int field)
  149. {
  150. field = frame2 ? field : (1 - field);
  151. return texel_at_linear(texel, field);
  152. }
  153. float4 texel_at_yadif_discard(int2 texel, int field)
  154. {
  155. return (texel_at_yadif(texel, field, true) + texel_at_discard(texel, field)) / 2;
  156. }
  157. float4 texel_at_yadif_discard_2x(int2 texel, int field)
  158. {
  159. field = frame2 ? (1 - field) : field;
  160. return (texel_at_yadif(texel, field, true) + texel_at_discard(texel, field)) / 2;
  161. }
  162. int2 pixel_uv(float2 uv)
  163. {
  164. return int2(uv * dimensions);
  165. }
  166. float4 PSYadifMode0RGBA(VertData v_in) : TARGET
  167. {
  168. return texel_at_yadif(pixel_uv(v_in.uv), field_order, true);
  169. }
  170. float4 PSYadifMode0RGBA_2x(VertData v_in) : TARGET
  171. {
  172. return texel_at_yadif_2x(pixel_uv(v_in.uv), field_order, true);
  173. }
  174. float4 PSYadifMode2RGBA(VertData v_in) : TARGET
  175. {
  176. return texel_at_yadif(pixel_uv(v_in.uv), field_order, false);
  177. }
  178. float4 PSYadifMode2RGBA_2x(VertData v_in) : TARGET
  179. {
  180. return texel_at_yadif_2x(pixel_uv(v_in.uv), field_order, false);
  181. }
  182. float4 PSYadifDiscardRGBA(VertData v_in) : TARGET
  183. {
  184. return texel_at_yadif_discard(pixel_uv(v_in.uv), field_order);
  185. }
  186. float4 PSYadifDiscardRGBA_2x(VertData v_in) : TARGET
  187. {
  188. return texel_at_yadif_discard_2x(pixel_uv(v_in.uv), field_order);
  189. }
  190. float4 PSLinearRGBA(VertData v_in) : TARGET
  191. {
  192. return texel_at_linear(pixel_uv(v_in.uv), field_order);
  193. }
  194. float4 PSLinearRGBA_2x(VertData v_in) : TARGET
  195. {
  196. return texel_at_linear_2x(pixel_uv(v_in.uv), field_order);
  197. }
  198. float4 PSDiscardRGBA(VertData v_in) : TARGET
  199. {
  200. return texel_at_discard(pixel_uv(v_in.uv), field_order);
  201. }
  202. float4 PSDiscardRGBA_2x(VertData v_in) : TARGET
  203. {
  204. return texel_at_discard_2x(pixel_uv(v_in.uv), field_order);
  205. }
  206. float4 PSBlendRGBA(VertData v_in) : TARGET
  207. {
  208. return texel_at_blend(pixel_uv(v_in.uv), field_order);
  209. }
  210. float4 PSBlendRGBA_2x(VertData v_in) : TARGET
  211. {
  212. return texel_at_blend_2x(pixel_uv(v_in.uv), field_order);
  213. }
  214. VertData VSDefault(VertData v_in)
  215. {
  216. VertData vert_out;
  217. vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
  218. vert_out.uv = v_in.uv;
  219. return vert_out;
  220. }
  221. #define TECHNIQUE(rgba_ps) \
  222. technique Draw \
  223. { \
  224. pass \
  225. { \
  226. vertex_shader = VSDefault(v_in); \
  227. pixel_shader = rgba_ps(v_in); \
  228. } \
  229. }