From 1be5d871c6023c20b2b5fc044cf0b36dbc051ce1 Mon Sep 17 00:00:00 2001 From: Lubos Lenco Date: Mon, 13 Jun 2016 15:07:57 +0200 Subject: [PATCH] Raw SMAA shaders. --- Assets/SMAAArea.png | Bin 0 -> 39631 bytes Assets/SMAASearch.png | Bin 0 -> 313 bytes Sources/cycles/renderpipeline/SMAAData.hx | 5 + raw/smaa_pass/smaa_blend_weight.frag.glsl | 122 +++++ raw/smaa_pass/smaa_blend_weight.vert.glsl | 34 ++ raw/smaa_pass/smaa_edge_detect.frag.glsl | 475 ++++++++++++++++++ raw/smaa_pass/smaa_edge_detect.vert.glsl | 27 + .../smaa_neighborhood_blending.frag.glsl | 77 +++ .../smaa_neighborhood_blending.vert.glsl | 25 + raw/smaa_pass/smaa_pass.frag.glsl | 164 ++++++ raw/smaa_pass/smaa_pass.shader.json | 25 + raw/smaa_pass/smaa_pass.vert.glsl | 18 + .../smaa_separate_multisamples.frag.glsl | 29 ++ raw/smaa_pass/smaa_temporal_resolve.frag.glsl | 49 ++ 14 files changed, 1050 insertions(+) create mode 100644 Assets/SMAAArea.png create mode 100644 Assets/SMAASearch.png create mode 100644 raw/smaa_pass/smaa_blend_weight.frag.glsl create mode 100644 raw/smaa_pass/smaa_blend_weight.vert.glsl create mode 100644 raw/smaa_pass/smaa_edge_detect.frag.glsl create mode 100644 raw/smaa_pass/smaa_edge_detect.vert.glsl create mode 100644 raw/smaa_pass/smaa_neighborhood_blending.frag.glsl create mode 100644 raw/smaa_pass/smaa_neighborhood_blending.vert.glsl create mode 100644 raw/smaa_pass/smaa_pass.frag.glsl create mode 100755 raw/smaa_pass/smaa_pass.shader.json create mode 100644 raw/smaa_pass/smaa_pass.vert.glsl create mode 100644 raw/smaa_pass/smaa_separate_multisamples.frag.glsl create mode 100644 raw/smaa_pass/smaa_temporal_resolve.frag.glsl diff --git a/Assets/SMAAArea.png b/Assets/SMAAArea.png new file mode 100644 index 0000000000000000000000000000000000000000..a49f2a45a246a1fac76631597123dd0bd643e5f4 GIT binary patch literal 39631 zcmW(+bzBr(7oKH_#_L%^H!3l>w9D(?Z4b^OY##BgBaCSrp4x#;@rVHu-)6 z^Sq;jzVlY;L`yL(TAk57aX$anKa}`=N~7xe+pOa=@Ijz*Aeu(_%y1SInZ%F*9Cqb$ zi}WUTtKN{K5#>J);;#;LyY3e61vvdFoC_pU!DW~PtKBa#*coE9SylNwTa9ktps9ke z8lcAb5}2r+-sHu}1C;lyl{i*|k?rK-^y*`8T$C`N!kn?C(|q%ns`Z2a$|86{5M%vX zLbXN!@mx1mV=ju`a`oWu6KZx4Bu9pl1kM;ZKVfv@A!A&7$PwLQ2e<08cPg0Z`km`? zF!>DMK1GAS+s|7(XMZXIVc>?Az*1rtxfz^U)cg1`ED7iW`BF6qKvOZL@J~W9I9cFW zDD9A;RsuzWy7(=?9}mS3T&Mu|q#938toDv=p4&3{xuFkmP=UH*^7R zN=+Pg3K-mLlA_PAS!DtMKzht`=k}MI)Y4ax;gL9K-8^A&0 zS5+LHL5E|<{CUas6sdp#fEv_*se{`GYHn$fY?MrNV#mw=)+m|(C)dTDBo(z$%`8Ju z5$3BfK}Fm$^Cit%Sf$k2)&BD%`%9vQjV*!Yd@un4<1%0xI}de+={#<(e^0vD+{;fQ z*Q7-DX!zTxp&A1AD*V$G)wt&CYtXdpE-6Sm@=n=-{B#IzcK`ePBMC7|ZXkkyI8}0N z2tc=!>IS&6XUq&8>)Qz7$YKkD;F$+w;gD=Cs==9H$P+Slq4$^>@kT;MV>?nH%Dp1( zLB*yji=bI+2?k@j<)dcYmtC7O0b>=v`45i!ua~1pKZ6e0X9LMkXo~tjmu`-~BBCbM z=lwl4|LlTz$WZdNj8G46L`B1pBikNNW<z@uwdV@&NA6Y*sU@2KJdz9}q^@vtRCU-j|IOpCVOjEzJY?2O)Ri47p@v1P&V z9%%*hqaVcRuo?Wm$B!*TP5}D{X+$2%U*Rf0j`Egy0F)M%X@oFaWP{fmNO)pPb=W*y`nBje}g-<%9611xu(wOX!aAE>A!~ z{>P$AY6tP2{w%%s+icqm%nV?>lNVQy4@HSIIDfH5ViYkH(HDOln8BOjHEjJ!&Kh4v zP|X7HzAZpkkFv{9<;M-<)#!OlM46?|9Oi{9*DY%1qg5qLQ(9@3WoG60B&NKt4HY4W z&>pcVkol#L)oO!9_kI1S(BYOU;G|@I|5QwL&->=M<}BuQ%l-B^8F@B{meip=D}{M} zikziqcf#P2p+x$}QrKtMSgA!gKLX@|4ErX64;sPARvH z@ZvdFe$DQS>3~LVsR|(b@qALhrDpqC?(of?2tjzskv=c326p|vQymCXUSj?weca3Nz0u75_-my{V+V?0BPMt; z#I9E>#46L53&rX*bRT!$(Kq~&`%1y=85#X!LNzbE;g4P(1V8%E-l&w*bgnbP#bIbS zp!M!QSO!{745Mb#>jK*QD?5~MeK2;EA>Ox2{2W2{v<_Zp^tsWOADe-66(2T27jUG~cb&-O?CA+pvxdQnz;M@T5v{g?d6lkJLCGEHgn8oxzfGgw(RW zA6to8fJUnTUhorYVr=rn#T}dSB!<)5Z{mR1@niID6Kd-*r#J*7_{WB<6>78pMECL% zjl7sU@w3nK2uf@+SqN9^b))%a5t^yW=4kQ~;q;%eN4!zIn&Z0{D(tKpe7;iK-|MRYqL-h~vXD8g3lYdLOD)`_JW8hI<|?EWa# zHP#PhwCUbAbcJ`wEy_{Q&Tc1t;eUs$8)Q3jG0T~`^QWwUhJf>ycx=Bnq(;28E;OAKU4$=1g>bw*OA<#E+-g3*EO^l zT3;b=yRcYWb_Ext?ZN8|7M!*K`4m4GH_`C!>yE16!XQr!Bk;?Zy0Nifo9B_>nrl+9 za~FNzR?#Qa9U{ef5gZyqAc@>OgM60e*oaPR-QkOUfS>9p`d0a|^s1?qdJw_X0sP%i%5KX`VBRS{8>vwgJ(FUWe{-YXME^G=}}}8 zZac#WebxmeFG7PEoV5#?)OS7rg#Miq&LsUuv+zq*M=uD8#+o0=Li`-$an zb5u<`HZ&mBSQtHj$c|lo(_4UDmlv?_3b1!bWp4Y8dHYX!F!KWC$3gc>&-auBPY?avW`40>)TMw0WG?4C zk8BQC-TcO3WbiO*dU-<9TpI$qS~S;PrUJAbTVB%Jz-^#Q|1ycg1=M6-{%cdW)CVk83iO_W zyJ2$U2`#qE^uWB*f)!25HQd**dz*xBjby3^`kyk2nVvkG5lNc{`JB7W0tS-r>{ z>^F`~1DOsjzQS}DMJBVVTXKVz?3n{QRN6P{gHc_#^O_>v5ei>5BiDMh4x)YPB;ABz z0r;2vL;u`w40=9&EgQ@T0Q@-+9{w3G=2L{qlEq!)uA9JU8JE*ub|vpnHdM&vzzv-{ zDv9AWfveE|i60$A-$1S6R4D57(g|a%-zhN23$TCU`RG`aJ4{62H!yyXMXil3a(vF@ z(9;%y(@Fv0vV{>VPkf$P&s)~W+om4Q~&Z!XhAg{2t7f{8%ja_{;%)MlCRQjOoYu z3A)M!KmBA1`qj{x;Ce=cvbrbmUL$W1#*D^rCJ(+%n*E-1Y(k3^z#CZNMelj#4qk_* zcb|-M?N63l56De}oU{94%oW+s2t_JXC$aYUv}Rnf!Gwxxv{^^-Cy$(O%67l@sh*l( zp@Qo?RLOW)4dd#7G*G5brZYr;4t7%*{t?mxN`n zQim0D$d*_FR*W`sbRd|AT{WR>%CE~eB*Zb}$?FVI&f|GJr1BHnkfF?3YdpY>c3X&= zy0gY7=6NpH`e45~tW$b?EWlCjaLUtJ}k4IJqoaKWhwNwIMXI!GD zp}lxWjaUD;nq`^v2Ia!d=L9GZ_7LIFAvNF{z!&$f&3-i$lF^ny~l-X1)h; zH5t$qV4*!^!!HV`lu@KY+F)HYvM*okx~C?c2S8C$QFgL(@)`5;8CDr69$%DdkQB=R zpJ<@1$bymdYtiRkjj#oqmAqhLnHHz1t zaU<3AR0=G+h&*RBt+To#X{b8#UCfxnBPScqjKAeMdaFB`ApRnp- zSJEG`LV&*pq=OzXkM?|T%CUb>!%lqT%(+CD#?CYt$@^mgcsy%9=i_amcVE`hL#s$$ z^68~w4TU3#gR~=i$CHJWsgEfqNnlLXoB`4KgOT!3r>-lUh(41a0V;gx{1fDpDXLbD zi__?p(Y(p;N~!|2w-eLvaKjf?-h*D7m8HXak@MVQx;Vvy> zJeQc`4t}jNQMo||BG)>ZmMm}>-7tMj=;Glkp;$o{^WNw{p<9(W=EF%C?u^q`Po|FX zGY+jdC)>I=>oPc;*k2uX|GJrQW<$4{a>7jwUoR>$yrq8f(?(3bDlR~(=i2mIsnN*m zy;w|HNVycgfNaJ2`gheR+KNmqzsFQVL@Ew#6p%(<0RrJ8CsgEmWFT7rmUa4 z3);+kaM7GedfB;is(+1Z9V7{p{z1zlj9Yy_v+>|8C57YsLB)AayU}YM$ec98l;8DU zffRm{Wm43C-fE*ID04NKAV>&aNO*@#gRc5GDetPPVW0fH3kJvkdBpo3nz#nF2h!n9Vad-bvv*W3^=9+L6;w z`5hV;pCA(r0zz!h`rImtayTclegf=A3{ zYM=5Otb7$4ZTTf;WJ6OCzYqiV#%f=Pd#V`ieZC<<_4f7JlI1WXPRB#&C+?HJLcGVb4BX?3;4kqSy+0e-F9VbzNSPet7Xa6Z^} zeZibt>e!NRnCc3&-GvK|C}i#IK-W z4`^s#bJD+lcKtwfyp1|D1bT$12O8CE$A;Er*5aCQ^;5Tr7eCSPe-iwe_D6;f-^Zj) zI00e*EY80j+LA$o;>9`}DEm%VA$eWuFe=pun%W8e*=Wm3@AFYKmrZVQ7H&K8wz)u% zS{laelcqt7`T2n;seU7T)|7CY)=Y8qLDk4f1U=^4u0b`Vi+u&}<53bLnE$L_xugp7 zcEN(@I1)ig8%!vX30iQ<(^OXhCHU=+h`g5<@houB=sBjBZ)?MvAqwQQ5J=PK6!G~vxG2*sCvjgYzzGM@kO6+CF=7|c2K zmSqR5Ynf{HQkf`a7)EX{*8Z#Av=57Bp6QA(8dC15zE^2M);et)ly%L+N}~Ye!1L!pB76PvhP;L^UbEseK9XLt zNoWXS)bO)%vf0y;T11tyw$-5nlMU_c5OPpK#Q2x*?|!gGG3SqLBrZ)~ct94gHN%Q*%X-e1gugo{^ksM~VT zEfFGBk(e9iL8}qKO&D{zP}hI!Kc zm+{A_Ldk5X?Tn#o>lWo9?eX0tZ%+Zx9KGWQ(|z$?{9k==kQ=6V5S>68h%7Bv1y*~F zaqhWgTe+nBZd218Wpzh~IsmsMt{xB2yZoCD88!=snPs$HoClM|T-s5&kKqmN zfS<&#F#(IX=t1Cu$^L_x(|e_Q6NR5N!DNGZxgiYlxjg)8XEa}$D6GX?bf5|TFrU#F-)@OPK+~?i2p66!HsrA8&D z53JQsWJm+`A^R3`moaZ84GLNY*0wkVK$a$-T<)tbEv^$66@oTp z#3R)s*jeQ5ahDc)ku`5MtYuSgh)(aU&7j#juA6&VR3&=gG%>2LgnNZ zVay1>qzW;n_1KQmS;3hgm9AA&M+jN*WKD0O&kUEdUs4iiGKTw$7W~lw_lL$xH-}sA zD%ncpWAKb3&8RBpu0O^Kx_pwtMw4>ERZptGWfm^2m4})$X{ln{dpv?vHuVe&?GpQ8 zL;ZxrNdT#q!rT%Pl!Zb0DCMn2v_zQ8Te+MluzHooM(slCk|9pUv~8W( zW`(NTF>St;NF22*{eoEV;{HqLem}ZTp#k=6WcgS`Q+ie{F{i@QM-Bv+hQxxqJcei@ zvHtdK!qK;T`mH`jU1v3zNdfX+5Md^w!`Zg;}1fU>`Hy{-!Cw5t+B+Y zh}+wUSR$Hrtt>Mp>%I`r^VWiPn!1Ipq}3SestimD*usrPBXA_BaQ|iAuGP=bE&QdB zA%YdWH`}ExvlW-E6(}*D+pzx)#VT<0I2~g9rEUnZcnSU2$SmXsSJ*0^iFqd={G(jG zyUlE$OINx5tZY1n;~*W17$Oc!wb-rs9l1Fh`x_3{5R5XIY&~kcH8FyBKx9;Y57^&* zU-8}C9$zzl_X0u{%WJ|j>KQg1w#{K)R4^}_b1P@Xw?a^e%h(RjO>u*8^xwe?BCt9UPSyjU*ekXlf@b3Ibz zH}3Z+r@Snv(ksIY{Xy9pMCt_iOdFk=Pkd30%8`XsWely+v&A}jzD)&jyJ;u2rD}Ha z!cUth_ND3`8&15bj<-BDpol9E9Xo3*4m$72X&E?b<8r9Dn{hyM4}vzzC5B`%7^>H* zi)h48zoVRJG4PGvm*}6x(xrP03=3RkrORwvc}obA3^p`nb!+6{^d1X5-^0X4ZMVrv zS_fJwR^;1g)fz7sFHNMT$274@+a5@>{G^4*V6r5ays0nx%1>XE8$oWEY8b&AlfkkW zgwyQz$lnAnED?cN4ee~QJkTGHrW3*(7zhpu#OO2nEzp)pCx}_`?e4JVtg4pub8KM} z)vW<*X-cwfwg)r0@EW_dOeU~YwZX~O(~l9shuF=Qx%cczc|)5d_$2*+ga#?iI+8pN z{&U_m^Dihy|E2CZ`=n4{w!eZfZxCHW5MJsCru25yyE!D@#S>K?OtEVcbO33ZFxN%} zzWIEjqut;HMqFxII1xEklC6*-=~F(w+hg&OlO{-5B`ho1(?{L0$;Cu!h^Z~}ZqL*K zEZdXNPR&$K%iCTh36c5N0!QO=UuX#ihRlV^wBOhOZ5}wy{DA5J(mB_GoUxF{bDIX< zhCbiCZ1sNRe@dLRD9g+l; zp35_6tKh}i^sH;Ydeo_)iATay?0h|&{WF`C81iPDkE?*TRs#1)%;4gu z1zpw7QGe{WJ-XD_KZaa@fx%cwc?WHf3x2qf+Mo}BPBTLwg7l@EvCp8lA9xJE!37Eyrn>%C9%MCY?7|Yp2wlsB1&XyQq(yJ zCbEyjehMfK^Y=J>I6XbNIko84YL9ty{9}v~WeZ{#V1<{v-pC|N9v(f)Mf6f2IShN^ z1h7$;z=?V1@WbI1&`OfX8F z=;7#5V@Gtai{hb?`*js#M2SgLi!<<d`C4v-_h}gmtrqw4c z<)=Q2RXb1IZ5DF8$*r+sjSgvDiKF&rXpwQW0s$DE0Z$075@T&05bMUEeb24QPuwnj zZPgu~%|O)fr>f<7d{iBr3 zm7TItI3aJ*YcokRG0jay*#L{`BmDAEzuW+L;}>zaW1$$7p_(!rx8Dn60{zbcA4l7o zHT9)+wlm1=X(zj8N^G&aT~n6_2p*|`aA%9PKke*Y25HfVAB7+0b5ifHACu|>hj+%B zaj>wKVa>BY%x!4u%kc4+q*es?S^oqn!`NZrnR;xA7kaFRrg;23dx5gui^qBuP^-)9Mg`#isA+-5SH$KxJQF&dXBd-KBeGsDVhl6!%M z?TZf`ijzP#sW~?-9?P@AWz$gyo~Wp7tnu2f*hBOMT)y$C0o1_NXy10j1d@-a)biqa z8C?`u>Q`E`N=wU~sI!8jn;+S}$1TG3d&d3Z4&8~?2%kk^IS*5}vO7Uyq=#`ZO`69t zs5^S`FdSF`8ly^}g|BE`W};Y@XG=(H#vDnJwan%-*~Ny>$j3s|q8z_lB=EfDC7E1R z;B85Lhz$@8;j3Wk#n3IEZQ}3DCrg1-{NlM*H=$_u*Qr8S1BnKYKe>%nd85M5UPt*+ zVVS*tu0gECg6XdmOt)DX(F6RD+&sxA3@bE@2$z0kE5l9Va@rl`vm+x*9TdK2ZpvFZ zjusu;H&wwjw{>JY-Tw?lZ|3G34JrR_kajGwcYGhU=RR5Lr*MR9uJK5A<{wf&)g=(c zTIrsgi2!PJt(RuXFc^p-D)yBSDTGz-OUsy1uD>=@vNAC`-0%DIWW{TvExc9`<^6WE{%C^)#Pd0f_1Y zH;}{p0@)2!=+kfjN%c6{L;9a1CelkQzdc2ka!74^P8geix7FiGI`9PS>A#(QQmiqq zJbb`zWdqZJKUp7Q{u9$1DPi;UdUmn9h+-hX>TqC-7ZWj+04FYve&?4s{7t{*B<}k6 zCBK{~&7>ha)!GEhjDtnJR?E%Tw(bS55s6KG=;8~`e5$?Y{q9)s(jd2F1M9R2UU)`$ z2}YLD@pP-x^xNANwtH;kB;xTjP91G;o75?Vb}GY9x_R}x=g2lVny5zy%A4t+m(Zed z_ZTUTh2>+0^uuj#R4u++m_`zoBC2&DhR-o&>$_6KY>^q zU)>G}mqwS;3Vg0Ay$G>c(N0lG^U$@c7XZ^5t$w@65>ySisS@jGJ^%#X4B#_0T2A!d z?fAsYTduQDk8M`gEbF?}B>dP)J2<7_A&cdkcpd1`I+e5@ohD(CWnOX8y* z{roT#;sfafzJs4`n|_e2YbWpIjk8;nBX@|fd@kVs6`Tf5s`q+sCaldHq-2uT1#-O)u@O%Q!@Q3 zo6xU|@_?w6;x0Y8@YoMaZZ9+6qdlGaEBe^L6cc4hXo=zkuZJqN8CI{LJ${KMP!x*( z&7}=5buxqESR02VvNn#gY^7BzxJ~;L!bCnR7eEl)^S)0hoKN|v&WpEV^T7f33JVXx zCz;Zv2``L}vQetitapzEMbcBkQPsvg!`cqB8{EJ~ik>|$*{n4Yi33Vnl!ge|cW?2e zu6V%eJao@blxDD%tb_CPS8VQnO0xa*aq{t`BlfGA0>tZip2lu}rBf?oUy+4H(4kHw z$G%Ub9db@#r{>-YFD!d6uIB_0 z+7j#p54`?RA5XD~luAc*Pf5N#-8>m+_BDg)4{^I*0~zDNKMD=$Vm^!Tt`u_aWVj_I z^Mx&&wc{WLz(!z&6nGYdr+$2*Dk1N?Z}Nq~$=)a6?qjUAkEr$c%nedJB+HcBRS)^gypKuFq)e!j~6~?E^QohDLEbX`V0)b(3 zqXMwxL90i}459jyt4sSvv#(7G3I{i(e0ZdbT!Pm1h`lavR@IA07qC@yx3p6rB(a*qC7G_%Y zL;rLLpImd|UOxS_CqY3{T>;06^=;}VD7|z9~w;>}+QxV;qh;#S0ErF>e6WM%m0A7&s53IF%UW zpL9!&qPDvAIn)8?YY_uqa|?C5rXSt+}DjFc4t@w=D!u*7bxMSdtgn7kebWNR83Sy}Fgut)8Rw zO1M2+s8?Jy4kZJ{hj@vADNJ3cDHf1pN}Cxvs( zn@859YA<#8ExTQNFrHf?8KI{Ag+Gl?|37ApY>dSx0EW7g*APe`V(2z)+c-9af?8&+ zQ$UMtGw1LhZqIwufg-c>mj;pd7N;Q`4sAY2XFY2l9TuPmvHGi1#%uo{q5m+F)0-lm zo`K{(hqNXomgzt+wwmn+N=oAyx};^IsrlpHOT2W`O7yW$&P)&=UG7AP$dk7ldcsfc z#T1lLHd{)VmCiOVXxc9keYtoYgWWCN*#ELgQ=XHG_ijVW?Zs84RBC3WdYhaa)g`bx zr33nv?}=WOX_+DnkT`gS^3^m`lwnw`dKe}nnqtCTm|rOh3sHp^>IV=>IPs`+_Ch2@ z>iWiObzO`Jo?i>HXLA}voY@Qp!5Y)S&Rhi!g)BGzCVvEV;UtGezU_*$gLPDa_0<|t z&XP7fvn`{v(}p#lV$or7Oq(Z)17h8U(@&nAa)wr~RTzg1RVC!#5N0G3-+Z*;iS{om zSmK$dI*ei~gLl+Uf)0`;$)NSe!0V(iZCjnYSvNzr|a*1gY_B;SswcKuRL@` ziM>styL7LUN%aM_s~#CL9ef9&5yUK<2pqpgCX41h{0LWYGl}?PP=iVfdiZR%DQnLD zHrZKf*5UPnzhCtGt;ug1Gy%vle>{b0lhn~DpOl2fCmc(rHJH*p?S!wfw@t$$rk3{J zTslVm;mn8b6eiVAhaCM)kHuU^=YqCdNGxC}=g5QOx4YSg|E4AFy`3h@$n#)NUZX7HQ_qrSzwdSPXZjaeY2*>(0vWs+b$5zSAM9+zlPZ&*Ro zXMwLaM<(SeOfnmc1uQ>CZ=fVOR+k_q1rOW}r`c)r@AD?fGQoeS4_F9!CW76Nj%IKd z4yS`ZXB;(NRBSMNQ$jtO}3^$=v_FLD$RWM*2gz41r54xhRRFKCHoy1}50lm?x2>A3@Gkgm^~yO5uZiijl%e_I*s#bqGFky% zLFzjHg(B)$%CN*nE56u2O(qZ2&*<`2ei!(zuf5Z^tb;Gl+{za7UysS_D9VsmbVe8^@rB$F9TURHCo!z4^))00j{6vFk*=>vEm>RH`fs5r3Q+VOJr??~!4k3e&wl+Aj2FjmfE1!k14bSDi#3k8a

KZf%8yp20eV5k6Cj2~{n)9vWhlSApbs~0bZ$b7y$VA#ilnvfu^%wW`LOp^iBlIi<_`tY{lps8Bv%lQMVJF2-OKDs0l3(Izhk4Yj@&hV zuRV;4gZkHCoC}cxGnE2bau}}K=3655>uDRGqj<%3{uzj<73Zj+1IpL$^Sf`pIWEB^ zm%Bp~x)rrb-GC_Sd)Fv$gUGi-=F>nu`H~tmy7LbEZ#;eumPRJVUWKnN-(Hzkwx=(( zQ{)1Xm1dW3TnXvwU3o2Iw~EEeS;@c5yqZ6uS^sR~yc=PO%sqUC=fdx{X(EZEN#0#= znLf#en9#Y6D<;__2UL~+-={VnN)C~P`q=vvh&Pb(T}H<$TJTW)5B)r-j-tS36ar4sy7=1_ISE>{a9H*MSf_$P+XOL! zoMt#k4^lllo5YWeHX`#fg$0Gh6W3`tDBs5+I5LeEnWJ_QE(Ee#Gw*kr?L*F!o(xfX z=yvZi4Q)MYOt0EmnwOoi*28U(6ft;Fse7pKV8Tb3+KX|d?(#nwXjVHw@?VA}>acgj zj#^*~wg!dmpZ?b|wA37VPTACu?y z&iSnHn?)~@G>Lnld#`JC-BE|!~+_c)yR199Gm#wYsyzgo} z4JqY#iFJ_-@rM$l9Z^Lf5IF85Ho@I!8_Dqzs!UA<`F zZ{?&ikT`Uyy@8o{E_4;BceZt6D6PG`F~WGt?PBP)a9IBtX>LDLc7L~)0h&7iV#EQw z!Qg;?gXDLYFKAgh+HC{L0`D%{Aaj8@yZxuspF?>zEV3$lb@g%)P95HS=nLNZ4|>?sYS)^C{{w03iZfFL;zryBUs?i6IYRkhEU7 zCPRM0i?os$a#Pc|Ml$?Hz42pgEAZSlR>njt#x}Q!gXziV!m}!*&ge%EUl72;3fTJ3 z`S&$S^SUj`DHr`4rZc1f03_ofZrGCVOmn z3Y)dmimNR@bP#cENcUc?m{uAN%lJA3>X!(keOI?o%`Bw-GU;87=U7zp$X^l)_qlWB z8qIou8f)|7dh@*yQxWNBZj_4<(?y@KBuPt%b3*7-G*ZAkqN!RZcH7liP1&&~6Ppd_ zVL|$_U|qGIxOaWR&&*qc_Y4mYX3JDBM-@HRD9PF{dB||gE|;)k%q0rmWCJ!Z;>q7t z`yvLQYFLqJFeMfOX&}|49^p+yut$t0>6|m5Sk<;gwb$XgMtdG1d*N5&D1U{T1^CygoQxCm7IIqGM9;G0Xe0@E2?;Zm*HlmGCx%Re7aze;Xx0U0BX z-tsINDf}iBct7Z_z`TJI>-ui0ybe_Oe^_mT8H1SW0_VN;Xb)SGQ)amy30I-B#(sVR z1cZS&lG4I9Zd3zu7(ACse#|5gMX*`fJL;lPaq!kJ`_aL12S1T7NT0mQK*;(#(KEu} z&0{YIPpOOeQijdh>?sEUv0cxDbN_!DMomMO$10dZJMPqiJPwe` znZ{GNZo@Aa&I&-`e#3s-pNTo&pgczB z2~IpXrEP(kyS8gUer}I#`+^&PP{!M65J-a^jxpnA9ylkb1-hs ze*GL=F;Li2#@1APV&WbrVCl#D3d>m%xm%obKg4*SpA^2=zx4$k`zXTKiP9{8I5%1F zw78f_2ue*xPteW73LoF0e*4|Eea!L^tV{Z<*5eZg6ErKpRxOb>7BDJl&1550Ch_HH zW2@#N)T>d|BFH0XEtdKJ}lsaQgcj;4ms!*JC2ZX_`&a* zkoJ4LPf))$T6I3Rw3Q&&8AQOk9CGELy9@dWKM*ExPj9c{d@)&28&o(p6LZkTFE8gd zBUmVDJ?oGmj}iO+o44bf8)&b@%405pUzvA|rwMf*BSHx2)10QU`hJ_$~` zZiQF2$Th{7nF0s+^4rZxZd2z^}VkRw0e zqg(gKJ@{^IQx0|Xnz{t~v75Z3f3;_c#vFcaEIFa6QFI8^FZw)v{a$m16)t=2H~Se` zt7z@>i#C1-|5h7doen5)+PS>?GKoB%=_0@BT!hlLw3KHN9rbckU*Ahjmh{74Ky`$6DG ztU%gbX{LfhnIu0(hwEcP=hKk(IP5bOA}+IeF=+TXvRWMV?Gb65(c#23YK!bNR|_F< zbKCZ)`QLMb(rGR}4a&^v&ozsS>|GJQ+ng=8{wIuDaRLU6 zARXjPB_6?37FS14|5Q-bKyoEjXZt|YXpDq+<(*fv^^RS1M#fB0#M*PL& z^#H6LlDS(;W8L-z8>#PC0O}3UQAxh^uiUsaX8%|sJ36_bC-G40<7Qsv5K_T@SXnajIUw(ArbDh@$r}#I1IF2R_1$%U z&K|E_Z*Q2Tg*3^ax}bgqpK#?xg~`~+MTdfL6G>U?fL2`e1$~)}vw$%8j1KJP*l7eT zkrLSPY4*M`)yg43Ha6{2o>3GnzQtY#a|LLfy5gvfy^K>ACKl-<4S2sr^ppK?eFM{Cg4mZxJC5TWvh0X z8lC_j-4`3%f5xqShqDk36QdURVW1UX z(hdt~=;Q}XeH~}-Wo1bUY?oohJMfES{DYj;_uLNX$^@gs6D4)>NqT`3FlQ5ivOtnr z4uSi94JHFffbYE~<*$BF(DU+!#I4zncC){Sk{qm!qJHB(LQ$y8s8psf13Q2D6|HF| z_}?Uw%+>0N{HGJUC)pujD(zvgfKMZaVi3%dWf}v-Fb-GAwIk3&&_66Y?6FB0LI|jB ze#O&p37w(|N}fhLG)b6=5v*~DXM$-gOaEI;YI$w$=XzRa-cwuWA8<>ynvOZl0QVcI9x;sdagh)-_Ih=nqUNMSL=k5=HW`?!8o#KNQD?ja8QC4yQH~2|@|FluPF+D=uCnh{fH-<02H?{tWe+KEo z&GBXYiD$;q^CP5(^Y&jV0_m{lvX1!Hr;|_;I)M?q>rFGXCu<*8oo+Zj_Tbqn&A+}we=Wl4b$6Esz9%_@c8M^Xx)eK0? zKRi^|MNFG~Qn7dL@a*R-)mdp6Xd0f2a>W zOM|{XFqv;otS81|T-q9C{mmTae#XPB23f`^(? zQdcav{a``uk@`xdVvd!6efX0*9rLjERaIr#gDWV+?sYQfH8*h8CZ+( z53c0(j|GJUIQm6-YBi$a{%s~)C1s2Scq8IP^MHCmkgQ?mQJ3sA$hMp<&-_z${D;L4 zpZcR)Jt#?vl*s1nX1+ibGv^+w|HIibG1Nlai@~N|Lg7|Ydl6OBC>nkXpRgb`Y3z_0 z_v8O21$e7pG9m-|Sc3be?K@D#{2NhT@ZP9A` zD1XyQ#PG@M#qCNoM)h&{8sYEtjcv7L7Ljs59=n?*Frdg;WDBsd;2JaSw{(Tl00^xp z8yzNoD}Ok8A3kHb;WkLUukECm&Gb-@i#9%R8F}0jzw;Lbpg7`GvfxsSt&Lyvdzh~n z_IB@->+(-G4$`KoNliYkOk3_2I&t3Ag;E|y00oE^h8Kja`@4Ue*E>on(`twly?IG* zsCU=Q)GD#YBHc`B-`rP{aav!1h}EE2N!K;2Ve3MD$N+H85aa_II_SD)=&rqa-Bm*S zxKfVIEn-M<*ItGVnqd;ae9Qnz;7H{dV!LP}^o8FVtJ#zVmA*-^=7#J!>kipdxM>Yh zm2{bp8sK``Es4bkvTyHNYz8d{ty0%OGem+4&LvRd3jln@{UMhNPEXIh6YpOU&Q)-5 zv}3XaRUWydkH73F$QZiBni9R$anHQTevOk9&VKr~Ip-mZZK0}jB--t3Zv4-}-78i% z9(4%gwv1r9UN`vG{-aHdgx>E#*8!3-vthOZE({EwpQ>Wa?CqH`xTAps6p%z+UXUcS zA4xC!KVhz&L1Jmz!&{}_*BjY#3d<|Sd9qmQ877&j{VqF|>l1$1ze6?J_}8xFR$gWA zg;CDGPoT@qi>a4(wwR&ea$aJQswRYsG2B zuDK)(b4mJxVrbIV%C6RvA z`eQ}#DfaMrmty^}es?S^#Gx)ppWLOytewC1CVY<=l@;gO8!d>r{!cH>HmKv&mPI9g z7Ics+<__#lxR$xQ@0AxmHQ)Q21Y=F3Z7!kZ9a|Zacd%~AM)arpz*ge{VbL1ImQ!H? zORk@N0E?OzdHGC>(9xuCulB$yQ5i8;WQ|A4NF&uKT`0g_QF9@J1Ugi^jDVI;yZAv? zf{jq!oiN|1gp&z}X^=Wh592+{@gMokYV9wW8#9 zl+}nHj16KAQFR*Q?dw-c56Pbj_`0b=p|@=~U4UtXY)7VIUD_HkQ7aQc8uUeKWw>;4 zsO0(Q%dbMaRFfnYQj>qqS!xAow$3k5R_7In~ZE=K%vdCc4` zKZ|dZ!>J%ay?*NA)w^>IT>3)) zJh-#|x!q&6wl#G0&`hcGtuCjMVlXE)Zu_)UUStnoJng%E?V}Y=*=}9@;g}i89sjd> zWzy8&qc5w(cPu9ZVNyyE9_BMSPKU3^@$4&hfV7okK2t?ODPxKKjgQJY6{>H|#CVMM z6^z9-7r^>UzUEk>L9la-C8Lo~x}ca*A@J-x`}Q$ZsE_zWXu2erF} zH5aB03eDp!M~1V4*qUNRIYBP8c@xT3mLq_8Qm8RaKwJ{J`2GFU<7pq2AR+LT#ci?=}yMNB4}~LQcDyJsW|ipmw9*L+MbfOhfbxl}89c zs@RZ*92z5c3xJHmB#gdcokIHyyL;~Qbx-ozNUi4=9SvR}-C2vC{O2nIZ4PzqiI>-Z zI*#|4q+Ux*?l$yfHL2U%$?eA?W&Rc?lCfjx>fii_Lh1CJZ2|asOn?au0w{Aqk>C2Bn@vq#kX9g%CUX0fB_lM-y zE$VB7eu#IW>A!FXFKUnR!5bb|>qD>&3u-~CHV@ZrR&K(EFr$9-SoRi6GMS%415Xt; zR~C;)qU07U*zr_3q(NBllr3Zxf$b(p%J%bBfU^T2B4h0z#k)Z^lxhDGl)hZmT%93`NWgc{R?-*N3uJ zh>5QtWY2*E?*Ri3%{D;MRsyd=szSYQMYBZd28rrvwBEhdAkF=GzTn^SCF$Ql9}-mCuAj1M(h@T))8`&PB$HAx zVLY}rChgGf`Mwj|NXj-KBVZ26>>L-RMc@|A2^@XXTe?MB(ZfH;XEq@k7- zHoua&C}3~?9%$>n%(cL%U^XCM{FYfOy$+`+8}A5Y7C&QRN?6_-Ksw?KP=t#NF82yY za0#v)*x^_$6i~Gg=Q;<=vLj77VFOF1UKJX1=(aluHfqNiZoA$5uB0_*1q^Pz4$YeZ z(h#hhcrcYvHv8OLOM9WoUW*m$_HQ^tytYuBr9fpTJ3?b5lwA7=aTetnl|ox>Yk^cd)oX|OdRj542a@KpyyI>jmdSS0-cgqds1L%4QYb1mbN;PcTiKMV!{#rtt${w!E zrYMgSvfA~-5~RI%QUo6(z1p&4h=f-X^KdyyB7!N=0QqlnP5dM;YRfx5*W9(2TJ5=389dZ-SIPA# zj(M31`WE-Ybyni`lL4(9Uya%>8j1= z+f(DE44eFU&*h(&k2h)4UQz!ez#6}TL}_7bdj85`&a*3#KE^v{$>`Xm6scu0CnSh_ zjDxf#Mv|#W|FNk9jUk;r#=kTxg7tjB*TB!sgoyfh78$NSvWp@2jvPMowcN;X6lX^0 zX$079`e7A5r}Ql*fnE432ziv5W!0{fK}7F|))~Q~ZC-esqI&P!4b+zrCTR@E+*{RC zkcY3wmf<4c?^?@6EAa=QdEq?sQ^1X@Ivb@9YEgCR(HRD6B$@Nlzc!mdQNz_r8y?r0 zobz|Ess{VT*2@!ssGHA!j%k{dgY~e_rLUD{$FBx2vYUT2V1LkXc*B|uiS-&CG%xS> zrTy8T_#E7^MkU6ti08N6iex9K zTgO7%`}xzfcAD?m22$ra`MD`o^FB3Z}*!GJjVY=q_w2cCHxsQ@2vU-5IOd+P-B$ofQja~`nTIyuRTd7JHqAW?PC zFtu|aplxeWAE&B7(tbzOVQCYDJl#s(ky!M%WI^gcw+T#JrSyP9-z&s;o-s4zkV2&H z_&Yb>>SFo`qwO;XH8k9jjX$fQ8afGn!S6ZRJ%e zHfdd={yC1ou%aP)Byxv(*YXEIR+n$wLM#bVfPBsHE7rL$^MPNB3H`yZ{boNz&ISoO zUAHD)`SD`&0E2jj;+?02_s)T?uMphw%@@EHV#O>noO461)IUW#_b!|*aB`RKjm@l8 z@Lz4e!RhJ>H{;@UIHJ@XdgoQ!Bbd^V%c^@~^|NHpy6H`?h~cy&BG1ZR$MJOEtDdQ6 zFJ-qzli&Sr0{MY5st5|VA>Y=3G>}G|_yaO61^}%Yb-Rx-$8hiV;j!N9mv!12+4>P3 z=U$JqF7DBpkgaqr66RJah0IF5tuW-)50ja&u^aXo{GlcW0ukm^a3`II%4uLwm5}sN z9{&nE%Yv${*m1<1(qwdMM@c>kB|)66KzPJ-3(k{j%&Nb@x*CYis!HKc#A@~=xqD#bk0&W`m ziWuTJGHTqJ32facFP~QQ2|NgTpwvTV(inicN?y641=XKan2^z`+Oq%$Gxnw`Q2th0 z>aZ`a3xIn$S&8G*ev#?AVmu;J12qHBO%o$+wT>V1#%XV9`P3z`daI4Ruy%U;t*Y|u z!biHUzedCmY<_6?KFFv2)I($DrlNIYscC+L1=Nv9AHQVuP$%QZ%*6b z6&JfF*WdWwSmAqKn6>3f+I1u7F9><}o+2+t|1{a4^8#>^j%fSg_1{(ZBQ|9DiS3g< z|G1Ie#kK5u@q5_&^+EnF!?jQ=SBpDgR{5R=kNCq6p%s7f9QSKKyH&sC#v2P(0R&8p z>RFai{D_HsWB6}7KmIWzLK@0nC)S$+>1-vUUOui3=)!7|+*uGe&PCmHfn$SiK<_uO zv&inQ7t-@h{Fckc!fkDde|nQ-qR8ua!i4uoN20UoH8r!=f~TJR`*wj#Ds@;}Y{`ab z*Rm$}Zqor!McN%9c}=2Ak4V*l!}@tny<5xQ!_B%uk}|>@#QC#j0bQ9`^CNN7N9=kR zcWAXJz(4OLyuGvi5QPu@9U^r3n~Ti2(LRCyg#g{JSQV_gA`=W8f;P{65!W|ByI=T| z*33%mFW%kv$AYq3K<#d*8K<%wRt{-*8LGOtuKicbM}+xRJr$UD=P%Dp=kuZtdE&K! zCv}ecD}2#623=HeYdmn8I(r;R;Sj?YY?{nbZim=tvbv*)~ z66D4nP51E+JW%X@XhEinNF7aPBlCqo=hI9Ml(16?GQJqR&slEw`Z{#4X0c3dqG#-IeM)9NOF)HBmUDn9|a6L2$q40}pcIfCLWw+3t zadC!@6`$PamXufnDf>mt?q4WFPXR$TrNPHk`OV&yXI{}wqF7Je;;nR`5`_^YAaplnw_w;s%QGV3l%PTqajhe42+H1AtWNf<)16~RHon*22htAv&?Tpzy>J<*nQ(>WG zTHI4EYj_hhzs4zLZ((gE1Q-N4+|V^;+u{z;N|ld+Oc>MNjx z?#H_uwG#nGJ6d_YvtIbGJuo>Ir6S&)xzzgj2Xwf6?xHz}XgN8ELaqlFm1`Ll4*|9! zf7WXMx7v#rZ|qS&TZvmo5R#`M>f%F|RkZlxj3_*R&8RNT7Jo?5F9f8q-G4+Ckm=457niD=_viqyK z6rlMKvOGm$o8A9CEy9NjO+r1gLBV}`PdsDrl3b(ky>JI~oHX(~VTCyH)e8#|1Vi?d zx4)-Sq7b|7l*c#A=k#t@EfZFf{az<@ zTI;KZ6Z!Y@J`mrk9BUDB5~L#EP_r~_p{l9PU05%*fu?EjoavVB3EEFbXE{2S+FyR>BN&_1+(z8wC^Q@|N(E$p1)g%OI|p293+1(f&8gmmFx^Rr}`uw+E8letp=)K_jjCqIFjZczP7u^AFN=`yT0 zB6rfae}){3!(61(g>SGwW z_2x?<^;@&1|EK}nAc->Jh2L8dQ_r-Kt` zC%t>-1#jWsJr#rn@nidVzLa;F6OgERKAyd@aK5xR5`oztt3A4Nj5q>)_k^A+Yi1KE zsFE!VJh9syrRiU(h;-3M8*!(oq#U)tMM#E{;C2A9cDug25X|`Z!(b5ExI$qQoq}3NAuEx^9CH2 zYCil1lu9K#9W7hp&v}FDH8~Qw;#gh-#Ctj8gkAYM6ng_`A&l%Q@r($Xx!dHbZvdwGNXH3!5ZTP|Cn7DK8FaMOUa5wn^-=)dep*D?{YHYbM^|fx zy0t@<(MLYMmACfAI&7F=QSkC3x{XN_XrroQ*p2}Q3YMU${<&u}-_x_$ z{}RC&Q)}KKzY=Tt^51Z&z+dw3$O!&uit}t@AoPhQ3lWc~M~#^w2Z?MNQ}O46G_T|X zq`q*E1!G6dEhl5-1wQrA-DWYnx!lHy_=~@RC*!LH2e4p?^seX81gd8GrRV_u7Ix_SWF%dOfo7rK*A%z*n1a7zaz6;nMbxTdy6W;7cPUzS@-r= z+}`kijx4q26*Di{KH`kaqG*oF)z9VL+UhS^M1T-Bl$>!BUWi~f_rS}+JUI%jzatr? zmaV~TXi%e$6Bc)?`meU3<8D)0QONA70|RiqJr&(5+{oqxk4;k^5DPf}28YRDYMI`^ zTFEBYZZ0=}xPeROGXToY^2IIQ$H;`aeFXVm*<~nTeO}y~AWhDKeyL(u8` z9&*U@ROmj5TQ`bLSG;p@6&Pd&e=hK$ z?fWCEQr2;JH{V$md({0bxD6~zn`5(nJ!h3rB-y};Xmr^JM&7)EW$xMp9jD9iPPYRo zcnU=G!m=ZwG!Zte{YkPMQnIRyMM^7*_IXvA%fX0=%m$<0CTtvz>|)7HeYUm;>R__! z(AgCqMBo%Nj;)j;)sYR0rnf!l&XYRyX~EzPhabk$k$zp>+)H7p6XKNj2KuG}wEkSW zYWigl;2oHtDoThK%8A2%wO2SSnGqqZBBfjVL!O`G&6>I3rzi}D70YjqEz$F8`yHtW z9ZRvUMVTMX3N@91M*_;ADb_Uly!&x895xmS1k+DKfuCF33j#G~o|byLvtnkYgUK(i zVz=*1!We3F#MJW_zs%uNmrhDkZ$63)eW-VRyp2ai*tlz74fFf8M6xfDpc4%pCbdUkeV5;yeAi+nePFDON5t$>c@Wcwx_jaqOjz+r&G z1i5fw!#SN~A%cC7$JQvlo>>FCKn1-+y`LOa)T##(S=@4(y67=a*o$TLE5Wm1J|w(v zwb@SnU2at#o#0OoQtU-y9ro)Oj>Ig6m*nbiPT#lol*56$HQ(_aw_uWM5mqKC z8rB>C49vW?t+Q1>KZ6x_X3oxmA&XqXZ zjiElJJxX2AGwXR>h5q^Q&6RTfs?A<+RC;6f=V{Uen>j2l13HSs(T%AiK-=-Q0>s&) zx{<*%KNWpAB0bZ}T*VV3q^&5n>>2}=$(d}bLCrzUgi~yBo~-7z>qcWEbbfg?B%81(QpP^_H$;%mF?ssS9YZD4j>8|Kp*|O6^OoQco+%$Q-Tw|BQoTk zmXOYP@;L@#Ha=G%=ojmsTRi?Gginb`V&rkVy?%}bb>?C&r+{X%$e%8bJg%4;UA&pV zksfs>sgyjRH0#IZZwz@GD#@do%UwgzLm4oKVfz$qO}_LLHFJUhwdxqnLl?6b0i8cA zgv5gQ@@4-Gs8=0Zm|d@~fUTUUUHwsO$APWBeei?FhDS__Qc!){%#Wi3liI&Lwaqes z%9k^+J?Pe!0?RMm z`uIp!2tm+n09Kx|HiCmZSYMr;pH1jDUO@NE%tst7y+$MP3U9m%+$Nhs<^LaZ}VFczj}ztC7ePe%*c9?Ir% zYGrHtrwu0wMWBr*WjkAj79Q8jtIUObX3YeVFZ2O4Nvhk1P|L(tAyn40+^opH?ZB#t zo{GtkU@0B}axCLm%w5Vk{~DLg634SO;s4RPpM=-o-iz5jM#dc*N(LvMpuQOI3O~Q{ z3;*~lwvgkXk3*zWUluCGW%rKtXAM6`%R3?uQSWAAR5lu|&j_H&B>w6lVf<)0IC>>a zn5$>~%eEq(0p#EWr=?nMJi7$%OeJ?-s-MYoNhdgpV$lBXXd>iFAEX;GaqKD2J}8I^ z*xOhODU?$zxe07Serg**e>N3!e+{7MB17x`4HvEoKXz;|Nkk`>flAeLC)k;ckr49p z-zezN|Hcawz)9ltY`4^1Tui`THBq>sj#x^y7M2ki_K?V-c+a2&9|oGq-5004L9X-pi$To)Px>L(?(bCTo;9Tr z1Ekp7Fb@8?I@WGePAkr;vYNvEK~&Q@Fq~z+M;P|r^CMlE5z6;aqYS4nc4&i^pQ3-1 z0(JUk6mT^3Uxwkz5)bS~YZ`jU#&q1y+2*jVdtFxN-j5!}_KKT_Ovr%>K-NGs;AnhT zylM5Wamj{hi)@kf$AL43!}uakR%OplY0!JPye7{-7c6|uMOR+^I&j=e?^E0T_lAU5 z<-$bq8Tb(gKr!ty%hi)2@mDph_UXh#v?@Ik3CGBH(=w_a9QFHlYu&0giK=_9B@ z%9xEcj&~hlF?lJtNU7nQ2z2~S^n6`HZ)?=ma`LAV>l>%|t$oQVXsYJx^%Y@21F(Mj zKZuf)$7sg0>nCa4v6%1f?TtON+_6O4)#tlS;`zec1m-=|f&|pxH>$Q4BzOM9gosX; zY8>FS&y;_SPdCOg0>&`c7_;p1G!<&#f~UI5q7I>hK0EjBEw}5RcR0%_*DG^o-4j8U_#X&tF*YXMACR;adsMd$NcDX4{|mqn#cTT&ydZz=SJ0QEUKe5g zolqWcglUm5kZF17sKr}vWEy%49&NC~X-swnRERf!g`<9dwD-%deSa8M*Mf+O^!~b^ zCR3aZ4@+Ig#E((S9wR`pY@!9`rUF84Nr}-6Im)eeE8X*{t#Q_MF;Q*El@=td0-xW( zDMf>WPe<=9dQR)w=*mxx<~ljg>EEM0`<9(dC)q$%vswIc2PiSVf~TxhSpwjIW1)GS zwgX&doKN{rq-6k96ze_w-P$@!R_rfQplxO{K-9g~OMe$H{-K6idkQvnIgR7sa_9Zt zsZ)LWD}gX|R^@m6HWbaSb^8%y7Wp<4YRzl5-w`hrp2}o|-v!6i(x4W0uFHzFs3uvy zw$Fc(6iL3-st9fn4%jYhdJDlO{-;sGwMxDJnT940E*@I|Y5f+sZeFo{aTZ@`yR(7% z&oY(kk>$5L$7sxH@V*;Y8$e+$(IwWbaT zEw=7HgW+J<^{2M#ilWQ52xq%zDHJxSG(Tepd5Dcla`*h80DqJrwfF7HQ|@}&0C;7i zWMu$CzlAqu1?%othXwFC!h{u~fBHRTBRuY@1i$P5TblZTC?cuoqm12LS5Z?sk-~9RVCk(Apg} zu-D9!2)Px0w39q{c|YR{&sR1YpJ7T}KA8_|Fy7rvkD9|B(QCTpc?+(cV8L@eD=*68(kHc$IU(*eF zvVn9et|&65E^z0&uM(J=0H!8-1aNl-7IZ+u2OLCpf=w1XL_hsoWMBkGFy>L|Y`UAU z^$=mxvkq@g+!gL7%iS^MEXvMC2q=9_{KNP*mFS5h5LTzElL#i(F`f%}_i=jv-LQ~A z=+%HifoNlaY)XZoi472{QrCfzt1c3VgCRe2H zX3hWDRxVXZ$lL{vx|B6N4x#r#IY@C%moo9QpJOUjsfuOC_iogtBfdwY)kmS|N=@GK zAY*!9-|=xV&*v9^yKl^!VSBcB#(8UyJs~O_qKj+e%rRpi4J$gC>S#ZTw<9OQ548I5 z%XVMwmq4clN;(Dp0$PdBD7es{1-GOUWQuS*IgE_R_Vzy*&&$RbqQW?zc%m=bkXyPB z05V#LB!HIr>yPji$Z{1fojrH|Qf?x9nBz!HZU~|*u|QB=&|?&#y9Yf@D;}$~YQ8oh zcH#|2^~;m%EC|ivn3_wZa%c~Yj3$un8=W8qW)a%0QMDbIN8Y z6jQ+AsanQJbVTkl*`9IH#0dmdw*H_Z5J$jsfL07g_NbI^J4vkdb*&HCG;p5!zgSr< zkpC{8G|imoca~~ye&qfh@4xY5A5jHRJdMJDx2%O(GT@X^N|<35#~Nq$4#$T_{-Nji zCN)?wV$$_6k7T$srDc+Mz)c(8t%?k{H6q7e4y67===z2I{MesE!E!dDXHh?bn5>^1 zvRT{jIQ<*LQcbNe4uK&L%@~$;L*N{htY3YA`a*5JJKK5K6opvUV6+08b%D>8$B-$P z3_(Ila)mLq?tj*yCBRHU2NJ^XjP?ZHj!=fwAhfw!>U-C&=!23&gQ$Yj_vtv|zA0NE zmw2PU!2A(x8Hb|r%y7ha^_lM(J}|O2@frWeAR3JHl%3Wg{n5l9bvYrcqOW;6HqP3e zK1}s_i+XYk=Z2*8TV+EMXvVjT_*-32d)IaK#o}IQF&NYEZMYA3_J{-t*zpZ`!1%4! z%fSDB=cFbV&ZlpTs(#fFgDrkl+i{`J?1~mkyr~=XZxj^*OSEx>Uq{zmSj`5^Y9dni zlZF&<)%^LZ-f>@1bK({(5_WidSZPU>;Aa-l83NK+GvG6k2TLXO7upw0-ULnsEKgYw zQmemVc&x%&Dy#ir{PumnWq@qd(06A>0#sV@5^cV8p2%S6O3g=E5lsq?U$X%{XC^g< z?BNIt0xwnaWcdbncAINwy>PJ4;7)5Z@T_MSG4%Bj-t#H~4PPEHMIB5k?V<*t$C(b@ zuM?~OjB~?8Ps}<=+vlz*XJ5d=sPPtMMJCGgBKMVQu=73Ff8(pd8L=b{Un=+WMtBXx zn@Zj4yZ()lr;r5+2Y#A%HI8i6yk;a)e@h!la4*g0S;b$3K^cVn1kC+D$75#_cAstG z76b1Eihi=_B$YS=UXa-UPhO@b;Um&Qw(}wQ23TAv&w@?}aFsdc%iwFEW#Baku*!M< z;$w=A%#gLP@Y4YI&OaOF0p-&M@apm9(gfGv{-Hy7;D$o(Wq|&5V@Fp>W7cIgagL8g{>oUma$%WzXhs zI58HU%sdcy>tFS3t=nQ)GflSj{C@Vszj`#R6q!qq6ULlHvDBv)Qd3PB5S`aZ5O)|} zqiG}|6gO@&7ld^$2%Zy`&Z;z#pVVS{IYVs_v&1!PsKwC89U z-EMmg%M*;iK>K*>|NJIL453%l=@8~}!Qyo;1#KZmI3mQz(yew&pByaPiEt!^og?zM z#WtW5&NwRg_9W^P@&e{*_*eZ9$X)S{!*vq4jZhd=bhMXeI8RDIPIr_J)>No_ur@G8 zlfQ!;!Y31jN=pM1a5O7R^4GWBSqmSBbEW2wEyV_#oA1Ya%AhUUC_hylQcxG04bOP~ z>?pJtXWT-Cf#VxJg-DSe?YZy!mY5uFvh+9c0)Cw$EQ%rR9#T4jICKFAc z>6#UL*8ck<&~EYJj~r$1gLJx6d0aOY7;?t4-yvno_+WO|`vq-Qlfjmd;HD7dv|`9p z5g9RSEP)&`mS}=s_qx|fs{Jbb3&kU4ZlUcsC+PulEk~xe?&Y>k^IIrLe~?rXls8{a zbEeqKq3&h?gmUodvffTKI{ZBfU8(IvaAtr}_pr;3$T*fDArb31*p%twYKC)&p=^LU zaTvGrS21;s{85`o+8dn;@sh`%bznnRhMe89T5JT14UN4O?wNLagN+1a#BcDf7}qGK zl^@KXBBrd2!J=0l&t}~qZd8{ZJyDlL^cy?2_9vMZW68OoXWFPhnf`#uNwTfG8j>O0 zfDcqr>ZxQ8=m?+lKV^K)`B?Sim5`2H=IvhkHF|H_u0Mc@iRoRx>}uja8H{^f$FG95 z^q4~hOgAgZVW{(6Lr0;w(e}c}8akn(709{L;fHX_l&_hSm{o&ir&4X^#xwu$NQYH( ziY)KU|LW}!q<-*7zr;MjEjF*rj1+$xr?iB`6fJCScuE@S3IaQ2a}ov=x0Rgv4te!1 z&hQ;jp6~(pn`iQBLX)!@b^wpZO3v!EwH;(Y9AfrnYs`)R7PFm66EU7iBgzOClqZza z)S&(A@-Jow^#jW^0vuLKd@pA|)gBxv*?#`|&#L7A+d(&(y(4=Uve>O|xp z*Z`@-1!t3xz@*W2O_ko(8v(B1`WGV}T&`_j9I2B}695>1$Wle6;enNekdao|26=2OhhNAeneW>qP{RCqyo(~Gui zHyOt;7nDqw@Z-t<&jTXgNpCe0AYJAJQ8LBgKx+Ae_tHkvr^DjYj~rPO<3laj8`R&nbZ$Npg$f{5E>^pnM@XVefqfj1hI^g-A0 zVLcoTi?6-OK~Zt|nww0Fj!oxfXhe#2 zFU-xZX!%d#ohZh=Fy&WAE{*pSjSo?uKvvl@CqJe^80XXGt)&brFd-%z8tm;=4ZR&H zq(6qX;$#ByV!5rxRx85^(#S4)9v$bCKZ2vtd-lvpAychgyGG@YRQ~vJhX~pIZUTTGFzTT}cPON_?Xsbo?*!@>+mxB$aVbTU%Q2cTeUuqqlJ@Nqb$Aue3th`&F?)aN(LMZX^(Y$B~H%RlaudsB(a%qu{!dh z8#l88G@@@J_pc)mP!;((Vta>j|~!+U53FyZ|_Et%glDe+prt=7|!?B4^t zQ!rlkUQ6LhAihKlG-fz{^jH5k`M8vA->o`8r{ap;J5{~)7p379GG(|zicI~ECV0$d zo4o(Hdmn4e!X$$Xd^^Sa_t=eXMHRP*aIldlr)J3zXkq*QMK}NF6;UgH>7@tj9D5Hz zzHa2&W(#X(^?PN`o@E$N!pa4`RL}z@ts{>z$T*?{y!ium=hHjk_5kIN$dZ-~X^7%8 zEpuL;uL|TCxd3XnJ-b25&b;V`U#{#~ra|+2j6Agd`ES2o5Sha?VUrd^pMBO9(SKOh zGqlF(Fc4=`5aC2MQ_6QU|2qEQqnP!6TQ^BlPY^nWHJ8BTqo$XQfAjG1dx#86#>`*BA@pAqLoM|MY z7uggg^w(S=n)UoWekH(BxA`fCL29xhs)(>COnB-aCB>k!=w_DJ$B-hk7h8&F6M@ZRQ5>b9 z!eKm>IcVxT9=V$uO?LO6H#20P0-&~H5PaLKw~-Z2h<_++cWZz1)n82y^P4K9LS>38 zf!pfpJ+A1d17e|C>#lMnu5$t*;zire<25Pamx|Z&?lNW(9Jto>$dpDIYGn}qonS4_ z2c$6SC9s%*bFWH2;#vAi?VJc)@o+!6NraqJBHES#Lloh@w*5ILzbLYPVMKBJR`=Oq zw~RBQHvN3QtDSK`p`KC`qtaut;qpgCk<5%xMM&zfpA8VT?&u3Jw8PB2LJP7R%fP9% z&{Qd1$1t`+O{+nbpr>zjH)!YyuDIE~zQ8@BwQ2Ho3 ze*KO$e^H#Nje*u;|5UJ$vb2WOyK0+(@S;q$s(C-~)3*r@n#x~ATZqwc&{IA*Ya!OIx~iG#A){T+q|8}ryHK}LG)?q-hym}mKPsB{t6@As5~N`@vu zMX$_&;>R42y)ZLgaQnFo4*_A&igu7@sKw6~{J3ONM2>?@4oJPJ+DMT}8!@Lghlum% z=oLL<(0s2-aSiFvY*;$Uk$|aHW6qOz+<9iM{rI@LL+gL)-lVVB-$mbmxWi?ZgAfzy zciQ`1I!_rzhDRT`yLAA6_<~N#G6rQqhnO_k@(6hfXR{ylp5xSV6ld%kAa$0hNT^lm zMBY}&aaDPNYU1<6++`)wcAsSvt?dB-l4V&*akY&1Cg#i>&RQLt!8gCiM?;4a-i_5X zH|+(NSd=tw1@>$Bey=cm*GqIUY( z6#d^;0nPQFJdG=t24<7}u!#_77%AAMIbjW0xipaoin&`q5!Jpx5 zBQ!>7lx@Vt8B1K#{`WC*WIvslh=H4xcP3u3Nxyn*8xY*W3AXGZ-FXLItV}PK78aIrX6N&t_K^h^5K#s{lC(#GpMO8 z+@1h|C@lzv4xuO=si8wC0@BorN^cU74$@Uh=pbD>ND&cKr1vJENJmQOU5ym!N^g0G zd+&QQZ|1$3H}igFa%S)E?3|qBto^O;Tk9QFgew0L{E-pui(aX5WOdfsepTuqtcA_z zRe%EXQ+9q`yP&t5ubqX4cwE(+x2r(ePDO>CVRVCP(k!!}BS3dV&mdaOEJ- z`YNGlxjKeYZ{|z~_?ry$nsFQ3f7?we-`&xCwveuZWS7hfd-Ep>C3$Jg-Th>3` zAIT>P9uy5>i;$`ZRHM0|}0V3!!bS-km!hu>9Uoe9Y@ALjxtlRQ__C4;S!vW-TRouqMg50&LXw8OAUS5tV~J&@zm_q`4!yiy?X+&JSBGM_ zDy$(?BmuEKVmxtU-g%CLNK1mOkxt2hoY98?d_ulIt(BDID+?ASsfRp;Vc1}i;ZrIj z^3Jb7aN8fop(h0LXsQuN7%oe3s#;`ZOti-3S0Thk8|;00u;a;mnb^qp2-J#nzD|N{ z$7N)*QT-Adahs01F4mc9p^0DM4N=#pdJfj!IfY#V9#|RjB{}Q7mN7%`%q^o(Ef)MZ zNO$Zh<&V|E%j}yMEraD@#(_&A&out_(8G^Tf4Bgiv%DAc4czh`;;|$;_T%Q{2Wh_O*~_md@vOz zKR%htT}h!=!+{8K@^w=~K`;A+um`@`KB~~0VxbZ)XVPZ2CE>Kh`8GzSm0Cl}KsqqW z@FYI>=uESg0V~FiDYzX*-l2Y5ny#9Cd^B2JyD*{5Q^lhyy=VMYWLt%E^>82HzGQA~ z{~9t?p$ig%kN77FHF1zuf$&!q_z+>BzbI_dvjK=l`I{yn>p z)o4pkG!YK$wNY5!O4Vr(>kFTzCiOcnoW|~hrp31>h)BFxIxd!w*t_phgD{o6`iG!< z=WTYdb7_g!AYGowle$Zxs^bn{N(cEtP4)p5#7yi2791#^6L*tP*jtHA)m}SuQFTy4 zwwj=>>i0uX6urTs5WRL|ZfV9613UDyRs)^()M1XGAt4zHF8gALRAiAO6g?AK3|@cE zy=q6)RbF_Y#Mc&)d779`t`fi2a1E5!p(;nt+6k$@ZNdi9aD z>#736x&i$L$X7@499be3)8{{Z#O~Hs(O&7#$WP5 z>&?|-GdtF8^Ul*%l{4QW978I?y>q_*cVGn8YelNK6EGp;c-^*%t|ZDqS0h)Sw$`?Q zlY^_PARFNypt*A^GeoecCt}YNuN|^gBJSlsXs!xlu1~Tb`DnsqC~j?u2n=9|>}lKI6#6YO7tzP=J#)NP!=$ItHMossRNT&rJNLuz?O zlo?VU7iMF8xeCv~IH{I*|#H6{04 zY`d7v*PopsE`gk_j8nQg@U{~n!pyb@P1NDb3G2!a?;_n%z?8Y(JZl{Xdx$iiF1A1p zLjd_4fj1lc@cYh(JG^^0j`bG@#PfLkBW!j{UqAnG*x>E%mB=TJUV6<|+{4=CB3~8o z@p8tN{O`>!(9tNF9sBa&l%<{>t3mAMUHSp$6+6kKsks{tUf>Ew{%`UjiX>&Wd<3_Ewk>t1_2hOyXL?)D*(2umJI~8z(DV*D!_CX z-TGdrG*618n%M%n-43wi+66J2tkozE>Rs>o&WWcWdhd^4Bn<-nOr!?sJ^{X(cjc=seDWsbv?E4yr2-PnT2sr$1> zU6}J-y6sG)ar2-=T>7j`JhDwbEXPq88&|@BQo>ixQhw%F7Z==gFa(AhI;*C9+q~j( zdD$|q?cIl2euelM^#sa7r}{6!orn?Fi>8tfsWal% z{PD}k%(%M}B6F2!?zJ^4EDqC>4VN1rIU0jbXX3T^!$CsU+cwUgp~fAoHF!@wWwI%icdns>s^+t+Ua5|mTtgrZ z;x=l$qZd)`dlBisETIDgW6-n}$fN9fIPASC@mG?9M2BJxR20!)9z5^1OzMQp8sK~_ zS*UJ)n}f|QgOm&AEQpkxdQF4CWlj$~$SUC_;fiqPfD{5nKzDGO5XP>>B$jG{d;3;Yqt(}N zJR!NC9(jZWEl^x#U)h~-b0n)%YYq&TXAEC==p@98tCKp&G|A8)*_ocbA3oydsX z8#_l8;8%-~#5nfJaJ+#V zTKc9B+<3Oj11v+XX}D9+LJIk&(0xzZ+o`y^lOCD51wN8QNz@j+!}h5)E}TYmb$p4e zdcI4z#DgxD!^E|ToP2!1Atmg~!U^1Y`*OkQ7;7Zz9oZG}S6}=kU^4iv{ZCrku!s8d zChkrVsD7dYB-6GDSXzAF`DA)yf!27w>?J;PW;sD|HUyiH=@(Pv&V$21h-uoklntS5 zsuI(E-ROLj3^tYYK|ocNht>7$n-_Jm)7J6*6)zD*z2wtT@v0IFCxGI!lzoAUr4U*x zb%min`w5CK^GRMox8gFb8)N1_!`{_BgFuEwF%FFp@{ug?B{3?k=x4K+Sf|reWg>Za zl{IxG?&shR((a6tpPx2vOvv{~>)AcIl}xR9a%0yf-sN8a3^`U zV21~W@;v$ZCqhMPjcwvdf^zz6mTvJAuCd@h4Q^sS3GXIlzAbaXmY3w|DP=9+jXfA6 zH=hnL$iaIG<7&L#5;KO9a0(c&V=_NDcluF2fv=;-JNQ*^nD&dO)#QZx@qj55 zw+(L5G-d{ASBO0o2Q!C`se*JiZIr<$wfi->W7g!%4?~u+k;+GD%fjM`Pj8R~!09D> z?p0iN0;@u`XUc%}>~we$uYdUNkr8|o)?3tLgLZ?}B#NbQ?By4H`cxmq7;k z09{N+Tny}|KEzG1+&;j$7;GIFrS>%4nqa+MSA1~d)Q17gedOm#=eMeak|4fwJDyEX zTL)`(s8{Njd>hSL79N=t5`!+~tKNG7xz3=LiDOLB%-D&4t&J>csZ7pAys1=_a?1q6 zKk>AgDM5$wzk`%kGln?E{XN?I%^ZWN{=cVjmRywV#BKaKQ_LFaBn2(W{~lck3Uri- z{u408TVG_MjPIW}$*X(8f$%n0GYc{*%gPz=-~BzFa;FhUQompWwXom>^8|X*1JP;px{;cSM!?`SHTK%t*wrZ{1}tx+V>Z+Nalp_`uUPpQ%OCj z4qeNOnwShXd7Sl#>{Aw>GgtluSe6q!3XwthdFMU`kMTJFfJ|HiOLfZmXrj@xkB{f% z?b%+mqLeMH8H+VEkmHGia`1T;d*&B`_k%wQ-J)zehOVQ1^$W5orK9r7V(YKoAXo3D z3Z1wCDqTvyv)p!l2+Hq9kpxvKQST}R$C4wOS}%35ca>UhOZHIclamst3a_qb^FC{Z zP;9-koyoJTAl$d|fR+m|_)(5P4wJ#I)vpECTzEo9Ulx_%BXf)(1_D6%Wc`@@Tq(M^+g<|d1$uJi~j+!SgUvmu@8j81F4Q|jyH|6UAKX}DQgO3mX=c=w?laZ zFvwiLS4KE$jM$z^r9h)|><|W3F)E&~;c5s??x0nUyp#KX2x}~aK%KQV1>QqXFB&!u zM->Ov6PKW?*d~GioJfTIju=0sfH?w7%brKwlnfL!$9~B)M#v-7%2b>biQK68CTGf? zoG#>!2Q?ilQfuxT%Xe~;bx%41IRvGj4RTqpxvSpsv7|zF0-FjGPpmnAxTF`;QJhmL z*j~u9azi;N(9*<>);-!(7M;e>=vAdHVeB{J^~GNlKeaFSTi@kP6yKzrE{t=6IDo3dqpkSlT63&6Il_banSsdR zYTwhO?)Sk>pfYqVjYInp%Qn3x9miKlg>aI+sqWPlj-{f>s}upxD?eVXdcU{{R-t5R z50K+7giu^;tMiCC`!I2Ig0;BAm#7~Xr%Wu)7`BG`WP!K9b&^DKEElY$x!HiQLuP1P zo(_1n=zMDmZojQj`Z11KpkD4``R{5hSx7WXX|qID?op6+L>TfKnuGY zTGD(=PI{Yvaz<~Gg5o{&8ITQ%_CALo6;+6aKni(j^eY(9ByB*!i26<^N>>>CsK5LY zl#3qj5}_G{U}PO#Kle%yyEL$Iy*V&orjExO#g5o$GH&%?my*Y_!ob@rx%eOJJFIlr zzXPqFV&$fKNT%+tZTvs5)Bg;#GAcT!X?jV@y{v^7PXDMRdLIIl@tKp>=Jj|#SDp2? zc-0Xd7vor;#TKcIfNX8HXf!DI0euf55*ec6+|WP}wjuf%x~?kqoG*_L*z(RHxo}9a+jLn9W&NJ!cW7Mo4-~zE(>}IwIJ|3l?uecxZsbv+8@13> z?5y;tVNgr`*+{u)2D6*JKRu|GyYSj#o^<;@2fwTgsaq!PkIt_RN%oZq$)2Q)_xjxW zn%9SeFmL)@iMQb^f%K8$R`1*&y-1VG6|hz|9KEg|#@A(@^_w9>%C2O8OBsDA3d8e+K7e?a7*xad(Ch73Lq==FL%C<`)e#*W^jTu*+@zmiD``u8_$Ug6KUC{AxSS9NjnPrJ=pQ(m`kpqQBb$;|dQZ{=geE4Jx2l599u&Hi(0^IXX*MYpnKoeP|=uP67T_>Jy zeIpQ-0mI?*?sgI{z|=UHgeQyNnKpcIBTwxJB=PZDbwj0$&l?^0B)mx=9M0E*w~4tw zX%>|s+*2;vWXc-m1YwTC%rT}Io+Nzlph!wPFCe5aLxbV}VV>*o;&6zi3VM69aWB}> zP57FDm@_-{8@LYjBu(Y$I-L-BXe#p^$ygbwT8%+Vz_tZ2s$eMs zN8-+V3=$j%E2O_Gz+gs}ZtJ%u!A+beVD2H$N__V=8~Xciqt<~`hZ;&E4IBH!hi|>%M<6o5I!s;9QpO^}|DEZIfnUSxg z&HrLF{b`3b$LIe*t)B!k+M9a5cLTh{006k=dDGAnW94ZhYwd0Wz5rq(q9`E|l#rRBNG literal 0 HcmV?d00001 diff --git a/Assets/SMAASearch.png b/Assets/SMAASearch.png new file mode 100644 index 0000000000000000000000000000000000000000..af934938cdd36ec8c669629868221add0a9d9104 GIT binary patch literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^4nQox0VEijd(^%HDVB6cUq=Rpjs4tz5?O(Kg=CK) zUj~LMH3o);76yi2K%s^g3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tW_htJgBdGz=yuSjQOFJp-Qv`LzZ zOsye{GPLGgoYwzZWJZD4WWBjp{v>cpe!OJ&&9RY_^#@}~h}O;0-A0FjhN+ggMwFx^ zmZVxG7o`Fz1|tJQGhG89vIsFUurjfgTe~DWM4fxA|OV literal 0 HcmV?d00001 diff --git a/Sources/cycles/renderpipeline/SMAAData.hx b/Sources/cycles/renderpipeline/SMAAData.hx index 6d0457bf..46e12aa0 100644 --- a/Sources/cycles/renderpipeline/SMAAData.hx +++ b/Sources/cycles/renderpipeline/SMAAData.hx @@ -31,6 +31,11 @@ // #define AREATEX_PITCH (AREATEX_WIDTH * 2) // #define AREATEX_SIZE (AREATEX_HEIGHT * AREATEX_PITCH) +// #define SEARCHTEX_WIDTH 64 +// #define SEARCHTEX_HEIGHT 16 +// #define SEARCHTEX_PITCH SEARCHTEX_WIDTH +// #define SEARCHTEX_SIZE (SEARCHTEX_HEIGHT * SEARCHTEX_PITCH) + package cycles.renderpipeline; class SMAAAreaData { diff --git a/raw/smaa_pass/smaa_blend_weight.frag.glsl b/raw/smaa_pass/smaa_blend_weight.frag.glsl new file mode 100644 index 00000000..720b8347 --- /dev/null +++ b/raw/smaa_pass/smaa_blend_weight.frag.glsl @@ -0,0 +1,122 @@ +#version 450 + +#ifdef GL_ES +precision mediump float; +#endif + + +uniform sampler2D tex; + +in vec2 texCoord; + + +// Blending Weight Calculation Pixel Shader (Second Pass) + +float4 SMAABlendingWeightCalculationPS(float2 texcoord, + float2 pixcoord, + float4 offset[3], + SMAATexture2D(edgesTex), + SMAATexture2D(areaTex), + SMAATexture2D(searchTex), + float4 subsampleIndices) { // Just pass zero for SMAA 1x, see @SUBSAMPLE_INDICES. + float4 weights = float4(0.0, 0.0, 0.0, 0.0); + + float2 e = SMAASample(edgesTex, texcoord).rg; + + SMAA_BRANCH + if (e.g > 0.0) { // Edge at north + #if !defined(SMAA_DISABLE_DIAG_DETECTION) + // Diagonals have both north and west edges, so searching for them in + // one of the boundaries is enough. + weights.rg = SMAACalculateDiagWeights(SMAATexturePass2D(edgesTex), SMAATexturePass2D(areaTex), texcoord, e, subsampleIndices); + + // We give priority to diagonals, so if we find a diagonal we skip + // horizontal/vertical processing. + SMAA_BRANCH + if (weights.r == -weights.g) { // weights.r + weights.g == 0.0 + #endif + + float2 d; + + // Find the distance to the left: + float3 coords; + coords.x = SMAASearchXLeft(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[0].xy, offset[2].x); + coords.y = offset[1].y; // offset[1].y = texcoord.y - 0.25 * SMAA_RT_METRICS.y (@CROSSING_OFFSET) + d.x = coords.x; + + // Now fetch the left crossing edges, two at a time using bilinear + // filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to + // discern what value each edge has: + float e1 = SMAASampleLevelZero(edgesTex, coords.xy).r; + + // Find the distance to the right: + coords.z = SMAASearchXRight(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[0].zw, offset[2].y); + d.y = coords.z; + + // We want the distances to be in pixel units (doing this here allow to + // better interleave arithmetic and memory accesses): + d = abs(round(mad(SMAA_RT_METRICS.zz, d, -pixcoord.xx))); + + // SMAAArea below needs a sqrt, as the areas texture is compressed + // quadratically: + float2 sqrt_d = sqrt(d); + + // Fetch the right crossing edges: + float e2 = SMAASampleLevelZeroOffset(edgesTex, coords.zy, int2(1, 0)).r; + + // Ok, we know how this pattern looks like, now it is time for getting + // the actual area: + weights.rg = SMAAArea(SMAATexturePass2D(areaTex), sqrt_d, e1, e2, subsampleIndices.y); + + // Fix corners: + coords.y = texcoord.y; + SMAADetectHorizontalCornerPattern(SMAATexturePass2D(edgesTex), weights.rg, coords.xyzy, d); + + #if !defined(SMAA_DISABLE_DIAG_DETECTION) + } else + e.r = 0.0; // Skip vertical processing. + #endif + } + + SMAA_BRANCH + if (e.r > 0.0) { // Edge at west + float2 d; + + // Find the distance to the top: + float3 coords; + coords.y = SMAASearchYUp(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[1].xy, offset[2].z); + coords.x = offset[0].x; // offset[1].x = texcoord.x - 0.25 * SMAA_RT_METRICS.x; + d.x = coords.y; + + // Fetch the top crossing edges: + float e1 = SMAASampleLevelZero(edgesTex, coords.xy).g; + + // Find the distance to the bottom: + coords.z = SMAASearchYDown(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[1].zw, offset[2].w); + d.y = coords.z; + + // We want the distances to be in pixel units: + d = abs(round(mad(SMAA_RT_METRICS.ww, d, -pixcoord.yy))); + + // SMAAArea below needs a sqrt, as the areas texture is compressed + // quadratically: + float2 sqrt_d = sqrt(d); + + // Fetch the bottom crossing edges: + float e2 = SMAASampleLevelZeroOffset(edgesTex, coords.xz, int2(0, 1)).g; + + // Get the area for this direction: + weights.ba = SMAAArea(SMAATexturePass2D(areaTex), sqrt_d, e1, e2, subsampleIndices.x); + + // Fix corners: + coords.x = texcoord.x; + SMAADetectVerticalCornerPattern(SMAATexturePass2D(edgesTex), weights.ba, coords.xyxz, d); + } + + return weights; +} + + +void main() { + // gl_FragColor = vec4(col); +} diff --git a/raw/smaa_pass/smaa_blend_weight.vert.glsl b/raw/smaa_pass/smaa_blend_weight.vert.glsl new file mode 100644 index 00000000..b7ca720e --- /dev/null +++ b/raw/smaa_pass/smaa_blend_weight.vert.glsl @@ -0,0 +1,34 @@ +#version 450 + +#ifdef GL_ES +precision highp float; +#endif + +in vec2 pos; + +out vec2 texCoord; + +const vec2 madd = vec2(0.5, 0.5); + + +// Blend Weight Calculation Vertex Shader +void SMAABlendingWeightCalculationVS(float2 texcoord, out float2 pixcoord, out float4 offset[3]) { + pixcoord = texcoord * SMAA_RT_METRICS.zw; + + // We will use these offsets for the searches later on (see @PSEUDO_GATHER4): + offset[0] = mad(SMAA_RT_METRICS.xyxy, float4(-0.25, -0.125, 1.25, -0.125), texcoord.xyxy); + offset[1] = mad(SMAA_RT_METRICS.xyxy, float4(-0.125, -0.25, -0.125, 1.25), texcoord.xyxy); + + // And these for the searches, they indicate the ends of the loops: + offset[2] = mad(SMAA_RT_METRICS.xxyy, + float4(-2.0, 2.0, -2.0, 2.0) * float(SMAA_MAX_SEARCH_STEPS), + float4(offset[0].xz, offset[1].yw)); +} + + +void main() { + // Scale vertex attribute to [0-1] range + texCoord = pos.xy * madd + madd; + + gl_Position = vec4(pos.xy, 0.0, 1.0); +} diff --git a/raw/smaa_pass/smaa_edge_detect.frag.glsl b/raw/smaa_pass/smaa_edge_detect.frag.glsl new file mode 100644 index 00000000..a5aa78d8 --- /dev/null +++ b/raw/smaa_pass/smaa_edge_detect.frag.glsl @@ -0,0 +1,475 @@ +#version 450 + +#ifdef GL_ES +precision mediump float; +#endif + +uniform sampler2D tex; + +in vec2 texCoord; + +// Edge Detection Pixel Shaders (First Pass) + +/** + * Luma Edge Detection + * + * IMPORTANT NOTICE: luma edge detection requires gamma-corrected colors, and + * thus 'colorTex' should be a non-sRGB texture. + */ +float2 SMAALumaEdgeDetectionPS(float2 texcoord, + float4 offset[3], + SMAATexture2D(colorTex) + #if SMAA_PREDICATION + , SMAATexture2D(predicationTex) + #endif + ) { + // Calculate the threshold: + #if SMAA_PREDICATION + float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, SMAATexturePass2D(predicationTex)); + #else + float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD); + #endif + + // Calculate lumas: + float3 weights = float3(0.2126, 0.7152, 0.0722); + float L = dot(SMAASamplePoint(colorTex, texcoord).rgb, weights); + + float Lleft = dot(SMAASamplePoint(colorTex, offset[0].xy).rgb, weights); + float Ltop = dot(SMAASamplePoint(colorTex, offset[0].zw).rgb, weights); + + // We do the usual threshold: + float4 delta; + delta.xy = abs(L - float2(Lleft, Ltop)); + float2 edges = step(threshold, delta.xy); + + // Then discard if there is no edge: + if (dot(edges, float2(1.0, 1.0)) == 0.0) + discard; + + // Calculate right and bottom deltas: + float Lright = dot(SMAASamplePoint(colorTex, offset[1].xy).rgb, weights); + float Lbottom = dot(SMAASamplePoint(colorTex, offset[1].zw).rgb, weights); + delta.zw = abs(L - float2(Lright, Lbottom)); + + // Calculate the maximum delta in the direct neighborhood: + float2 maxDelta = max(delta.xy, delta.zw); + + // Calculate left-left and top-top deltas: + float Lleftleft = dot(SMAASamplePoint(colorTex, offset[2].xy).rgb, weights); + float Ltoptop = dot(SMAASamplePoint(colorTex, offset[2].zw).rgb, weights); + delta.zw = abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop)); + + // Calculate the final maximum delta: + maxDelta = max(maxDelta.xy, delta.zw); + float finalDelta = max(maxDelta.x, maxDelta.y); + + // Local contrast adaptation: + edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy); + + return edges; +} + +/** + * Color Edge Detection + * + * IMPORTANT NOTICE: color edge detection requires gamma-corrected colors, and + * thus 'colorTex' should be a non-sRGB texture. + */ +float2 SMAAColorEdgeDetectionPS(float2 texcoord, + float4 offset[3], + SMAATexture2D(colorTex) + #if SMAA_PREDICATION + , SMAATexture2D(predicationTex) + #endif + ) { + // Calculate the threshold: + #if SMAA_PREDICATION + float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, predicationTex); + #else + float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD); + #endif + + // Calculate color deltas: + float4 delta; + float3 C = SMAASamplePoint(colorTex, texcoord).rgb; + + float3 Cleft = SMAASamplePoint(colorTex, offset[0].xy).rgb; + float3 t = abs(C - Cleft); + delta.x = max(max(t.r, t.g), t.b); + + float3 Ctop = SMAASamplePoint(colorTex, offset[0].zw).rgb; + t = abs(C - Ctop); + delta.y = max(max(t.r, t.g), t.b); + + // We do the usual threshold: + float2 edges = step(threshold, delta.xy); + + // Then discard if there is no edge: + if (dot(edges, float2(1.0, 1.0)) == 0.0) + discard; + + // Calculate right and bottom deltas: + float3 Cright = SMAASamplePoint(colorTex, offset[1].xy).rgb; + t = abs(C - Cright); + delta.z = max(max(t.r, t.g), t.b); + + float3 Cbottom = SMAASamplePoint(colorTex, offset[1].zw).rgb; + t = abs(C - Cbottom); + delta.w = max(max(t.r, t.g), t.b); + + // Calculate the maximum delta in the direct neighborhood: + float2 maxDelta = max(delta.xy, delta.zw); + + // Calculate left-left and top-top deltas: + float3 Cleftleft = SMAASamplePoint(colorTex, offset[2].xy).rgb; + t = abs(C - Cleftleft); + delta.z = max(max(t.r, t.g), t.b); + + float3 Ctoptop = SMAASamplePoint(colorTex, offset[2].zw).rgb; + t = abs(C - Ctoptop); + delta.w = max(max(t.r, t.g), t.b); + + // Calculate the final maximum delta: + maxDelta = max(maxDelta.xy, delta.zw); + float finalDelta = max(maxDelta.x, maxDelta.y); + + // Local contrast adaptation: + edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy); + + return edges; +} + +/** + * Depth Edge Detection + */ +float2 SMAADepthEdgeDetectionPS(float2 texcoord, + float4 offset[3], + SMAATexture2D(depthTex)) { + float3 neighbours = SMAAGatherNeighbours(texcoord, offset, SMAATexturePass2D(depthTex)); + float2 delta = abs(neighbours.xx - float2(neighbours.y, neighbours.z)); + float2 edges = step(SMAA_DEPTH_THRESHOLD, delta); + + if (dot(edges, float2(1.0, 1.0)) == 0.0) + discard; + + return edges; +} + +//----------------------------------------------------------------------------- +// Diagonal Search Functions + +#if !defined(SMAA_DISABLE_DIAG_DETECTION) + +/** + * Allows to decode two binary values from a bilinear-filtered access. + */ +float2 SMAADecodeDiagBilinearAccess(float2 e) { + // Bilinear access for fetching 'e' have a 0.25 offset, and we are + // interested in the R and G edges: + // + // +---G---+-------+ + // | x o R x | + // +-------+-------+ + // + // Then, if one of these edge is enabled: + // Red: (0.75 * X + 0.25 * 1) => 0.25 or 1.0 + // Green: (0.75 * 1 + 0.25 * X) => 0.75 or 1.0 + // + // This function will unpack the values (mad + mul + round): + // wolframalpha.com: round(x * abs(5 * x - 5 * 0.75)) plot 0 to 1 + e.r = e.r * abs(5.0 * e.r - 5.0 * 0.75); + return round(e); +} + +float4 SMAADecodeDiagBilinearAccess(float4 e) { + e.rb = e.rb * abs(5.0 * e.rb - 5.0 * 0.75); + return round(e); +} + +/** + * These functions allows to perform diagonal pattern searches. + */ +float2 SMAASearchDiag1(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, out float2 e) { + float4 coord = float4(texcoord, -1.0, 1.0); + float3 t = float3(SMAA_RT_METRICS.xy, 1.0); + while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && + coord.w > 0.9) { + coord.xyz = mad(t, float3(dir, 1.0), coord.xyz); + e = SMAASampleLevelZero(edgesTex, coord.xy).rg; + coord.w = dot(e, float2(0.5, 0.5)); + } + return coord.zw; +} + +float2 SMAASearchDiag2(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, out float2 e) { + float4 coord = float4(texcoord, -1.0, 1.0); + coord.x += 0.25 * SMAA_RT_METRICS.x; // See @SearchDiag2Optimization + float3 t = float3(SMAA_RT_METRICS.xy, 1.0); + while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && + coord.w > 0.9) { + coord.xyz = mad(t, float3(dir, 1.0), coord.xyz); + + // @SearchDiag2Optimization + // Fetch both edges at once using bilinear filtering: + e = SMAASampleLevelZero(edgesTex, coord.xy).rg; + e = SMAADecodeDiagBilinearAccess(e); + + // Non-optimized version: + // e.g = SMAASampleLevelZero(edgesTex, coord.xy).g; + // e.r = SMAASampleLevelZeroOffset(edgesTex, coord.xy, int2(1, 0)).r; + + coord.w = dot(e, float2(0.5, 0.5)); + } + return coord.zw; +} + +/** + * Similar to SMAAArea, this calculates the area corresponding to a certain + * diagonal distance and crossing edges 'e'. + */ +float2 SMAAAreaDiag(SMAATexture2D(areaTex), float2 dist, float2 e, float offset) { + float2 texcoord = mad(float2(SMAA_AREATEX_MAX_DISTANCE_DIAG, SMAA_AREATEX_MAX_DISTANCE_DIAG), e, dist); + + // We do a scale and bias for mapping to texel space: + texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5 * SMAA_AREATEX_PIXEL_SIZE); + + // Diagonal areas are on the second half of the texture: + texcoord.x += 0.5; + + // Move to proper place, according to the subpixel offset: + texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset; + + // Do it! + return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord)); +} + +/** + * This searches for diagonal patterns and returns the corresponding weights. + */ +float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex), SMAATexture2D(areaTex), float2 texcoord, float2 e, float4 subsampleIndices) { + float2 weights = float2(0.0, 0.0); + + // Search for the line ends: + float4 d; + float2 end; + if (e.r > 0.0) { + d.xz = SMAASearchDiag1(SMAATexturePass2D(edgesTex), texcoord, float2(-1.0, 1.0), end); + d.x += float(end.y > 0.9); + } else + d.xz = float2(0.0, 0.0); + d.yw = SMAASearchDiag1(SMAATexturePass2D(edgesTex), texcoord, float2(1.0, -1.0), end); + + SMAA_BRANCH + if (d.x + d.y > 2.0) { // d.x + d.y + 1 > 3 + // Fetch the crossing edges: + float4 coords = mad(float4(-d.x + 0.25, d.x, d.y, -d.y - 0.25), SMAA_RT_METRICS.xyxy, texcoord.xyxy); + float4 c; + c.xy = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).rg; + c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).rg; + c.yxwz = SMAADecodeDiagBilinearAccess(c.xyzw); + + // Non-optimized version: + // float4 coords = mad(float4(-d.x, d.x, d.y, -d.y), SMAA_RT_METRICS.xyxy, texcoord.xyxy); + // float4 c; + // c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).g; + // c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, 0)).r; + // c.z = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).g; + // c.w = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, -1)).r; + + // Merge crossing edges at each side into a single value: + float2 cc = mad(float2(2.0, 2.0), c.xz, c.yw); + + // Remove the crossing edge if we didn't found the end of the line: + SMAAMovc(bool2(step(0.9, d.zw)), cc, float2(0.0, 0.0)); + + // Fetch the areas for this line: + weights += SMAAAreaDiag(SMAATexturePass2D(areaTex), d.xy, cc, subsampleIndices.z); + } + + // Search for the line ends: + d.xz = SMAASearchDiag2(SMAATexturePass2D(edgesTex), texcoord, float2(-1.0, -1.0), end); + if (SMAASampleLevelZeroOffset(edgesTex, texcoord, int2(1, 0)).r > 0.0) { + d.yw = SMAASearchDiag2(SMAATexturePass2D(edgesTex), texcoord, float2(1.0, 1.0), end); + d.y += float(end.y > 0.9); + } else + d.yw = float2(0.0, 0.0); + + SMAA_BRANCH + if (d.x + d.y > 2.0) { // d.x + d.y + 1 > 3 + // Fetch the crossing edges: + float4 coords = mad(float4(-d.x, -d.x, d.y, d.y), SMAA_RT_METRICS.xyxy, texcoord.xyxy); + float4 c; + c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).g; + c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, -1)).r; + c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).gr; + float2 cc = mad(float2(2.0, 2.0), c.xz, c.yw); + + // Remove the crossing edge if we didn't found the end of the line: + SMAAMovc(bool2(step(0.9, d.zw)), cc, float2(0.0, 0.0)); + + // Fetch the areas for this line: + weights += SMAAAreaDiag(SMAATexturePass2D(areaTex), d.xy, cc, subsampleIndices.w).gr; + } + + return weights; +} +#endif + +//----------------------------------------------------------------------------- +// Horizontal/Vertical Search Functions + +/** + * This allows to determine how much length should we add in the last step + * of the searches. It takes the bilinearly interpolated edge (see + * @PSEUDO_GATHER4), and adds 0, 1 or 2, depending on which edges and + * crossing edges are active. + */ +float SMAASearchLength(SMAATexture2D(searchTex), float2 e, float offset) { + // The texture is flipped vertically, with left and right cases taking half + // of the space horizontally: + float2 scale = SMAA_SEARCHTEX_SIZE * float2(0.5, -1.0); + float2 bias = SMAA_SEARCHTEX_SIZE * float2(offset, 1.0); + + // Scale and bias to access texel centers: + scale += float2(-1.0, 1.0); + bias += float2( 0.5, -0.5); + + // Convert from pixel coordinates to texcoords: + // (We use SMAA_SEARCHTEX_PACKED_SIZE because the texture is cropped) + scale *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE; + bias *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE; + + // Lookup the search texture: + return SMAA_SEARCHTEX_SELECT(SMAASampleLevelZero(searchTex, mad(scale, e, bias))); +} + +/** + * Horizontal/vertical search functions for the 2nd pass. + */ +float SMAASearchXLeft(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { + /** + * @PSEUDO_GATHER4 + * This texcoord has been offset by (-0.25, -0.125) in the vertex shader to + * sample between edge, thus fetching four edges in a row. + * Sampling with different offsets in each direction allows to disambiguate + * which edges are active from the four fetched ones. + */ + float2 e = float2(0.0, 1.0); + while (texcoord.x > end && + e.g > 0.8281 && // Is there some edge not activated? + e.r == 0.0) { // Or is there a crossing edge that breaks the line? + e = SMAASampleLevelZero(edgesTex, texcoord).rg; + texcoord = mad(-float2(2.0, 0.0), SMAA_RT_METRICS.xy, texcoord); + } + + float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0), 3.25); + return mad(SMAA_RT_METRICS.x, offset, texcoord.x); + + // Non-optimized version: + // We correct the previous (-0.25, -0.125) offset we applied: + // texcoord.x += 0.25 * SMAA_RT_METRICS.x; + + // The searches are bias by 1, so adjust the coords accordingly: + // texcoord.x += SMAA_RT_METRICS.x; + + // Disambiguate the length added by the last step: + // texcoord.x += 2.0 * SMAA_RT_METRICS.x; // Undo last step + // texcoord.x -= SMAA_RT_METRICS.x * (255.0 / 127.0) * SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0); + // return mad(SMAA_RT_METRICS.x, offset, texcoord.x); +} + +float SMAASearchXRight(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { + float2 e = float2(0.0, 1.0); + while (texcoord.x < end && + e.g > 0.8281 && // Is there some edge not activated? + e.r == 0.0) { // Or is there a crossing edge that breaks the line? + e = SMAASampleLevelZero(edgesTex, texcoord).rg; + texcoord = mad(float2(2.0, 0.0), SMAA_RT_METRICS.xy, texcoord); + } + float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.5), 3.25); + return mad(-SMAA_RT_METRICS.x, offset, texcoord.x); +} + +float SMAASearchYUp(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { + float2 e = float2(1.0, 0.0); + while (texcoord.y > end && + e.r > 0.8281 && // Is there some edge not activated? + e.g == 0.0) { // Or is there a crossing edge that breaks the line? + e = SMAASampleLevelZero(edgesTex, texcoord).rg; + texcoord = mad(-float2(0.0, 2.0), SMAA_RT_METRICS.xy, texcoord); + } + float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e.gr, 0.0), 3.25); + return mad(SMAA_RT_METRICS.y, offset, texcoord.y); +} + +float SMAASearchYDown(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { + float2 e = float2(1.0, 0.0); + while (texcoord.y < end && + e.r > 0.8281 && // Is there some edge not activated? + e.g == 0.0) { // Or is there a crossing edge that breaks the line? + e = SMAASampleLevelZero(edgesTex, texcoord).rg; + texcoord = mad(float2(0.0, 2.0), SMAA_RT_METRICS.xy, texcoord); + } + float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e.gr, 0.5), 3.25); + return mad(-SMAA_RT_METRICS.y, offset, texcoord.y); +} + +/** + * Ok, we have the distance and both crossing edges. So, what are the areas + * at each side of current edge? + */ +float2 SMAAArea(SMAATexture2D(areaTex), float2 dist, float e1, float e2, float offset) { + // Rounding prevents precision errors of bilinear filtering: + float2 texcoord = mad(float2(SMAA_AREATEX_MAX_DISTANCE, SMAA_AREATEX_MAX_DISTANCE), round(4.0 * float2(e1, e2)), dist); + + // We do a scale and bias for mapping to texel space: + texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5 * SMAA_AREATEX_PIXEL_SIZE); + + // Move to proper place, according to the subpixel offset: + texcoord.y = mad(SMAA_AREATEX_SUBTEX_SIZE, offset, texcoord.y); + + // Do it! + return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord)); +} + +//----------------------------------------------------------------------------- +// Corner Detection Functions + +void SMAADetectHorizontalCornerPattern(SMAATexture2D(edgesTex), inout float2 weights, float4 texcoord, float2 d) { + #if !defined(SMAA_DISABLE_CORNER_DETECTION) + float2 leftRight = step(d.xy, d.yx); + float2 rounding = (1.0 - SMAA_CORNER_ROUNDING_NORM) * leftRight; + + rounding /= leftRight.x + leftRight.y; // Reduce blending for pixels in the center of a line. + + float2 factor = float2(1.0, 1.0); + factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2(0, 1)).r; + factor.x -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2(1, 1)).r; + factor.y -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2(0, -2)).r; + factor.y -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2(1, -2)).r; + + weights *= saturate(factor); + #endif +} + +void SMAADetectVerticalCornerPattern(SMAATexture2D(edgesTex), inout float2 weights, float4 texcoord, float2 d) { + #if !defined(SMAA_DISABLE_CORNER_DETECTION) + float2 leftRight = step(d.xy, d.yx); + float2 rounding = (1.0 - SMAA_CORNER_ROUNDING_NORM) * leftRight; + + rounding /= leftRight.x + leftRight.y; + + float2 factor = float2(1.0, 1.0); + factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2( 1, 0)).g; + factor.x -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2( 1, 1)).g; + factor.y -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2(-2, 0)).g; + factor.y -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2(-2, 1)).g; + + weights *= saturate(factor); + #endif +} + + +void main() { + // gl_FragColor = vec4(col); +} diff --git a/raw/smaa_pass/smaa_edge_detect.vert.glsl b/raw/smaa_pass/smaa_edge_detect.vert.glsl new file mode 100644 index 00000000..268a7c84 --- /dev/null +++ b/raw/smaa_pass/smaa_edge_detect.vert.glsl @@ -0,0 +1,27 @@ +#version 450 + +#ifdef GL_ES +precision highp float; +#endif + +in vec2 pos; + +out vec2 texCoord; + +const vec2 madd = vec2(0.5, 0.5); + + +// Edge Detection Vertex Shader +void SMAAEdgeDetectionVS(float2 texcoord, out float4 offset[3]) { + offset[0] = mad(SMAA_RT_METRICS.xyxy, float4(-1.0, 0.0, 0.0, -1.0), texcoord.xyxy); + offset[1] = mad(SMAA_RT_METRICS.xyxy, float4( 1.0, 0.0, 0.0, 1.0), texcoord.xyxy); + offset[2] = mad(SMAA_RT_METRICS.xyxy, float4(-2.0, 0.0, 0.0, -2.0), texcoord.xyxy); +} + + +void main() { + // Scale vertex attribute to [0-1] range + texCoord = pos.xy * madd + madd; + + gl_Position = vec4(pos.xy, 0.0, 1.0); +} diff --git a/raw/smaa_pass/smaa_neighborhood_blending.frag.glsl b/raw/smaa_pass/smaa_neighborhood_blending.frag.glsl new file mode 100644 index 00000000..979bc556 --- /dev/null +++ b/raw/smaa_pass/smaa_neighborhood_blending.frag.glsl @@ -0,0 +1,77 @@ +#version 450 + +#ifdef GL_ES +precision mediump float; +#endif + + +uniform sampler2D tex; + +in vec2 texCoord; + + +//----------------------------------------------------------------------------- +// Neighborhood Blending Pixel Shader (Third Pass) + +float4 SMAANeighborhoodBlendingPS(float2 texcoord, + float4 offset, + SMAATexture2D(colorTex), + SMAATexture2D(blendTex) + #if SMAA_REPROJECTION + , SMAATexture2D(velocityTex) + #endif + ) { + // Fetch the blending weights for current pixel: + float4 a; + a.x = SMAASample(blendTex, offset.xy).a; // Right + a.y = SMAASample(blendTex, offset.zw).g; // Top + a.wz = SMAASample(blendTex, texcoord).xz; // Bottom / Left + + // Is there any blending weight with a value greater than 0.0? + SMAA_BRANCH + if (dot(a, float4(1.0, 1.0, 1.0, 1.0)) < 1e-5) { + float4 color = SMAASampleLevelZero(colorTex, texcoord); + + #if SMAA_REPROJECTION + float2 velocity = SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, texcoord)); + + // Pack velocity into the alpha channel: + color.a = sqrt(5.0 * length(velocity)); + #endif + + return color; + } else { + bool h = max(a.x, a.z) > max(a.y, a.w); // max(horizontal) > max(vertical) + + // Calculate the blending offsets: + float4 blendingOffset = float4(0.0, a.y, 0.0, a.w); + float2 blendingWeight = a.yw; + SMAAMovc(bool4(h, h, h, h), blendingOffset, float4(a.x, 0.0, a.z, 0.0)); + SMAAMovc(bool2(h, h), blendingWeight, a.xz); + blendingWeight /= dot(blendingWeight, float2(1.0, 1.0)); + + // Calculate the texture coordinates: + float4 blendingCoord = mad(blendingOffset, float4(SMAA_RT_METRICS.xy, -SMAA_RT_METRICS.xy), texcoord.xyxy); + + // We exploit bilinear filtering to mix current pixel with the chosen + // neighbor: + float4 color = blendingWeight.x * SMAASampleLevelZero(colorTex, blendingCoord.xy); + color += blendingWeight.y * SMAASampleLevelZero(colorTex, blendingCoord.zw); + + #if SMAA_REPROJECTION + // Antialias velocity for proper reprojection in a later stage: + float2 velocity = blendingWeight.x * SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, blendingCoord.xy)); + velocity += blendingWeight.y * SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, blendingCoord.zw)); + + // Pack velocity into the alpha channel: + color.a = sqrt(5.0 * length(velocity)); + #endif + + return color; + } +} + + +void main() { + // gl_FragColor = vec4(col); +} diff --git a/raw/smaa_pass/smaa_neighborhood_blending.vert.glsl b/raw/smaa_pass/smaa_neighborhood_blending.vert.glsl new file mode 100644 index 00000000..f4084087 --- /dev/null +++ b/raw/smaa_pass/smaa_neighborhood_blending.vert.glsl @@ -0,0 +1,25 @@ +#version 450 + +#ifdef GL_ES +precision highp float; +#endif + +in vec2 pos; + +out vec2 texCoord; + +const vec2 madd = vec2(0.5, 0.5); + + +// Neighborhood Blending Vertex Shader +void SMAANeighborhoodBlendingVS(float2 texcoord, out float4 offset) { + offset = mad(SMAA_RT_METRICS.xyxy, float4( 1.0, 0.0, 0.0, 1.0), texcoord.xyxy); +} + + +void main() { + // Scale vertex attribute to [0-1] range + texCoord = pos.xy * madd + madd; + + gl_Position = vec4(pos.xy, 0.0, 1.0); +} diff --git a/raw/smaa_pass/smaa_pass.frag.glsl b/raw/smaa_pass/smaa_pass.frag.glsl new file mode 100644 index 00000000..e94ac690 --- /dev/null +++ b/raw/smaa_pass/smaa_pass.frag.glsl @@ -0,0 +1,164 @@ +/** + * Copyright (C) 2013 Jorge Jimenez (jorge@iryoku.com) + * Copyright (C) 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com) + * Copyright (C) 2013 Belen Masia (bmasia@unizar.es) + * Copyright (C) 2013 Fernando Navarro (fernandn@microsoft.com) + * Copyright (C) 2013 Diego Gutierrez (diegog@unizar.es) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to + * do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. As clarification, there + * is no requirement that the copyright notice and permission be included in + * binary distributions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +/** + * _______ ___ ___ ___ ___ + * / || \/ | / \ / \ + * | (---- | \ / | / ^ \ / ^ \ + * \ \ | |\/| | / /_\ \ / /_\ \ + * ----) | | | | | / _____ \ / _____ \ + * |_______/ |__| |__| /__/ \__\ /__/ \__\ + * + * E N H A N C E D + * S U B P I X E L M O R P H O L O G I C A L A N T I A L I A S I N G + * + * http://www.iryoku.com/smaa/ + */ + +#version 450 + +#ifdef GL_ES +precision mediump float; +#endif + +#define SMAA_RT_METRICS vec4(1.0 / 800.0, 1.0 / 600.0, 800.0, 600.0) +// #define SMAA_GLSL_3 +#define SMAA_PRESET_HIGH +// #include "SMAA.h" + +// #define SMAA_AREATEX_SELECT(sample) sample.rg +// #define SMAA_SEARCHTEX_SELECT(sample) sample.r +// #define SMAA_DECODE_VELOCITY(sample) sample.rg + +// #if defined(SMAA_PRESET_LOW) +// #define SMAA_THRESHOLD 0.15 +// #define SMAA_MAX_SEARCH_STEPS 4 +// #define SMAA_DISABLE_DIAG_DETECTION +// #define SMAA_DISABLE_CORNER_DETECTION +// #elif defined(SMAA_PRESET_MEDIUM) +// #define SMAA_THRESHOLD 0.1 +// #define SMAA_MAX_SEARCH_STEPS 8 +// #define SMAA_DISABLE_DIAG_DETECTION +// #define SMAA_DISABLE_CORNER_DETECTION +// #elif defined(SMAA_PRESET_HIGH) +#define SMAA_THRESHOLD 0.1 +#define SMAA_DEPTH_THRESHOLD (0.1 * SMAA_THRESHOLD) // For depth edge detection, depends on the depth range of the scene +#define SMAA_MAX_SEARCH_STEPS 16 +// Define SMAA_DISABLE_DIAG_DETECTION to disable diagonal processing +#define SMAA_MAX_SEARCH_STEPS_DIAG 8 +// Define SMAA_DISABLE_CORNER_DETECTION to disable corner processing +#define SMAA_CORNER_ROUNDING 25 +// If there is an neighbor edge that has SMAA_LOCAL_CONTRAST_FACTOR times bigger contrast than current edge, current edge will be discarded +#define SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR 2.0 +// Predicated thresholding allows to better preserve texture details and to improve performance +#define SMAA_PREDICATION 0 +// Threshold to be used in the additional predication buffer +#define SMAA_PREDICATION_THRESHOLD 0.01 +// How much to scale the global threshold used for luma or color edge detection when using predication +#define SMAA_PREDICATION_SCALE 2.0 +// How much to locally decrease the threshold +#define SMAA_PREDICATION_STRENGTH 0.4 +// Temporal reprojection allows to remove ghosting artifacts when using temporal supersampling +#define SMAA_REPROJECTION 0 +// SMAA_REPROJECTION_WEIGHT_SCALE controls the velocity weighting +#define SMAA_REPROJECTION_WEIGHT_SCALE 30.0 +// #elif defined(SMAA_PRESET_ULTRA) +// #define SMAA_THRESHOLD 0.05 +// #define SMAA_MAX_SEARCH_STEPS 32 +// #define SMAA_MAX_SEARCH_STEPS_DIAG 16 +// #define SMAA_CORNER_ROUNDING 25 +// #endif + +// Non-Configurable Defines +#define SMAA_AREATEX_MAX_DISTANCE 16 +#define SMAA_AREATEX_MAX_DISTANCE_DIAG 20 +#define SMAA_AREATEX_PIXEL_SIZE (1.0 / vec2(160.0, 560.0)) +#define SMAA_AREATEX_SUBTEX_SIZE (1.0 / 7.0) +#define SMAA_SEARCHTEX_SIZE vec2(66.0, 33.0) +#define SMAA_SEARCHTEX_PACKED_SIZE vec2(64.0, 16.0) +#define SMAA_CORNER_ROUNDING_NORM (float(SMAA_CORNER_ROUNDING) / 100.0) + +#define SMAA_FLATTEN +#define SMAA_BRANCH +// #define lerp(a, b, t) mix(a, b, t) +// #define saturate(a) clamp(a, 0.0, 1.0) +// #define mad(a, b, c) (a * b + c) + +uniform sampler2D tex; + +in vec2 texCoord; + + + +//----------------------------------------------------------------------------- +// Misc functions +// Gathers current pixel, and the top-left neighbors. +float3 SMAAGatherNeighbours(float2 texcoord, + float4 offset[3], + SMAATexture2D(tex)) { + #ifdef SMAAGather + return SMAAGather(tex, texcoord + SMAA_RT_METRICS.xy * float2(-0.5, -0.5)).grb; + #else + float P = SMAASamplePoint(tex, texcoord).r; + float Pleft = SMAASamplePoint(tex, offset[0].xy).r; + float Ptop = SMAASamplePoint(tex, offset[0].zw).r; + return float3(P, Pleft, Ptop); + #endif +} + +// Adjusts the threshold by means of predication. +float2 SMAACalculatePredicatedThreshold(float2 texcoord, + float4 offset[3], + SMAATexture2D(predicationTex)) { + float3 neighbours = SMAAGatherNeighbours(texcoord, offset, SMAATexturePass2D(predicationTex)); + float2 delta = abs(neighbours.xx - neighbours.yz); + float2 edges = step(SMAA_PREDICATION_THRESHOLD, delta); + return SMAA_PREDICATION_SCALE * SMAA_THRESHOLD * (1.0 - SMAA_PREDICATION_STRENGTH * edges); +} + +// Conditional move: +void SMAAMovc(bool2 cond, inout float2 variable, float2 value) { + SMAA_FLATTEN if (cond.x) variable.x = value.x; + SMAA_FLATTEN if (cond.y) variable.y = value.y; +} +void SMAAMovc(bool4 cond, inout float4 variable, float4 value) { + SMAAMovc(cond.xy, variable.xy, value.xy); + SMAAMovc(cond.zw, variable.zw, value.zw); +} + + + + + + + + +void main() { + // gl_FragColor = vec4(col); +} diff --git a/raw/smaa_pass/smaa_pass.shader.json b/raw/smaa_pass/smaa_pass.shader.json new file mode 100755 index 00000000..748756c2 --- /dev/null +++ b/raw/smaa_pass/smaa_pass.shader.json @@ -0,0 +1,25 @@ +{ + "contexts": [ + { + "id": "smaa_pass", + "params": [ + { + "id": "depth_write", + "value": "true" + }, + { + "id": "compare_mode", + "value": "always" + }, + { + "id": "cull_mode", + "value": "none" + } + ], + "links": [], + "texture_params": [], + "vertex_shader": "smaa_pass.vert.glsl", + "fragment_shader": "smaa_pass.frag.glsl" + } + ] +} diff --git a/raw/smaa_pass/smaa_pass.vert.glsl b/raw/smaa_pass/smaa_pass.vert.glsl new file mode 100644 index 00000000..e1cc9c08 --- /dev/null +++ b/raw/smaa_pass/smaa_pass.vert.glsl @@ -0,0 +1,18 @@ +#version 450 + +#ifdef GL_ES +precision highp float; +#endif + +in vec2 pos; + +out vec2 texCoord; + +const vec2 madd = vec2(0.5, 0.5); + +void main() { + // Scale vertex attribute to [0-1] range + texCoord = pos.xy * madd + madd; + + gl_Position = vec4(pos.xy, 0.0, 1.0); +} diff --git a/raw/smaa_pass/smaa_separate_multisamples.frag.glsl b/raw/smaa_pass/smaa_separate_multisamples.frag.glsl new file mode 100644 index 00000000..e1a9e863 --- /dev/null +++ b/raw/smaa_pass/smaa_separate_multisamples.frag.glsl @@ -0,0 +1,29 @@ +#version 450 + +#ifdef GL_ES +precision mediump float; +#endif + +uniform sampler2D tex; + +in vec2 texCoord; + + +// Separate Multisamples Pixel Shader (Optional Pass) + +#ifdef SMAALoad +void SMAASeparatePS(float4 position, + float2 texcoord, + out float4 target0, + out float4 target1, + SMAATexture2DMS2(colorTexMS)) { + int2 pos = int2(position.xy); + target0 = SMAALoad(colorTexMS, pos, 0); + target1 = SMAALoad(colorTexMS, pos, 1); +} +#endif + + +void main() { + // gl_FragColor = vec4(col); +} diff --git a/raw/smaa_pass/smaa_temporal_resolve.frag.glsl b/raw/smaa_pass/smaa_temporal_resolve.frag.glsl new file mode 100644 index 00000000..1441f4d9 --- /dev/null +++ b/raw/smaa_pass/smaa_temporal_resolve.frag.glsl @@ -0,0 +1,49 @@ +#version 450 + +#ifdef GL_ES +precision mediump float; +#endif + +uniform sampler2D tex; + +in vec2 texCoord; + + +// Temporal Resolve Pixel Shader (Optional Pass) + +float4 SMAAResolvePS(float2 texcoord, + SMAATexture2D(currentColorTex), + SMAATexture2D(previousColorTex) + #if SMAA_REPROJECTION + , SMAATexture2D(velocityTex) + #endif + ) { + #if SMAA_REPROJECTION + // Velocity is assumed to be calculated for motion blur, so we need to + // inverse it for reprojection: + float2 velocity = -SMAA_DECODE_VELOCITY(SMAASamplePoint(velocityTex, texcoord).rg); + + // Fetch current pixel: + float4 current = SMAASamplePoint(currentColorTex, texcoord); + + // Reproject current coordinates and fetch previous pixel: + float4 previous = SMAASamplePoint(previousColorTex, texcoord + velocity); + + // Attenuate the previous pixel if the velocity is different: + float delta = abs(current.a * current.a - previous.a * previous.a) / 5.0; + float weight = 0.5 * saturate(1.0 - sqrt(delta) * SMAA_REPROJECTION_WEIGHT_SCALE); + + // Blend the pixels according to the calculated weight: + return lerp(current, previous, weight); + #else + // Just blend the pixels: + float4 current = SMAASamplePoint(currentColorTex, texcoord); + float4 previous = SMAASamplePoint(previousColorTex, texcoord); + return lerp(current, previous, 0.5); + #endif +} + + +void main() { + // gl_FragColor = vec4(col); +}