_MLAA old.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /******************************************************************************/
  2. #define MLAAThreshold 0.1f
  3. #define MLAAThreshold2 (2.5f/255)
  4. inline Flt ColDiff(Vec a, Vec b)
  5. {
  6. return Dist2(a,b)>(MLAAThreshold*MLAAThreshold);
  7. }
  8. Vec4 EdgeSoftenEdgeDetect_PS(IF_IS_PIXEL
  9. Vec2 inTex:TEXCOORD):COLOR
  10. {
  11. Vec col =Tex(Col,inTex ).rgb,
  12. col_x=Tex(Col,inTex+PixSize*Vec2(1,0)).rgb,
  13. col_y=Tex(Col,inTex+PixSize*Vec2(0,1)).rgb;
  14. Vec2 edge =Vec2(ColDiff(col,col_x),ColDiff(col,col_y));
  15. //clip(edge.x+edge.y-1); // if both are zero then don't output stencil value
  16. return Vec4(edge,0,0);
  17. }
  18. Vec4 EdgeSoftenCalcDist_PS(IF_IS_PIXEL
  19. Vec2 inTex:TEXCOORD):COLOR
  20. {
  21. Vec4 dist=Vec4(0,0,0,0);
  22. Vec2 edge=Tex(Col,inTex).xy;
  23. //if(edge.x==0 && edge.y==0)clip(-1);
  24. #if MODEL!=SM_2
  25. BRANCH if(edge.y)
  26. #endif
  27. {
  28. // scan left
  29. {
  30. Vec2 tex=inTex; tex.y+=0.5f*PixSize.y; // use bilinear filtering to scan both top and bottom
  31. Flt inc=1.0f/255;
  32. UNROLL for(Int i=0; i<4; i++)
  33. {
  34. tex.x-=PixSize.x; Vec2 edge=TexLod(Col,tex).xy;
  35. if( edge.r)inc=0; // top or bottom edge found
  36. if(!edge.g)inc=0;
  37. dist.x+=inc;
  38. }
  39. }
  40. // scan right
  41. {
  42. Vec2 tex =inTex; tex.y+=0.5f*PixSize.y; // use bilinear filtering to scan both top and bottom
  43. Flt inc =1.0f/255;
  44. Vec2 edge=TexLod(Col,tex).xy;
  45. UNROLL for(Int i=0; i<3; i++)
  46. {
  47. if( edge.r)inc=0; // top or bottom edge found
  48. tex.x+=PixSize.x; edge=TexLod(Col,tex).xy;
  49. if(!edge.g)inc=0;
  50. dist.y+=inc;
  51. }
  52. }
  53. }
  54. #if MODEL!=SM_2
  55. BRANCH if(edge.x)
  56. #endif
  57. {
  58. // scan top
  59. {
  60. Vec2 tex=inTex; tex.x+=0.5f*PixSize.x; // use bilinear filtering to scan both left and right
  61. Flt inc=1.0f/255;
  62. UNROLL for(Int i=0; i<4; i++)
  63. {
  64. tex.y-=PixSize.y; Vec2 edge=TexLod(Col,tex).xy;
  65. if( edge.g)inc=0; // horizontal edge on right or left
  66. if(!edge.r)inc=0;
  67. dist.z+=inc;
  68. }
  69. }
  70. // scan bottom
  71. {
  72. Vec2 tex =inTex; tex.x+=0.5f*PixSize.x; // use bilinear filtering to scan both left and right
  73. Flt inc =1.0f/255;
  74. Vec2 edge=TexLod(Col,tex).xy;
  75. UNROLL for(Int i=0; i<3; i++)
  76. {
  77. if( edge.g)inc=0; // horizontal edge on right or left
  78. tex.y+=PixSize.y; edge=TexLod(Col,tex).xy;
  79. if(!edge.r)inc=0;
  80. dist.w+=inc;
  81. }
  82. }
  83. }
  84. return dist;
  85. }
  86. /*Vec4 EdgeSoftenUpdateDist1_PS(IF_IS_PIXEL
  87. Vec2 inTex:TEXCOORD):COLOR
  88. {
  89. Vec4 dist =Tex(Col,inTex), offset=dist*(PixSize*255).xxyy;
  90. dist.x+=Tex(Col,inTex-Vec2(offset.x,0)).x;
  91. dist.y+=Tex(Col,inTex+Vec2(offset.y,0)).y;
  92. dist.z+=Tex(Col,inTex-Vec2(0,offset.z)).z;
  93. dist.w+=Tex(Col,inTex+Vec2(0,offset.w)).w;
  94. return dist;
  95. }
  96. Vec4 EdgeSoftenUpdateDist_PS(IF_IS_PIXEL
  97. Vec2 inTex:TEXCOORD):COLOR
  98. {
  99. Vec4 deltaPos =Tex(Col,inTex);
  100. Vec4 result =deltaPos;
  101. Vec2 texSize255=PixSize*255; deltaPos*=texSize255.xxyy;
  102. // LEFT
  103. BRANCH if(result.r>=MLAAThreshold2)
  104. {
  105. Vec2 currUV=inTex-Vec2(deltaPos.r,0);
  106. UNROLL for(Int i=0; i<3; i++)
  107. {
  108. Flt deltaU=TexLod(Col,currUV).r;
  109. result.r+=deltaU;
  110. currUV.x-=deltaU*texSize255.x;
  111. }
  112. }
  113. // RIGHT
  114. BRANCH if(result.g>=MLAAThreshold2)
  115. {
  116. Vec2 currUV=inTex+Vec2(deltaPos.g,0);
  117. UNROLL for(Int i=0; i<3; i++)
  118. {
  119. Flt deltaU=TexLod(Col,currUV).g;
  120. result.g+=deltaU;
  121. currUV.x+=deltaU*texSize255.x;
  122. }
  123. }
  124. // TOP
  125. BRANCH if(result.b>=MLAAThreshold2)
  126. {
  127. Vec2 currUV=inTex-Vec2(0,deltaPos.b);
  128. UNROLL for(Int i=0; i<3; i++)
  129. {
  130. Flt deltaV=TexLod(Col,currUV).b;
  131. result.b+=deltaV;
  132. currUV.y-=deltaV*texSize255.y;
  133. }
  134. }
  135. // BOTTOM
  136. BRANCH if(result.a>=MLAAThreshold2)
  137. {
  138. Vec2 currUV=inTex+Vec2(0,deltaPos.a);
  139. UNROLL for(Int i=0; i<3; i++)
  140. {
  141. Flt deltaV=TexLod(Col,currUV).a;
  142. result.a+=deltaV;
  143. currUV.y+=deltaV*texSize255.y;
  144. }
  145. }
  146. return result;
  147. }*/
  148. //#define SCAN_EDGES
  149. //Col1=EdgeDetect
  150. //Col2=Distance
  151. /*// Scan horizontal edge
  152. int scanHEdge(Vec2 uv, out Vec2 startUV, out Vec2 endUV, out int negLength, out int posLength)
  153. {
  154. negLength=0;
  155. posLength=0;
  156. int length=1;
  157. startUV=endUV=uv;
  158. // scan left
  159. for(;;)
  160. {
  161. startUV.x -= PixSize.x;
  162. // current texel
  163. Vec2 edge=tex2Dlod(Col1,Vec4(startUV,0.f,0.f)).xy;
  164. // bottom texel
  165. Vec2 edgeB=tex2Dlod(Col1,Vec4(startUV+Vec2(0.f,PixSize.y),0.f,0.f)).xy;
  166. if(!edge.y || edge.x || edgeB.x) // either the horizontal edge stops, or we meet a vertical bar (above or below)
  167. {
  168. // yes ? stop
  169. startUV.x += PixSize.x;
  170. break;
  171. }
  172. ++ negLength;
  173. ++ length;
  174. }
  175. // scan right
  176. // current texel
  177. Vec2 edge=tex2Dlod(Col1,Vec4(endUV,0.f,0.f)).xy;
  178. // bottom texel
  179. Vec2 edgeB=tex2Dlod(Col1,Vec4(endUV+Vec2(0.f,PixSize.y),0.f,0.f)).xy;
  180. for(;;)
  181. {
  182. if(edge.x || edgeB.x) break; // met a vertical bar above or below ? -> stops
  183. endUV.x += PixSize.x;
  184. // current texel
  185. edge=tex2Dlod(Col1,Vec4(endUV,0.f,0.f)).xy;
  186. if(!edge.y) break; // test if horizontal edge stops
  187. // bottom texel
  188. edgeB=tex2Dlod(Col1,Vec4(endUV+Vec2(0.f,PixSize.y),0.f,0.f)).xy;
  189. ++ posLength;
  190. ++ length;
  191. }
  192. return length;
  193. }
  194. // Scan vertical edge
  195. int scanVEdge(Vec2 uv, out Vec2 startUV, out Vec2 endUV, out int negLength, out int posLength)
  196. {
  197. negLength=0;
  198. posLength=0;
  199. int length=1;
  200. startUV=endUV=uv;
  201. // scan up
  202. for(;;)
  203. {
  204. startUV.y -= PixSize.y;
  205. // current texel
  206. Vec2 edge=tex2Dlod(Col1,Vec4(startUV,0.f,0.f)).xy;
  207. // right texel
  208. Vec2 edgeR=tex2Dlod(Col1,Vec4(startUV+Vec2(PixSize.x,0.f),0.f,0.f)).xy;
  209. if(!edge.x || edge.y || edgeR.y) // either the vertical edge stops, or we met an horizontal bar (right or left)
  210. {
  211. // yes ? stop
  212. startUV.y += PixSize.y;
  213. break;
  214. }
  215. ++ negLength;
  216. ++ length;
  217. }
  218. // scan bottom
  219. // current texel
  220. Vec2 edge=tex2Dlod(Col1,Vec4(endUV,0.f,0.f)).xy;
  221. // right texel
  222. Vec2 edgeR=tex2Dlod(Col1,Vec4(endUV+Vec2(PixSize.x,0.f),0.f,0.f)).xy;
  223. for(;;)
  224. {
  225. if(edge.y || edgeR.y) break; // met a horizontal on the right or the left ? -> stops
  226. endUV.y += PixSize.y;
  227. // current texel
  228. edge=tex2Dlod(Col1,Vec4(endUV,0.f,0.f)).xy;
  229. if(!edge.x) break; // test if vertical edge stops
  230. // right texel
  231. edgeR=tex2Dlod(Col1,Vec4(endUV+Vec2(PixSize.x,0.f),0.f,0.f)).xy;
  232. ++ posLength;
  233. ++ length;
  234. }
  235. return length;
  236. }*/
  237. inline Flt BlendFactor(Flt start, Flt end, Flt pos, Flt h0, Flt h1, Flt step)
  238. {
  239. Flt slope=(h1 -h0)/(end+step-start),
  240. hb0 = h0 +slope*(pos-start),
  241. hb1 = hb0+step*slope,
  242. area =(hb0+hb1)*0.5f;
  243. return area;
  244. }
  245. Vec4 EdgeSoftenApply_PS(IF_IS_PIXEL
  246. Vec2 inTex:TEXCOORD):COLOR
  247. {
  248. Vec2 edges =Tex(Col1,inTex ).xy,
  249. edgesT=Tex(Col1,inTex+PixSize*Vec2( 0,-1)).xy,
  250. edgesL=Tex(Col1,inTex+PixSize*Vec2(-1, 0)).xy;
  251. Vec4 finalCol=0;
  252. Flt weight =0;
  253. BRANCH if(edges.g+edges.r+edgesT.g+edgesL.r>0) // no edge found -> no need for anti-aliasing
  254. {
  255. #ifndef SCAN_EDGES
  256. Vec4 dist =TexLod(Col2,inTex ),
  257. distT=TexLod(Col2,inTex+PixSize*Vec2( 0,-1)),
  258. distL=TexLod(Col2,inTex+PixSize*Vec2(-1, 0));
  259. #endif
  260. // BOTTOM HORIZONTAL EDGE
  261. if(edges.g)
  262. {
  263. Flt negLength, posLength, length;
  264. Vec2 startUV, endUV;
  265. #ifdef SCAN_EDGES
  266. length=scanHEdge(inTex, startUV, endUV, negLength, posLength);
  267. #else
  268. // Use distance from the distance texture
  269. negLength=dist.r*255;
  270. posLength=dist.g*255;
  271. length =negLength+posLength+1;
  272. startUV =inTex+Vec2(-PixSize.x*negLength,0);
  273. endUV =inTex+Vec2( PixSize.x*posLength,0);
  274. #endif
  275. // test |_____ case
  276. if(negLength<posLength) // if(length>1 && negLength<=posLength) // passed the middle, the contribution is NULL
  277. {
  278. Vec4 c=TexLod(Col1,startUV+PixSize*Vec2(-1,0));
  279. if(c.r)
  280. {
  281. Flt h0= 0.5f,
  282. h1=-0.5f,
  283. b = BlendFactor(startUV.x, endUV.x, inTex.x, h0, h1, PixSize.x);
  284. finalCol+=TexLod(Col,inTex+Vec2(0,b*PixSize.y)); // lerp, using bilinear filtering for transition
  285. weight +=1;
  286. }
  287. }else
  288. // test _____| case
  289. if(negLength>posLength) // if(length>1 && negLength>=posLength) // passed the middle, the contribution is NULL
  290. {
  291. Vec4 c=TexLod(Col1,endUV);
  292. if(c.r)
  293. {
  294. Flt h0=-0.5f,
  295. h1= 0.5f,
  296. b = BlendFactor(startUV.x, endUV.x, inTex.x, h0, h1, PixSize.x);
  297. finalCol+=TexLod(Col,inTex+Vec2(0,b*PixSize.y)); // lerp, using bilinear filtering for transition
  298. weight +=1;
  299. }
  300. }
  301. }else
  302. // TOP HORIZONTAL EDGE
  303. if(edgesT.g)
  304. {
  305. Flt negLength, posLength, length;
  306. Vec2 startUV, endUV;
  307. #ifdef SCAN_EDGES
  308. length=scanHEdge(inTex+PixSize*Vec2(0,-1), startUV, endUV, negLength, posLength);
  309. #else
  310. // use distance from the distance texture
  311. negLength=distT.r*255;
  312. posLength=distT.g*255;
  313. length =negLength+posLength+1;
  314. startUV =inTex+Vec2(-PixSize.x*negLength,-PixSize.y);
  315. endUV =inTex+Vec2( PixSize.x*posLength,-PixSize.y);
  316. #endif
  317. // ______
  318. // test | case
  319. if(negLength<posLength) // if(length>1 && negLength<=posLength) // passed the middle, the contribution is NULL
  320. {
  321. Vec4 c=TexLod(Col1,startUV+PixSize*Vec2(-1,1));
  322. if(c.r)
  323. {
  324. Flt h0=-0.5f,
  325. h1= 0.5f,
  326. b = BlendFactor(startUV.x, endUV.x, inTex.x, h0, h1, PixSize.x);
  327. finalCol+=TexLod(Col,inTex+Vec2(0,b*PixSize.y)); // lerp, using bilinear filtering for transition
  328. weight +=1;
  329. }
  330. }else
  331. // ______
  332. // test | case
  333. if(negLength>posLength) // if(length>1 && negLength>=posLength) // passed the middle, the contribution is NULL
  334. {
  335. Vec4 c=TexLod(Col1,endUV+PixSize*Vec2(0,1));
  336. if(c.r)
  337. {
  338. Flt h0= 0.5f,
  339. h1=-0.5f,
  340. b = BlendFactor(startUV.x, endUV.x, inTex.x, h0, h1, PixSize.x);
  341. finalCol+=TexLod(Col,inTex+Vec2(0,b*PixSize.y)); // lerp, using bilinear filtering for transition
  342. weight +=1;
  343. }
  344. }
  345. }
  346. // VERTICAL EDGE ON THE RIGHT
  347. if(edges.r)
  348. {
  349. Flt negLength, posLength, length;
  350. Vec2 startUV, endUV;
  351. #ifdef SCAN_EDGES
  352. length=scanVEdge(inTex, startUV, endUV, negLength, posLength);
  353. #else
  354. // use distance from the distance texture
  355. negLength=dist.b*255;
  356. posLength=dist.a*255;
  357. length =negLength+posLength+1;
  358. startUV =inTex+Vec2(0,-PixSize.y*negLength);
  359. endUV =inTex+Vec2(0, PixSize.y*posLength);
  360. #endif
  361. // test _ case
  362. // |
  363. // |
  364. if(negLength<posLength) // if(length>1 && negLength<=posLength) // passed the middle, the contribution is NULL
  365. {
  366. Vec4 c=TexLod(Col1,startUV+PixSize*Vec2(0,-1));
  367. if(c.g)
  368. {
  369. Flt h0= 0.5f,
  370. h1=-0.5f,
  371. b = BlendFactor(startUV.y, endUV.y, inTex.y, h0, h1, PixSize.y);
  372. finalCol+=TexLod(Col,inTex+Vec2(b*PixSize.x,0)); // lerp, using bilinear filtering for transition
  373. weight +=1;
  374. }
  375. }else
  376. // test | case
  377. // |
  378. // --
  379. if(negLength>posLength) // if(length>1 && negLength>=posLength) // passed the middle, the contribution is NULL
  380. {
  381. Vec4 c=TexLod(Col1,endUV);
  382. if(c.g)
  383. {
  384. Flt h0=-0.5f,
  385. h1= 0.5f,
  386. b = BlendFactor(startUV.y, endUV.y, inTex.y, h0, h1, PixSize.y);
  387. finalCol+=TexLod(Col,inTex+Vec2(b*PixSize.x,0)); // lerp, using bilinear filtering for transition
  388. weight +=1;
  389. }
  390. }
  391. }else
  392. // VERTICAL EDGE ON THE LEFT
  393. if(edgesL.r)
  394. {
  395. Flt negLength, posLength, length;
  396. Vec2 startUV, endUV;
  397. #ifdef SCAN_EDGES
  398. length=scanVEdge(inTex+PixSize*Vec2(-1,0), startUV, endUV, negLength, posLength);
  399. #else
  400. // use distance from the distance texture
  401. negLength=distL.b*255;
  402. posLength=distL.a*255;
  403. length =negLength+posLength+1;
  404. startUV =inTex+Vec2(-PixSize.x,-PixSize.y*negLength);
  405. endUV =inTex+Vec2(-PixSize.x, PixSize.y*posLength);
  406. #endif
  407. // test _ case
  408. // |
  409. // |
  410. if(negLength<posLength) // if(length>1 && negLength<=posLength) // passed the middle, the contribution is NULL
  411. {
  412. Vec4 c=TexLod(Col1,startUV+PixSize*Vec2(1,-1));
  413. if(c.g)
  414. {
  415. Flt h0=-0.5f,
  416. h1= 0.5f,
  417. b = BlendFactor(startUV.y, endUV.y, inTex.y, h0, h1, PixSize.y);
  418. finalCol+=TexLod(Col,inTex+Vec2(b*PixSize.x,0)); // lerp, using bilinear filtering for transition
  419. weight +=1;
  420. }
  421. }else
  422. // test | case
  423. // |
  424. // --
  425. if(negLength>posLength) // if(length>1 && negLength>=posLength) // passed the middle, the contribution is NULL
  426. {
  427. Vec4 c=TexLod(Col1,endUV+PixSize*Vec2(1,0));
  428. if(c.g)
  429. {
  430. Flt h0= 0.5f,
  431. h1=-0.5f,
  432. b = BlendFactor(startUV.y, endUV.y, inTex.y, h0, h1, PixSize.y);
  433. finalCol+=TexLod(Col,inTex+Vec2(b*PixSize.x,0)); // lerp, using bilinear filtering for transition
  434. weight +=1;
  435. }
  436. }
  437. }
  438. }
  439. finalCol+=(1.0f/256)*Tex(Col,inTex);
  440. weight +=(1.0f/256);
  441. return finalCol/weight;
  442. }
  443. /******************************************************************************/
  444. #if MODEL!=SM_2
  445. TECHNIQUE(EdgeSoftenEdgeDetect , Draw_VS(), EdgeSoftenEdgeDetect_PS ());
  446. TECHNIQUE(EdgeSoftenCalcDist , Draw_VS(), EdgeSoftenCalcDist_PS ());
  447. //TECHNIQUE(EdgeSoftenUpdateDist1, Draw_VS(), EdgeSoftenUpdateDist1_PS());
  448. //TECHNIQUE(EdgeSoftenUpdateDist , Draw_VS(), EdgeSoftenUpdateDist_PS ());
  449. TECHNIQUE(EdgeSoftenApply , Draw_VS(), EdgeSoftenApply_PS ());
  450. #endif
  451. /******************************************************************************/