FXAAPreset2.shader 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  2. Shader "Hidden/FXAA Preset 2" {
  3. Properties {
  4. _MainTex ("Base (RGB)", 2D) = "white" {}
  5. }
  6. SubShader {
  7. Pass {
  8. ZTest Always Cull Off ZWrite Off
  9. CGPROGRAM
  10. #pragma vertex vert
  11. #pragma fragment frag
  12. #include "UnityCG.cginc"
  13. #pragma target 3.0
  14. // doesn't make sense to have this on consoles, it'll fallback to FXAA2
  15. #pragma exclude_renderers xbox360 ps3 gles
  16. #define FXAA_HLSL_3 1
  17. #define FXAA_PRESET 2
  18. // Copyright (c) 2010 NVIDIA Corporation. All rights reserved.
  19. //
  20. // TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
  21. // *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
  22. // OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
  23. // AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS
  24. // BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
  25. // WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
  26. // BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
  27. // ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS
  28. // BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  29. /*============================================================================
  30. FXAA
  31. ============================================================================*/
  32. /*============================================================================
  33. API PORTING
  34. ============================================================================*/
  35. #ifndef FXAA_GLSL_120
  36. #define FXAA_GLSL_120 0
  37. #endif
  38. #ifndef FXAA_GLSL_130
  39. #define FXAA_GLSL_130 0
  40. #endif
  41. #ifndef FXAA_HLSL_3
  42. #define FXAA_HLSL_3 0
  43. #endif
  44. #ifndef FXAA_HLSL_4
  45. #define FXAA_HLSL_4 0
  46. #endif
  47. /*--------------------------------------------------------------------------*/
  48. #if FXAA_GLSL_120
  49. // Requires,
  50. // #version 120
  51. // #extension GL_EXT_gpu_shader4 : enable
  52. #define int2 ivec2
  53. #define float2 vec2
  54. #define float3 vec3
  55. #define float4 vec4
  56. #define FxaaBool3 bvec3
  57. #define FxaaInt2 ivec2
  58. #define FxaaFloat2 vec2
  59. #define FxaaFloat3 vec3
  60. #define FxaaFloat4 vec4
  61. #define FxaaBool2Float(a) mix(0.0, 1.0, (a))
  62. #define FxaaPow3(x, y) pow(x, y)
  63. #define FxaaSel3(f, t, b) mix((f), (t), (b))
  64. #define FxaaTex sampler2D
  65. #endif
  66. /*--------------------------------------------------------------------------*/
  67. #if FXAA_GLSL_130
  68. // Requires "#version 130" or better
  69. #define int2 ivec2
  70. #define float2 vec2
  71. #define float3 vec3
  72. #define float4 vec4
  73. #define FxaaBool3 bvec3
  74. #define FxaaInt2 ivec2
  75. #define FxaaFloat2 vec2
  76. #define FxaaFloat3 vec3
  77. #define FxaaFloat4 vec4
  78. #define FxaaBool2Float(a) mix(0.0, 1.0, (a))
  79. #define FxaaPow3(x, y) pow(x, y)
  80. #define FxaaSel3(f, t, b) mix((f), (t), (b))
  81. #define FxaaTex sampler2D
  82. #endif
  83. /*--------------------------------------------------------------------------*/
  84. #if FXAA_HLSL_3
  85. #define int2 float2
  86. #define FxaaInt2 float2
  87. #define FxaaFloat2 float2
  88. #define FxaaFloat3 float3
  89. #define FxaaFloat4 float4
  90. #define FxaaBool2Float(a) (a)
  91. #define FxaaPow3(x, y) pow(x, y)
  92. #define FxaaSel3(f, t, b) ((f)*(!b) + (t)*(b))
  93. #define FxaaTex sampler2D
  94. #endif
  95. /*--------------------------------------------------------------------------*/
  96. #if FXAA_HLSL_4
  97. #define FxaaInt2 int2
  98. #define FxaaFloat2 float2
  99. #define FxaaFloat3 float3
  100. #define FxaaFloat4 float4
  101. #define FxaaBool2Float(a) (a)
  102. #define FxaaPow3(x, y) pow(x, y)
  103. #define FxaaSel3(f, t, b) ((f)*(!b) + (t)*(b))
  104. struct FxaaTex { SamplerState smpl; Texture2D tex; };
  105. #endif
  106. /*--------------------------------------------------------------------------*/
  107. #define FxaaToFloat3(a) FxaaFloat3((a), (a), (a))
  108. /*--------------------------------------------------------------------------*/
  109. float4 FxaaTexLod0(FxaaTex tex, float2 pos) {
  110. #if FXAA_GLSL_120
  111. return texture2DLod(tex, pos.xy, 0.0);
  112. #endif
  113. #if FXAA_GLSL_130
  114. return textureLod(tex, pos.xy, 0.0);
  115. #endif
  116. #if FXAA_HLSL_3
  117. return tex2Dlod(tex, float4(pos.xy, 0.0, 0.0));
  118. #endif
  119. #if FXAA_HLSL_4
  120. return tex.tex.SampleLevel(tex.smpl, pos.xy, 0.0);
  121. #endif
  122. }
  123. /*--------------------------------------------------------------------------*/
  124. float4 FxaaTexGrad(FxaaTex tex, float2 pos, float2 grad) {
  125. #if FXAA_GLSL_120
  126. return texture2DGrad(tex, pos.xy, grad, grad);
  127. #endif
  128. #if FXAA_GLSL_130
  129. return textureGrad(tex, pos.xy, grad, grad);
  130. #endif
  131. #if FXAA_HLSL_3
  132. return tex2Dgrad(tex, pos.xy, grad, grad);
  133. #endif
  134. #if FXAA_HLSL_4
  135. return tex.tex.SampleGrad(tex.smpl, pos.xy, grad, grad);
  136. #endif
  137. }
  138. /*--------------------------------------------------------------------------*/
  139. float4 FxaaTexOff(FxaaTex tex, float2 pos, int2 off, float2 rcpFrame) {
  140. #if FXAA_GLSL_120
  141. return texture2DLodOffset(tex, pos.xy, 0.0, off.xy);
  142. #endif
  143. #if FXAA_GLSL_130
  144. return textureLodOffset(tex, pos.xy, 0.0, off.xy);
  145. #endif
  146. #if FXAA_HLSL_3
  147. return tex2Dlod(tex, float4(pos.xy + (off * rcpFrame), 0, 0));
  148. #endif
  149. #if FXAA_HLSL_4
  150. return tex.tex.SampleLevel(tex.smpl, pos.xy, 0.0, off.xy);
  151. #endif
  152. }
  153. /*============================================================================
  154. SRGB KNOBS
  155. ------------------------------------------------------------------------------
  156. FXAA_SRGB_ROP - Set to 1 when applying FXAA to an sRGB back buffer (DX10/11).
  157. This will do the sRGB to linear transform,
  158. as ROP will expect linear color from this shader,
  159. and this shader works in non-linear color.
  160. ============================================================================*/
  161. #define FXAA_SRGB_ROP 0
  162. /*============================================================================
  163. DEBUG KNOBS
  164. ------------------------------------------------------------------------------
  165. All debug knobs draw FXAA-untouched pixels in FXAA computed luma (monochrome).
  166. FXAA_DEBUG_PASSTHROUGH - Red for pixels which are filtered by FXAA with a
  167. yellow tint on sub-pixel aliasing filtered by FXAA.
  168. FXAA_DEBUG_HORZVERT - Blue for horizontal edges, gold for vertical edges.
  169. FXAA_DEBUG_PAIR - Blue/green for the 2 pixel pair choice.
  170. FXAA_DEBUG_NEGPOS - Red/blue for which side of center of span.
  171. FXAA_DEBUG_OFFSET - Red/blue for -/+ x, gold/skyblue for -/+ y.
  172. ============================================================================*/
  173. #ifndef FXAA_DEBUG_PASSTHROUGH
  174. #define FXAA_DEBUG_PASSTHROUGH 0
  175. #endif
  176. #ifndef FXAA_DEBUG_HORZVERT
  177. #define FXAA_DEBUG_HORZVERT 0
  178. #endif
  179. #ifndef FXAA_DEBUG_PAIR
  180. #define FXAA_DEBUG_PAIR 0
  181. #endif
  182. #ifndef FXAA_DEBUG_NEGPOS
  183. #define FXAA_DEBUG_NEGPOS 0
  184. #endif
  185. #ifndef FXAA_DEBUG_OFFSET
  186. #define FXAA_DEBUG_OFFSET 0
  187. #endif
  188. /*--------------------------------------------------------------------------*/
  189. #if FXAA_DEBUG_PASSTHROUGH || FXAA_DEBUG_HORZVERT || FXAA_DEBUG_PAIR
  190. #define FXAA_DEBUG 1
  191. #endif
  192. #if FXAA_DEBUG_NEGPOS || FXAA_DEBUG_OFFSET
  193. #define FXAA_DEBUG 1
  194. #endif
  195. #ifndef FXAA_DEBUG
  196. #define FXAA_DEBUG 0
  197. #endif
  198. /*============================================================================
  199. COMPILE-IN KNOBS
  200. ------------------------------------------------------------------------------
  201. FXAA_PRESET - Choose compile-in knob preset 0-5.
  202. ------------------------------------------------------------------------------
  203. FXAA_EDGE_THRESHOLD - The minimum amount of local contrast required
  204. to apply algorithm.
  205. 1.0/3.0 - too little
  206. 1.0/4.0 - good start
  207. 1.0/8.0 - applies to more edges
  208. 1.0/16.0 - overkill
  209. ------------------------------------------------------------------------------
  210. FXAA_EDGE_THRESHOLD_MIN - Trims the algorithm from processing darks.
  211. Perf optimization.
  212. 1.0/32.0 - visible limit (smaller isn't visible)
  213. 1.0/16.0 - good compromise
  214. 1.0/12.0 - upper limit (seeing artifacts)
  215. ------------------------------------------------------------------------------
  216. FXAA_SEARCH_STEPS - Maximum number of search steps for end of span.
  217. ------------------------------------------------------------------------------
  218. FXAA_SEARCH_ACCELERATION - How much to accelerate search,
  219. 1 - no acceleration
  220. 2 - skip by 2 pixels
  221. 3 - skip by 3 pixels
  222. 4 - skip by 4 pixels
  223. ------------------------------------------------------------------------------
  224. FXAA_SEARCH_THRESHOLD - Controls when to stop searching.
  225. 1.0/4.0 - seems to be the best quality wise
  226. ------------------------------------------------------------------------------
  227. FXAA_SUBPIX_FASTER - Turn on lower quality but faster subpix path.
  228. Not recomended, but used in preset 0.
  229. ------------------------------------------------------------------------------
  230. FXAA_SUBPIX - Toggle subpix filtering.
  231. 0 - turn off
  232. 1 - turn on
  233. 2 - turn on full (ignores FXAA_SUBPIX_TRIM and CAP)
  234. ------------------------------------------------------------------------------
  235. FXAA_SUBPIX_TRIM - Controls sub-pixel aliasing removal.
  236. 1.0/2.0 - low removal
  237. 1.0/3.0 - medium removal
  238. 1.0/4.0 - default removal
  239. 1.0/8.0 - high removal
  240. 0.0 - complete removal
  241. ------------------------------------------------------------------------------
  242. FXAA_SUBPIX_CAP - Insures fine detail is not completely removed.
  243. This is important for the transition of sub-pixel detail,
  244. like fences and wires.
  245. 3.0/4.0 - default (medium amount of filtering)
  246. 7.0/8.0 - high amount of filtering
  247. 1.0 - no capping of sub-pixel aliasing removal
  248. ============================================================================*/
  249. #ifndef FXAA_PRESET
  250. #define FXAA_PRESET 3
  251. #endif
  252. /*--------------------------------------------------------------------------*/
  253. #if (FXAA_PRESET == 0)
  254. #define FXAA_EDGE_THRESHOLD (1.0/4.0)
  255. #define FXAA_EDGE_THRESHOLD_MIN (1.0/12.0)
  256. #define FXAA_SEARCH_STEPS 2
  257. #define FXAA_SEARCH_ACCELERATION 4
  258. #define FXAA_SEARCH_THRESHOLD (1.0/4.0)
  259. #define FXAA_SUBPIX 1
  260. #define FXAA_SUBPIX_FASTER 1
  261. #define FXAA_SUBPIX_CAP (2.0/3.0)
  262. #define FXAA_SUBPIX_TRIM (1.0/4.0)
  263. #endif
  264. /*--------------------------------------------------------------------------*/
  265. #if (FXAA_PRESET == 1)
  266. #define FXAA_EDGE_THRESHOLD (1.0/8.0)
  267. #define FXAA_EDGE_THRESHOLD_MIN (1.0/16.0)
  268. #define FXAA_SEARCH_STEPS 4
  269. #define FXAA_SEARCH_ACCELERATION 3
  270. #define FXAA_SEARCH_THRESHOLD (1.0/4.0)
  271. #define FXAA_SUBPIX 1
  272. #define FXAA_SUBPIX_FASTER 0
  273. #define FXAA_SUBPIX_CAP (3.0/4.0)
  274. #define FXAA_SUBPIX_TRIM (1.0/4.0)
  275. #endif
  276. /*--------------------------------------------------------------------------*/
  277. #if (FXAA_PRESET == 2)
  278. #define FXAA_EDGE_THRESHOLD (1.0/8.0)
  279. #define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
  280. #define FXAA_SEARCH_STEPS 8
  281. #define FXAA_SEARCH_ACCELERATION 2
  282. #define FXAA_SEARCH_THRESHOLD (1.0/4.0)
  283. #define FXAA_SUBPIX 1
  284. #define FXAA_SUBPIX_FASTER 0
  285. #define FXAA_SUBPIX_CAP (3.0/4.0)
  286. #define FXAA_SUBPIX_TRIM (1.0/4.0)
  287. #endif
  288. /*--------------------------------------------------------------------------*/
  289. #if (FXAA_PRESET == 3)
  290. #define FXAA_EDGE_THRESHOLD (1.0/8.0)
  291. #define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
  292. #define FXAA_SEARCH_STEPS 16
  293. #define FXAA_SEARCH_ACCELERATION 1
  294. #define FXAA_SEARCH_THRESHOLD (1.0/4.0)
  295. #define FXAA_SUBPIX 1
  296. #define FXAA_SUBPIX_FASTER 0
  297. #define FXAA_SUBPIX_CAP (3.0/4.0)
  298. #define FXAA_SUBPIX_TRIM (1.0/4.0)
  299. #endif
  300. /*--------------------------------------------------------------------------*/
  301. #if (FXAA_PRESET == 4)
  302. #define FXAA_EDGE_THRESHOLD (1.0/8.0)
  303. #define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
  304. #define FXAA_SEARCH_STEPS 24
  305. #define FXAA_SEARCH_ACCELERATION 1
  306. #define FXAA_SEARCH_THRESHOLD (1.0/4.0)
  307. #define FXAA_SUBPIX 1
  308. #define FXAA_SUBPIX_FASTER 0
  309. #define FXAA_SUBPIX_CAP (3.0/4.0)
  310. #define FXAA_SUBPIX_TRIM (1.0/4.0)
  311. #endif
  312. /*--------------------------------------------------------------------------*/
  313. #if (FXAA_PRESET == 5)
  314. #define FXAA_EDGE_THRESHOLD (1.0/8.0)
  315. #define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
  316. #define FXAA_SEARCH_STEPS 32
  317. #define FXAA_SEARCH_ACCELERATION 1
  318. #define FXAA_SEARCH_THRESHOLD (1.0/4.0)
  319. #define FXAA_SUBPIX 1
  320. #define FXAA_SUBPIX_FASTER 0
  321. #define FXAA_SUBPIX_CAP (3.0/4.0)
  322. #define FXAA_SUBPIX_TRIM (1.0/4.0)
  323. #endif
  324. /*--------------------------------------------------------------------------*/
  325. #define FXAA_SUBPIX_TRIM_SCALE (1.0/(1.0 - FXAA_SUBPIX_TRIM))
  326. /*============================================================================
  327. HELPERS
  328. ============================================================================*/
  329. // Return the luma, the estimation of luminance from rgb inputs.
  330. // This approximates luma using one FMA instruction,
  331. // skipping normalization and tossing out blue.
  332. // FxaaLuma() will range 0.0 to 2.963210702.
  333. float FxaaLuma(float3 rgb) {
  334. return rgb.y * (0.587/0.299) + rgb.x; }
  335. /*--------------------------------------------------------------------------*/
  336. float3 FxaaLerp3(float3 a, float3 b, float amountOfA) {
  337. return (FxaaToFloat3(-amountOfA) * b) +
  338. ((a * FxaaToFloat3(amountOfA)) + b); }
  339. /*--------------------------------------------------------------------------*/
  340. // Support any extra filtering before returning color.
  341. float3 FxaaFilterReturn(float3 rgb) {
  342. #if FXAA_SRGB_ROP
  343. // Do sRGB encoded value to linear conversion.
  344. return FxaaSel3(
  345. rgb * FxaaToFloat3(1.0/12.92),
  346. FxaaPow3(
  347. rgb * FxaaToFloat3(1.0/1.055) + FxaaToFloat3(0.055/1.055),
  348. FxaaToFloat3(2.4)),
  349. rgb > FxaaToFloat3(0.04045));
  350. #else
  351. return rgb;
  352. #endif
  353. }
  354. /*============================================================================
  355. VERTEX SHADER
  356. ============================================================================*/
  357. float2 FxaaVertexShader(
  358. // Both x and y range {-1.0 to 1.0 across screen}.
  359. float2 inPos) {
  360. float2 pos;
  361. pos.xy = (inPos.xy * FxaaFloat2(0.5, 0.5)) + FxaaFloat2(0.5, 0.5);
  362. return pos; }
  363. /*============================================================================
  364. PIXEL SHADER
  365. ============================================================================*/
  366. float3 FxaaPixelShader(
  367. // Output of FxaaVertexShader interpolated across screen.
  368. // xy -> actual texture position {0.0 to 1.0}
  369. float2 pos,
  370. // Input texture.
  371. FxaaTex tex,
  372. // RCPFRAME SHOULD PIXEL SHADER CONSTANTS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  373. // {1.0/frameWidth, 1.0/frameHeight}
  374. float2 rcpFrame) {
  375. /*----------------------------------------------------------------------------
  376. EARLY EXIT IF LOCAL CONTRAST BELOW EDGE DETECT LIMIT
  377. ------------------------------------------------------------------------------
  378. Majority of pixels of a typical image do not require filtering,
  379. often pixels are grouped into blocks which could benefit from early exit
  380. right at the beginning of the algorithm.
  381. Given the following neighborhood,
  382. N
  383. W M E
  384. S
  385. If the difference in local maximum and minimum luma (contrast "range")
  386. is lower than a threshold proportional to the maximum local luma ("rangeMax"),
  387. then the shader early exits (no visible aliasing).
  388. This threshold is clamped at a minimum value ("FXAA_EDGE_THRESHOLD_MIN")
  389. to avoid processing in really dark areas.
  390. ----------------------------------------------------------------------------*/
  391. float3 rgbN = FxaaTexOff(tex, pos.xy, FxaaInt2( 0,-1), rcpFrame).xyz;
  392. float3 rgbW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1, 0), rcpFrame).xyz;
  393. float3 rgbM = FxaaTexOff(tex, pos.xy, FxaaInt2( 0, 0), rcpFrame).xyz;
  394. float3 rgbE = FxaaTexOff(tex, pos.xy, FxaaInt2( 1, 0), rcpFrame).xyz;
  395. float3 rgbS = FxaaTexOff(tex, pos.xy, FxaaInt2( 0, 1), rcpFrame).xyz;
  396. float lumaN = FxaaLuma(rgbN);
  397. float lumaW = FxaaLuma(rgbW);
  398. float lumaM = FxaaLuma(rgbM);
  399. float lumaE = FxaaLuma(rgbE);
  400. float lumaS = FxaaLuma(rgbS);
  401. float rangeMin = min(lumaM, min(min(lumaN, lumaW), min(lumaS, lumaE)));
  402. float rangeMax = max(lumaM, max(max(lumaN, lumaW), max(lumaS, lumaE)));
  403. float range = rangeMax - rangeMin;
  404. #if FXAA_DEBUG
  405. float lumaO = lumaM / (1.0 + (0.587/0.299));
  406. #endif
  407. if(range < max(FXAA_EDGE_THRESHOLD_MIN, rangeMax * FXAA_EDGE_THRESHOLD)) {
  408. #if FXAA_DEBUG
  409. return FxaaFilterReturn(FxaaToFloat3(lumaO));
  410. #endif
  411. return FxaaFilterReturn(rgbM); }
  412. #if FXAA_SUBPIX > 0
  413. #if FXAA_SUBPIX_FASTER
  414. float3 rgbL = (rgbN + rgbW + rgbE + rgbS + rgbM) *
  415. FxaaToFloat3(1.0/5.0);
  416. #else
  417. float3 rgbL = rgbN + rgbW + rgbM + rgbE + rgbS;
  418. #endif
  419. #endif
  420. /*----------------------------------------------------------------------------
  421. COMPUTE LOWPASS
  422. ------------------------------------------------------------------------------
  423. FXAA computes a local neighborhood lowpass value as follows,
  424. (N + W + E + S)/4
  425. Then uses the ratio of the contrast range of the lowpass
  426. and the range found in the early exit check,
  427. as a sub-pixel aliasing detection filter.
  428. When FXAA detects sub-pixel aliasing (such as single pixel dots),
  429. it later blends in "blendL" amount
  430. of a lowpass value (computed in the next section) to the final result.
  431. ----------------------------------------------------------------------------*/
  432. #if FXAA_SUBPIX != 0
  433. float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25;
  434. float rangeL = abs(lumaL - lumaM);
  435. #endif
  436. #if FXAA_SUBPIX == 1
  437. float blendL = max(0.0,
  438. (rangeL / range) - FXAA_SUBPIX_TRIM) * FXAA_SUBPIX_TRIM_SCALE;
  439. blendL = min(FXAA_SUBPIX_CAP, blendL);
  440. #endif
  441. #if FXAA_SUBPIX == 2
  442. float blendL = rangeL / range;
  443. #endif
  444. #if FXAA_DEBUG_PASSTHROUGH
  445. #if FXAA_SUBPIX == 0
  446. float blendL = 0.0;
  447. #endif
  448. return FxaaFilterReturn(
  449. FxaaFloat3(1.0, blendL/FXAA_SUBPIX_CAP, 0.0));
  450. #endif
  451. /*----------------------------------------------------------------------------
  452. CHOOSE VERTICAL OR HORIZONTAL SEARCH
  453. ------------------------------------------------------------------------------
  454. FXAA uses the following local neighborhood,
  455. NW N NE
  456. W M E
  457. SW S SE
  458. To compute an edge amount for both vertical and horizontal directions.
  459. Note edge detect filters like Sobel fail on single pixel lines through M.
  460. FXAA takes the weighted average magnitude of the high-pass values
  461. for rows and columns as an indication of local edge amount.
  462. A lowpass value for anti-sub-pixel-aliasing is computed as
  463. (N+W+E+S+M+NW+NE+SW+SE)/9.
  464. This full box pattern has higher quality than other options.
  465. Note following this block, both vertical and horizontal cases
  466. flow in parallel (reusing the horizontal variables).
  467. ----------------------------------------------------------------------------*/
  468. float3 rgbNW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1,-1), rcpFrame).xyz;
  469. float3 rgbNE = FxaaTexOff(tex, pos.xy, FxaaInt2( 1,-1), rcpFrame).xyz;
  470. float3 rgbSW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1, 1), rcpFrame).xyz;
  471. float3 rgbSE = FxaaTexOff(tex, pos.xy, FxaaInt2( 1, 1), rcpFrame).xyz;
  472. #if (FXAA_SUBPIX_FASTER == 0) && (FXAA_SUBPIX > 0)
  473. rgbL += (rgbNW + rgbNE + rgbSW + rgbSE);
  474. rgbL *= FxaaToFloat3(1.0/9.0);
  475. #endif
  476. float lumaNW = FxaaLuma(rgbNW);
  477. float lumaNE = FxaaLuma(rgbNE);
  478. float lumaSW = FxaaLuma(rgbSW);
  479. float lumaSE = FxaaLuma(rgbSE);
  480. float edgeVert =
  481. abs((0.25 * lumaNW) + (-0.5 * lumaN) + (0.25 * lumaNE)) +
  482. abs((0.50 * lumaW ) + (-1.0 * lumaM) + (0.50 * lumaE )) +
  483. abs((0.25 * lumaSW) + (-0.5 * lumaS) + (0.25 * lumaSE));
  484. float edgeHorz =
  485. abs((0.25 * lumaNW) + (-0.5 * lumaW) + (0.25 * lumaSW)) +
  486. abs((0.50 * lumaN ) + (-1.0 * lumaM) + (0.50 * lumaS )) +
  487. abs((0.25 * lumaNE) + (-0.5 * lumaE) + (0.25 * lumaSE));
  488. bool horzSpan = edgeHorz >= edgeVert;
  489. #if FXAA_DEBUG_HORZVERT
  490. if(horzSpan) return FxaaFilterReturn(FxaaFloat3(1.0, 0.75, 0.0));
  491. else return FxaaFilterReturn(FxaaFloat3(0.0, 0.50, 1.0));
  492. #endif
  493. float lengthSign = horzSpan ? -rcpFrame.y : -rcpFrame.x;
  494. if(!horzSpan) lumaN = lumaW;
  495. if(!horzSpan) lumaS = lumaE;
  496. float gradientN = abs(lumaN - lumaM);
  497. float gradientS = abs(lumaS - lumaM);
  498. lumaN = (lumaN + lumaM) * 0.5;
  499. lumaS = (lumaS + lumaM) * 0.5;
  500. /*----------------------------------------------------------------------------
  501. CHOOSE SIDE OF PIXEL WHERE GRADIENT IS HIGHEST
  502. ------------------------------------------------------------------------------
  503. This chooses a pixel pair.
  504. For "horzSpan == true" this will be a vertical pair,
  505. [N] N
  506. [M] or [M]
  507. S [S]
  508. Note following this block, both {N,M} and {S,M} cases
  509. flow in parallel (reusing the {N,M} variables).
  510. This pair of image rows or columns is searched below
  511. in the positive and negative direction
  512. until edge status changes
  513. (or the maximum number of search steps is reached).
  514. ----------------------------------------------------------------------------*/
  515. bool pairN = gradientN >= gradientS;
  516. #if FXAA_DEBUG_PAIR
  517. if(pairN) return FxaaFilterReturn(FxaaFloat3(0.0, 0.0, 1.0));
  518. else return FxaaFilterReturn(FxaaFloat3(0.0, 1.0, 0.0));
  519. #endif
  520. if(!pairN) lumaN = lumaS;
  521. if(!pairN) gradientN = gradientS;
  522. if(!pairN) lengthSign *= -1.0;
  523. float2 posN;
  524. posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5);
  525. posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0);
  526. /*----------------------------------------------------------------------------
  527. CHOOSE SEARCH LIMITING VALUES
  528. ------------------------------------------------------------------------------
  529. Search limit (+/- gradientN) is a function of local gradient.
  530. ----------------------------------------------------------------------------*/
  531. gradientN *= FXAA_SEARCH_THRESHOLD;
  532. /*----------------------------------------------------------------------------
  533. SEARCH IN BOTH DIRECTIONS UNTIL FIND LUMA PAIR AVERAGE IS OUT OF RANGE
  534. ------------------------------------------------------------------------------
  535. This loop searches either in vertical or horizontal directions,
  536. and in both the negative and positive direction in parallel.
  537. This loop fusion is faster than searching separately.
  538. The search is accelerated using FXAA_SEARCH_ACCELERATION length box filter
  539. via anisotropic filtering with specified texture gradients.
  540. ----------------------------------------------------------------------------*/
  541. float2 posP = posN;
  542. float2 offNP = horzSpan ?
  543. FxaaFloat2(rcpFrame.x, 0.0) :
  544. FxaaFloat2(0.0f, rcpFrame.y);
  545. float lumaEndN = lumaN;
  546. float lumaEndP = lumaN;
  547. bool doneN = false;
  548. bool doneP = false;
  549. #if FXAA_SEARCH_ACCELERATION == 1
  550. posN += offNP * FxaaFloat2(-1.0, -1.0);
  551. posP += offNP * FxaaFloat2( 1.0, 1.0);
  552. #endif
  553. #if FXAA_SEARCH_ACCELERATION == 2
  554. posN += offNP * FxaaFloat2(-1.5, -1.5);
  555. posP += offNP * FxaaFloat2( 1.5, 1.5);
  556. offNP *= FxaaFloat2(2.0, 2.0);
  557. #endif
  558. #if FXAA_SEARCH_ACCELERATION == 3
  559. posN += offNP * FxaaFloat2(-2.0, -2.0);
  560. posP += offNP * FxaaFloat2( 2.0, 2.0);
  561. offNP *= FxaaFloat2(3.0, 3.0);
  562. #endif
  563. #if FXAA_SEARCH_ACCELERATION == 4
  564. posN += offNP * FxaaFloat2(-2.5, -2.5);
  565. posP += offNP * FxaaFloat2( 2.5, 2.5);
  566. offNP *= FxaaFloat2(4.0, 4.0);
  567. #endif
  568. for(int i = 0; i < FXAA_SEARCH_STEPS; i++) {
  569. #if FXAA_SEARCH_ACCELERATION == 1
  570. if(!doneN) lumaEndN =
  571. FxaaLuma(FxaaTexLod0(tex, posN.xy).xyz);
  572. if(!doneP) lumaEndP =
  573. FxaaLuma(FxaaTexLod0(tex, posP.xy).xyz);
  574. #else
  575. if(!doneN) lumaEndN =
  576. FxaaLuma(FxaaTexGrad(tex, posN.xy, offNP).xyz);
  577. if(!doneP) lumaEndP =
  578. FxaaLuma(FxaaTexGrad(tex, posP.xy, offNP).xyz);
  579. #endif
  580. doneN = doneN || (abs(lumaEndN - lumaN) >= gradientN);
  581. doneP = doneP || (abs(lumaEndP - lumaN) >= gradientN);
  582. if(doneN && doneP) break;
  583. if(!doneN) posN -= offNP;
  584. if(!doneP) posP += offNP; }
  585. /*----------------------------------------------------------------------------
  586. HANDLE IF CENTER IS ON POSITIVE OR NEGATIVE SIDE
  587. ------------------------------------------------------------------------------
  588. FXAA uses the pixel's position in the span
  589. in combination with the values (lumaEnd*) at the ends of the span,
  590. to determine filtering.
  591. This step computes which side of the span the pixel is on.
  592. On negative side if dstN < dstP,
  593. posN pos posP
  594. |-----------|------|------------------|
  595. | | | |
  596. |<--dstN--->|<---------dstP---------->|
  597. |
  598. span center
  599. ----------------------------------------------------------------------------*/
  600. float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y;
  601. float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y;
  602. bool directionN = dstN < dstP;
  603. #if FXAA_DEBUG_NEGPOS
  604. if(directionN) return FxaaFilterReturn(FxaaFloat3(1.0, 0.0, 0.0));
  605. else return FxaaFilterReturn(FxaaFloat3(0.0, 0.0, 1.0));
  606. #endif
  607. lumaEndN = directionN ? lumaEndN : lumaEndP;
  608. /*----------------------------------------------------------------------------
  609. CHECK IF PIXEL IS IN SECTION OF SPAN WHICH GETS NO FILTERING
  610. ------------------------------------------------------------------------------
  611. If both the pair luma at the end of the span (lumaEndN)
  612. and middle pixel luma (lumaM)
  613. are on the same side of the middle pair average luma (lumaN),
  614. then don't filter.
  615. Cases,
  616. (1.) "L",
  617. lumaM
  618. |
  619. V XXXXXXXX <- other line averaged
  620. XXXXXXX[X]XXXXXXXXXXX <- source pixel line
  621. | . |
  622. --------------------------
  623. [ ]xxxxxx[x]xx[X]XXXXXX <- pair average
  624. --------------------------
  625. ^ ^ ^ ^
  626. | | | |
  627. . |<---->|<---------- no filter region
  628. . | | |
  629. . center | |
  630. . | lumaEndN
  631. . | .
  632. . lumaN .
  633. . .
  634. |<--- span -->|
  635. (2.) "^" and "-",
  636. <- other line averaged
  637. XXXXX[X]XXX <- source pixel line
  638. | | |
  639. --------------------------
  640. [ ]xxxx[x]xx[ ] <- pair average
  641. --------------------------
  642. | | |
  643. |<--->|<--->|<---------- filter both sides
  644. (3.) "v" and inverse of "-",
  645. XXXXXX XXXXXXXXX <- other line averaged
  646. XXXXXXXXXXX[X]XXXXXXXXXXXX <- source pixel line
  647. | | |
  648. --------------------------
  649. XXXX[X]xxxx[x]xx[X]XXXXXXX <- pair average
  650. --------------------------
  651. | | |
  652. |<--->|<--->|<---------- don't filter both!
  653. Note the "v" case for FXAA requires no filtering.
  654. This is because the inverse of the "-" case is the "v".
  655. Filtering "v" case turns open spans like this,
  656. XXXXXXXXX
  657. Into this (which is not desired),
  658. x+. .+x
  659. XXXXXXXXX
  660. ----------------------------------------------------------------------------*/
  661. if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0))
  662. lengthSign = 0.0;
  663. /*----------------------------------------------------------------------------
  664. COMPUTE SUB-PIXEL OFFSET AND FILTER SPAN
  665. ------------------------------------------------------------------------------
  666. FXAA filters using a bilinear texture fetch offset
  667. from the middle pixel M towards the center of the pair (NM below).
  668. Maximum filtering will be half way between pair.
  669. Reminder, at this point in the code,
  670. the {N,M} pair is also reused for all cases: {S,M}, {W,M}, and {E,M}.
  671. +-------+
  672. | | 0.5 offset
  673. | N | |
  674. | | V
  675. +-------+....---
  676. | |
  677. | M...|....---
  678. | | ^
  679. +-------+ |
  680. . . 0.0 offset
  681. . S .
  682. . .
  683. .........
  684. Position on span is used to compute sub-pixel filter offset using simple ramp,
  685. posN posP
  686. |\ |<------- 0.5 pixel offset into pair pixel
  687. | \ |
  688. | \ |
  689. ---.......|...\..........|<------- 0.25 pixel offset into pair pixel
  690. ^ | ^\ |
  691. | | | \ |
  692. V | | \ |
  693. ---.......|===|==========|<------- 0.0 pixel offset (ie M pixel)
  694. ^ . | ^ .
  695. | . pos | .
  696. | . . | .
  697. | . . center .
  698. | . . .
  699. | |<->|<---------.-------- dstN
  700. | . . .
  701. | . |<-------->|<------- dstP
  702. | . .
  703. | |<------------>|<------- spanLength
  704. |
  705. subPixelOffset
  706. ----------------------------------------------------------------------------*/
  707. float spanLength = (dstP + dstN);
  708. dstN = directionN ? dstN : dstP;
  709. float subPixelOffset = (0.5 + (dstN * (-1.0/spanLength))) * lengthSign;
  710. #if FXAA_DEBUG_OFFSET
  711. float ox = horzSpan ? 0.0 : subPixelOffset*2.0/rcpFrame.x;
  712. float oy = horzSpan ? subPixelOffset*2.0/rcpFrame.y : 0.0;
  713. if(ox < 0.0) return FxaaFilterReturn(
  714. FxaaLerp3(FxaaToFloat3(lumaO),
  715. FxaaFloat3(1.0, 0.0, 0.0), -ox));
  716. if(ox > 0.0) return FxaaFilterReturn(
  717. FxaaLerp3(FxaaToFloat3(lumaO),
  718. FxaaFloat3(0.0, 0.0, 1.0), ox));
  719. if(oy < 0.0) return FxaaFilterReturn(
  720. FxaaLerp3(FxaaToFloat3(lumaO),
  721. FxaaFloat3(1.0, 0.6, 0.2), -oy));
  722. if(oy > 0.0) return FxaaFilterReturn(
  723. FxaaLerp3(FxaaToFloat3(lumaO),
  724. FxaaFloat3(0.2, 0.6, 1.0), oy));
  725. return FxaaFilterReturn(FxaaFloat3(lumaO, lumaO, lumaO));
  726. #endif
  727. float3 rgbF = FxaaTexLod0(tex, FxaaFloat2(
  728. pos.x + (horzSpan ? 0.0 : subPixelOffset),
  729. pos.y + (horzSpan ? subPixelOffset : 0.0))).xyz;
  730. #if FXAA_SUBPIX == 0
  731. return FxaaFilterReturn(rgbF);
  732. #else
  733. return FxaaFilterReturn(FxaaLerp3(rgbL, rgbF, blendL));
  734. #endif
  735. }
  736. struct v2f {
  737. float4 pos : SV_POSITION;
  738. float2 uv : TEXCOORD0;
  739. };
  740. v2f vert (appdata_img v)
  741. {
  742. v2f o;
  743. o.pos = UnityObjectToClipPos (v.vertex);
  744. o.uv = v.texcoord.xy;
  745. return o;
  746. }
  747. sampler2D _MainTex;
  748. float4 _MainTex_TexelSize;
  749. float4 frag (v2f i) : SV_Target
  750. {
  751. return float4(FxaaPixelShader(i.uv.xy, _MainTex, _MainTex_TexelSize.xy).xyz, 0.0f);
  752. }
  753. ENDCG
  754. }
  755. }
  756. Fallback "Hidden/FXAA II"
  757. }