area.effect 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. uniform float4x4 ViewProj;
  2. uniform float2 base_dimension;
  3. uniform float2 base_dimension_i;
  4. uniform texture2d image;
  5. sampler_state textureSampler {
  6. Filter = Linear;
  7. AddressU = Clamp;
  8. AddressV = Clamp;
  9. };
  10. struct VertData {
  11. float4 pos : POSITION;
  12. float2 uv : TEXCOORD0;
  13. };
  14. struct VertInOut {
  15. float2 uv : TEXCOORD0;
  16. float4 pos : POSITION;
  17. };
  18. struct FragData {
  19. float2 uv : TEXCOORD0;
  20. };
  21. VertInOut VSDefault(VertData vert_in)
  22. {
  23. VertInOut vert_out;
  24. vert_out.pos = mul(float4(vert_in.pos.xyz, 1.0), ViewProj);
  25. vert_out.uv = vert_in.uv;
  26. return vert_out;
  27. }
  28. float4 DrawArea(float2 uv)
  29. {
  30. float2 uv_delta = float2(ddx(uv.x), ddy(uv.y));
  31. // Handle potential OpenGL flip.
  32. if (obs_glsl_compile)
  33. uv_delta.y = abs(uv_delta.y);
  34. float2 uv_min = uv - 0.5 * uv_delta;
  35. float2 uv_max = uv_min + uv_delta;
  36. float2 load_index_begin = floor(uv_min * base_dimension);
  37. float2 load_index_end = ceil(uv_max * base_dimension);
  38. float2 target_dimension = 1.0 / uv_delta;
  39. float2 target_pos = uv * target_dimension;
  40. float2 target_pos_min = target_pos - 0.5;
  41. float2 target_pos_max = target_pos + 0.5;
  42. float2 scale = base_dimension_i * target_dimension;
  43. float4 total_color = float4(0.0, 0.0, 0.0, 0.0);
  44. float load_index_y = load_index_begin.y;
  45. do {
  46. float source_y_min = load_index_y * scale.y;
  47. float source_y_max = source_y_min + scale.y;
  48. float y_min = max(source_y_min, target_pos_min.y);
  49. float y_max = min(source_y_max, target_pos_max.y);
  50. float height = y_max - y_min;
  51. float load_index_x = load_index_begin.x;
  52. do {
  53. float source_x_min = load_index_x * scale.x;
  54. float source_x_max = source_x_min + scale.x;
  55. float x_min = max(source_x_min, target_pos_min.x);
  56. float x_max = min(source_x_max, target_pos_max.x);
  57. float width = x_max - x_min;
  58. float area = width * height;
  59. float4 color = image.Load(int3(load_index_x, load_index_y, 0));
  60. total_color += area * color;
  61. ++load_index_x;
  62. } while (load_index_x < load_index_end.x);
  63. ++load_index_y;
  64. } while (load_index_y < load_index_end.y);
  65. return total_color;
  66. }
  67. float4 PSDrawAreaRGBA(FragData frag_in) : TARGET
  68. {
  69. return DrawArea(frag_in.uv);
  70. }
  71. float4 PSDrawAreaRGBADivide(FragData frag_in) : TARGET
  72. {
  73. float4 rgba = DrawArea(frag_in.uv);
  74. float alpha = rgba.a;
  75. float multiplier = (alpha > 0.0) ? (1.0 / alpha) : 0.0;
  76. return float4(rgba.rgb * multiplier, alpha);
  77. }
  78. float4 PSDrawAreaRGBAUpscale(FragData frag_in) : TARGET
  79. {
  80. float2 uv = frag_in.uv;
  81. float2 uv_delta = float2(ddx(uv.x), ddy(uv.y));
  82. // Handle potential OpenGL flip.
  83. if (obs_glsl_compile)
  84. uv_delta.y = abs(uv_delta.y);
  85. float2 uv_min = uv - 0.5 * uv_delta;
  86. float2 uv_max = uv_min + uv_delta;
  87. float2 load_index_first = floor(uv_min * base_dimension);
  88. float2 load_index_last = ceil(uv_max * base_dimension) - 1.0;
  89. if (load_index_first.x < load_index_last.x) {
  90. float uv_boundary_x = load_index_last.x * base_dimension_i.x;
  91. uv.x = ((uv.x - uv_boundary_x) / uv_delta.x) * base_dimension_i.x + uv_boundary_x;
  92. } else
  93. uv.x = (load_index_first.x + 0.5) * base_dimension_i.x;
  94. if (load_index_first.y < load_index_last.y) {
  95. float uv_boundary_y = load_index_last.y * base_dimension_i.y;
  96. uv.y = ((uv.y - uv_boundary_y) / uv_delta.y) * base_dimension_i.y + uv_boundary_y;
  97. } else
  98. uv.y = (load_index_first.y + 0.5) * base_dimension_i.y;
  99. return image.Sample(textureSampler, uv);
  100. }
  101. technique Draw
  102. {
  103. pass
  104. {
  105. vertex_shader = VSDefault(vert_in);
  106. pixel_shader = PSDrawAreaRGBA(frag_in);
  107. }
  108. }
  109. technique DrawAlphaDivide
  110. {
  111. pass
  112. {
  113. vertex_shader = VSDefault(vert_in);
  114. pixel_shader = PSDrawAreaRGBADivide(frag_in);
  115. }
  116. }
  117. technique DrawUpscale
  118. {
  119. pass
  120. {
  121. vertex_shader = VSDefault(vert_in);
  122. pixel_shader = PSDrawAreaRGBAUpscale(frag_in);
  123. }
  124. }