源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 line
6.8 KiB

  1. Shader "Hidden/FXAA" {
  2. Properties {
  3. _MainTex ("Texture", 2D) = "white" {}
  4. }
  5. CGINCLUDE
  6. #include "UnityCG.cginc"
  7. sampler2D _MainTex;
  8. half4 _MainTex_TexelSize;
  9. half _ContrastThreshold, _RelativeThreshold;
  10. half _SubpixelBlending;
  11. struct VertexData {
  12. half4 vertex : POSITION;
  13. half2 uv : TEXCOORD0;
  14. };
  15. struct Interpolators {
  16. half4 pos : SV_POSITION;
  17. half2 uv : TEXCOORD0;
  18. };
  19. Interpolators VertexProgram (VertexData v) {
  20. Interpolators i;
  21. i.pos = UnityObjectToClipPos(v.vertex);
  22. i.uv = v.uv;
  23. return i;
  24. }
  25. half4 Sample (half2 uv) {
  26. return tex2Dlod(_MainTex, half4(uv, 0, 0));
  27. }
  28. half SampleLuminance (half2 uv) {
  29. return Sample(uv).g;
  30. // #if defined(LUMINANCE_GREEN)
  31. // return Sample(uv).g;
  32. // #else
  33. // return Sample(uv).a;
  34. // #endif
  35. }
  36. half SampleLuminance (half2 uv, half uOffset, half vOffset) {
  37. uv += _MainTex_TexelSize * half2(uOffset, vOffset);
  38. return SampleLuminance(uv);
  39. }
  40. struct LuminanceData {
  41. half m, n, e, s, w;
  42. half ne, nw, se, sw;
  43. half highest, lowest, contrast;
  44. };
  45. LuminanceData SampleLuminanceNeighborhood (half2 uv) {
  46. LuminanceData l;
  47. l.m = SampleLuminance(uv);
  48. l.n = SampleLuminance(uv, 0, 1);
  49. l.e = SampleLuminance(uv, 1, 0);
  50. l.s = SampleLuminance(uv, 0, -1);
  51. l.w = SampleLuminance(uv, -1, 0);
  52. l.ne = SampleLuminance(uv, 1, 1);
  53. l.nw = SampleLuminance(uv, -1, 1);
  54. l.se = SampleLuminance(uv, 1, -1);
  55. l.sw = SampleLuminance(uv, -1, -1);
  56. l.highest = max(max(max(max(l.n, l.e), l.s), l.w), l.m);
  57. l.lowest = min(min(min(min(l.n, l.e), l.s), l.w), l.m);
  58. l.contrast = l.highest - l.lowest;
  59. return l;
  60. }
  61. bool ShouldSkipPixel (LuminanceData l) {
  62. half threshold =
  63. max(_ContrastThreshold, _RelativeThreshold * l.highest);
  64. return l.contrast < threshold;
  65. }
  66. half DeterminePixelBlendFactor (LuminanceData l) {
  67. half filter = 2 * (l.n + l.e + l.s + l.w);
  68. filter += l.ne + l.nw + l.se + l.sw;
  69. filter *= 1.0 / 12.0;
  70. filter = abs(filter - l.m);
  71. filter = saturate(filter / l.contrast);
  72. half blendFactor = smoothstep(0, 1, filter);
  73. return blendFactor * blendFactor * _SubpixelBlending;
  74. }
  75. struct EdgeData {
  76. bool isHorizontal;
  77. half pixelStep;
  78. half oppositeLuminance, gradient;
  79. };
  80. EdgeData DetermineEdge (LuminanceData l) {
  81. EdgeData e;
  82. half horizontal =
  83. abs(l.n + l.s - 2 * l.m) * 2 +
  84. abs(l.ne + l.se - 2 * l.e) +
  85. abs(l.nw + l.sw - 2 * l.w);
  86. half vertical =
  87. abs(l.e + l.w - 2 * l.m) * 2 +
  88. abs(l.ne + l.nw - 2 * l.n) +
  89. abs(l.se + l.sw - 2 * l.s);
  90. e.isHorizontal = horizontal >= vertical;
  91. half pLuminance = e.isHorizontal ? l.n : l.e;
  92. half nLuminance = e.isHorizontal ? l.s : l.w;
  93. half pGradient = abs(pLuminance - l.m);
  94. half nGradient = abs(nLuminance - l.m);
  95. e.pixelStep =
  96. e.isHorizontal ? _MainTex_TexelSize.y : _MainTex_TexelSize.x;
  97. if (pGradient < nGradient) {
  98. e.pixelStep = -e.pixelStep;
  99. e.oppositeLuminance = nLuminance;
  100. e.gradient = nGradient;
  101. }
  102. else {
  103. e.oppositeLuminance = pLuminance;
  104. e.gradient = pGradient;
  105. }
  106. return e;
  107. }
  108. #if defined(LOW_QUALITY)
  109. #define EDGE_STEP_COUNT 4
  110. #define EDGE_STEPS 1, 1.5, 2, 4
  111. #define EDGE_GUESS 12
  112. #else
  113. #define EDGE_STEP_COUNT 10
  114. #define EDGE_STEPS 1, 1.5, 2, 2, 2, 2, 2, 2, 2, 4
  115. #define EDGE_GUESS 8
  116. #endif
  117. static const half edgeSteps[EDGE_STEP_COUNT] = { EDGE_STEPS };
  118. half DetermineEdgeBlendFactor (LuminanceData l, EdgeData e, half2 uv) {
  119. half2 uvEdge = uv;
  120. half2 edgeStep;
  121. if (e.isHorizontal) {
  122. uvEdge.y += e.pixelStep * 0.5;
  123. edgeStep = half2(_MainTex_TexelSize.x, 0);
  124. }
  125. else {
  126. uvEdge.x += e.pixelStep * 0.5;
  127. edgeStep = half2(0, _MainTex_TexelSize.y);
  128. }
  129. half edgeLuminance = (l.m + e.oppositeLuminance) * 0.5;
  130. half gradientThreshold = e.gradient * 0.25;
  131. half2 puv = uvEdge + edgeStep * edgeSteps[0];
  132. half pLuminanceDelta = SampleLuminance(puv) - edgeLuminance;
  133. bool pAtEnd = abs(pLuminanceDelta) >= gradientThreshold;
  134. UNITY_UNROLL
  135. for (int i = 1; i < EDGE_STEP_COUNT && !pAtEnd; i++) {
  136. puv += edgeStep * edgeSteps[i];
  137. pLuminanceDelta = SampleLuminance(puv) - edgeLuminance;
  138. pAtEnd = abs(pLuminanceDelta) >= gradientThreshold;
  139. }
  140. if (!pAtEnd) {
  141. puv += edgeStep * EDGE_GUESS;
  142. }
  143. half2 nuv = uvEdge - edgeStep * edgeSteps[0];
  144. half nLuminanceDelta = SampleLuminance(nuv) - edgeLuminance;
  145. bool nAtEnd = abs(nLuminanceDelta) >= gradientThreshold;
  146. UNITY_UNROLL
  147. for (int i = 1; i < EDGE_STEP_COUNT && !nAtEnd; i++) {
  148. nuv -= edgeStep * edgeSteps[i];
  149. nLuminanceDelta = SampleLuminance(nuv) - edgeLuminance;
  150. nAtEnd = abs(nLuminanceDelta) >= gradientThreshold;
  151. }
  152. if (!nAtEnd) {
  153. nuv -= edgeStep * EDGE_GUESS;
  154. }
  155. half pDistance, nDistance;
  156. if (e.isHorizontal) {
  157. pDistance = puv.x - uv.x;
  158. nDistance = uv.x - nuv.x;
  159. }
  160. else {
  161. pDistance = puv.y - uv.y;
  162. nDistance = uv.y - nuv.y;
  163. }
  164. half shortestDistance;
  165. bool deltaSign;
  166. if (pDistance <= nDistance) {
  167. shortestDistance = pDistance;
  168. deltaSign = pLuminanceDelta >= 0;
  169. }
  170. else {
  171. shortestDistance = nDistance;
  172. deltaSign = nLuminanceDelta >= 0;
  173. }
  174. if (deltaSign == (l.m - edgeLuminance >= 0)) {
  175. return 0;
  176. }
  177. return 0.5 - shortestDistance / (pDistance + nDistance);
  178. }
  179. half4 ApplyFXAA (half2 uv) {
  180. LuminanceData l = SampleLuminanceNeighborhood(uv);
  181. if (ShouldSkipPixel(l)) {
  182. return Sample(uv);
  183. }
  184. half pixelBlend = DeterminePixelBlendFactor(l);
  185. EdgeData e = DetermineEdge(l);
  186. half edgeBlend = DetermineEdgeBlendFactor(l, e, uv);
  187. half finalBlend = max(pixelBlend, edgeBlend);
  188. if (e.isHorizontal) {
  189. uv.y += e.pixelStep * finalBlend;
  190. }
  191. else {
  192. uv.x += e.pixelStep * finalBlend;
  193. }
  194. return half4(Sample(uv).rgb, l.m);
  195. }
  196. ENDCG
  197. SubShader {
  198. Cull Off
  199. ZTest Always
  200. ZWrite Off
  201. Pass { // 0 luminancePass
  202. CGPROGRAM
  203. #pragma vertex VertexProgram
  204. #pragma fragment FragmentProgram
  205. // #pragma enable_d3d11_debug_symbols
  206. #pragma multi_compile _ GAMMA_BLENDING
  207. half4 FragmentProgram (Interpolators i) : SV_Target {
  208. half4 sample = tex2D(_MainTex, i.uv);
  209. sample.rgb = saturate(sample.rgb);
  210. sample.a = LinearRgbToLuminance(sample.rgb);
  211. #if defined(GAMMA_BLENDING)
  212. sample.rgb = LinearToGammaSpace(sample.rgb);
  213. #endif
  214. return sample;
  215. }
  216. ENDCG
  217. }
  218. Pass { // 1 fxaaPass
  219. CGPROGRAM
  220. #pragma vertex VertexProgram
  221. #pragma fragment FragmentProgram
  222. // #pragma enable_d3d11_debug_symbols
  223. // #pragma multi_compile _ LUMINANCE_GREEN
  224. #pragma multi_compile _ LOW_QUALITY
  225. #pragma multi_compile _ GAMMA_BLENDING
  226. half4 FragmentProgram (Interpolators i) : SV_Target {
  227. half4 sample = ApplyFXAA(i.uv);
  228. #if defined(GAMMA_BLENDING)
  229. sample.rgb = GammaToLinearSpace(sample.rgb);
  230. #endif
  231. return sample;
  232. }
  233. ENDCG
  234. }
  235. }
  236. }