From 4960cc74e09dada8837745e5f14d4571c15836c8 Mon Sep 17 00:00:00 2001 From: luis605 Date: Fri, 4 Apr 2025 22:41:34 +0100 Subject: [PATCH] [examples] Reviewed shader view depth --- .../resources/shaders/glsl100/depth.fs | 37 ++++++++++++------ .../resources/shaders/glsl330/depth.fs | 36 ++++++++++++----- examples/shaders/shaders_view_depth.c | 2 + examples/shaders/shaders_view_depth.png | Bin 7745 -> 11335 bytes 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/examples/shaders/resources/shaders/glsl100/depth.fs b/examples/shaders/resources/shaders/glsl100/depth.fs index cdd45f17f..0ea7c46e7 100644 --- a/examples/shaders/resources/shaders/glsl100/depth.fs +++ b/examples/shaders/resources/shaders/glsl100/depth.fs @@ -1,19 +1,34 @@ #version 100 -in vec2 fragTexCoord; -out vec4 finalColor; -uniform sampler2D depthTexture; +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +// Input uniform values +uniform sampler2D depthTexture; +uniform bool flipY; + +float nearPlane = 0.1; +float farPlane = 100.0; + +// Function to linearize depth from non-linear depth buffer float linearizeDepth(float depth) { - float n = 0.1; // near plane - float f = 100.0; // far plane - return (2.0 * n) / (f + n - depth * (f - n)); + return (2.0 * nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane)); } -void main() { - vec2 flippedTexCoord = vec2(fragTexCoord.x, 1.0 - fragTexCoord.y); - float depth = texture(depthTexture, flippedTexCoord).r; +void main() +{ + // Handle potential Y-flipping + vec2 texCoord = fragTexCoord; + if (flipY) + texCoord.y = 1.0 - texCoord.y; + + // Sample depth texture + float depth = texture2D(depthTexture, texCoord).r; + + // Linearize depth float linearDepth = linearizeDepth(depth); - finalColor = vec4(vec3(linearDepth), 1.0); -} + + // Output final color + gl_FragColor = vec4(vec3(linearDepth), 1.0); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/depth.fs b/examples/shaders/resources/shaders/glsl330/depth.fs index ccda3111b..cbcb6da67 100644 --- a/examples/shaders/resources/shaders/glsl330/depth.fs +++ b/examples/shaders/resources/shaders/glsl330/depth.fs @@ -1,19 +1,37 @@ #version 330 +// Input vertex attributes (from vertex shader) in vec2 fragTexCoord; -out vec4 finalColor; -uniform sampler2D depthTexture; +// Input uniform values +uniform sampler2D depthTexture; +uniform bool flipY; + +const float nearPlane = 0.1; +const float farPlane = 100.0; + +// Output fragment color +out vec4 finalColor; + +// Linearizes the depth buffer value float linearizeDepth(float depth) { - float n = 0.1; // near plane - float f = 100.0; // far plane - return (2.0 * n) / (f + n - depth * (f - n)); + return (2.0 * nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane)); } -void main() { - vec2 flippedTexCoord = vec2(fragTexCoord.x, 1.0 - fragTexCoord.y); - float depth = texture(depthTexture, flippedTexCoord).r; +void main() +{ + // Handle potential Y-flipping + vec2 texCoord = fragTexCoord; + if (flipY) + texCoord.y = 1.0 - texCoord.y; + + // Sample depth + float depth = texture(depthTexture, texCoord).r; + + // Linearize depth value float linearDepth = linearizeDepth(depth); + + // Output final color finalColor = vec4(vec3(linearDepth), 1.0); -} +} \ No newline at end of file diff --git a/examples/shaders/shaders_view_depth.c b/examples/shaders/shaders_view_depth.c index fa5393280..5da0c1ca4 100644 --- a/examples/shaders/shaders_view_depth.c +++ b/examples/shaders/shaders_view_depth.c @@ -52,6 +52,8 @@ int main(void) // Load depth shader and get depth texture shader location Shader depthShader = LoadShader(0, TextFormat("resources/shaders/glsl%i/depth.fs", GLSL_VERSION)); int depthLoc = GetShaderLocation(depthShader, "depthTexture"); + int flipTextureLoc = GetShaderLocation(depthShader, "flipY"); + SetShaderValue(depthShader, flipTextureLoc, (int[]){ 1 }, SHADER_UNIFORM_INT); // Flip Y texture // Load models Model cube = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f)); diff --git a/examples/shaders/shaders_view_depth.png b/examples/shaders/shaders_view_depth.png index bcce1fd61497f5884d045a9b1bafab3b34dcaa0b..b68de9644cab86bc0ff3422f147bdee0a59a2494 100644 GIT binary patch literal 11335 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYU_8XZ#=yWJp1k%10|Ns~v6E*A2L}g74M$1` z1A_vCr;B4q#hkZy&#qHBK2_quiZJOJYr}8tVy#e&Uc|`w?Tk~y{6k`%_6_Ot4hZ@7 z=6s*=#HR7YTAs;Qa#((fZjt1B(CT^4DXKCpk>kRl4}Q~BIMZeGd|t<@!~OMt9=97EJbZY`a^JAe6%%i7JNnVh{@JwS_crZ)&ewkU zUH|)^cXZ?KKiW9${K}8Bru|>{^^TPN?N5~x|Ls0{zW@LK-u#-y40k^N`T6<1-OOK4 zvJbkjY`rb^w<72GPO0cGpV!wid`T!`a?**u^J25iG)|8% zTFze{Z@fFhDtyA^%4+*#Y!S&}Oi712RZsssamnvSaPRll?_vy+rm;@+qa_O>sGIzlFMJy_xTx9lg301zSIJ5Is z`}Z4VO1-&DJ`1hXWl*lNdg@vK?R$RyUA~41b)U}8-=61W8ocktgoruH3*09QO$hS( zd9l3i>x=u>m6z)82;}n>`Q|iQ`-z+M>T4eUtN=jb- z+VimFn3mo145`N~Zv`ihY~R z@YO=rR6N`pPH@T z;}mdP{<+AE#Z^p2?`BMh@pAe1XZ^pl&&T`oSQj5}c@m`b>G1rzvacU6UteQ+>|*?$ zpX%#vpWpTWzw6J@+4Vv9{(f1nzfHE`7vqM8UslP?YrdAO-!F83Rga8t$7h#EUrevd z%`f_6={LFQ@{+_;kGIS1F6{}PF4XIBvV9ekH)m8_=O5N8h7DWKYAd*V3pH7;pZVzy zkNKO=S{_TDC@=Qm3~qaEto(Ra@3i|0c2>zODc`qD+2wfa=f=LNy+P~3P1eoaU0M6? zWB;NYmj4g^?W;}7j;E;H5?bTqXnRHFLw5F)kMXy@SFe|@^l2M9E$771ul-pN_ zffDiknsYysqixgQ?!PXVy#9LL-_5G$qkqp@`hV|n!)bs1+)6$_&sLk^yG{MSKfCvJ z7%bqa&pi!JY1W%`g`}3LYTQY`!*K1k4r8Z{r+c2Xfn2fB#2s>tYi+$8e5}qqtZJ-F zt*h_9_f72Y_CH)Rl5eO+T+9!+czgOpL)NTSrpw>hn(O|o4gMy==<_v-DX7@V(DLhf zOS##f@AnJZ?>+sOZ$WP&DA6svYW`|Q->v*xHy&4Y*Z9U~-(Kr~jY;C%&ezEYRTR=b!zr@1jKTjrj}A%;P;ct`wLvu8d{9Y4l+Cw4OQkWwR>g{Cl$}_qpd$ zxlXnV<_Du{w;sP@$#f&^7ng^~@vf7Gjx(bicYfOw-CzIu?EC#SZ%+H$YuvB;{QK!? zfBTBJKbN1s?Y(W4)3$GEstZ=1u3(yQ^Bw1jISub?IpA*gwJ9!`P>Ro&6>$O66yXn!j&A(10b8Qjb#k9%f;g0e- z$(IUq-+P1wPT~t?tx}1Q4u1A|-p;oU_np)g_Pi^RyjJ-0YGAi&xb2A<2An!cS*39? z{0u3VR2WyvewZ7k`z*xZo$dFUo0r!vjhsHs&o|P{^!a!BST8%T%DqgNj1*5wTyfS{ z%01OLMaDJjwC&7WTn5)49_F{-Bdz-H<^8>(bzkPjhyFb}vH9|eTF4bgdDour{e5%ur^)&M{=6zaCx82uW%U2w_lmE{?7vo={U_(-=WSJg_x`{4Si&^^ z^P8KSnGBA8etv%c?KiV8DE}{2FS^~ZZ$|#BQ#SKv-sUrK-^|idYIJ9X5x8zS6t+kF zUAL86^cL-`_{Kf6)D$MFZ#|LAyy9fd^>g=<<6nQ@nbu$$;&3Bm+w72S-?pW!iCF#A z^vb8-CVR>oE}Hr~DES|mcstDN&o{y5*Dbbh3-`M2Tedtefn6fsb1gr z{WSM6#s%?06Ra2AXIZ>mfAPfQB~SL9PhHb-Xe&pGuo9zTB~!rc>eD92IB!IEfZb;U zaUav^um9@a@2z*ROB9-LLOA8gHpbd+yZ;i(%(JR{2N?Wu%vXJx39~;_Bi_Yqsia%?dsk>-&*IdxwPiz zOLp=9;s-ybecf*V_jI@Y{%=1->VIF}zvqX2htr0z__v0oeb1`Dy@`CS#&FUm_ilrf z-TxnZKOMXM-sabLF}`-^%8H5^fBxv(Rqn6(y;eTw(ll?s+uzrk@BjZIJy2-E+P|0I z|K08WKW=uz8QbUH_3r1RzOKJsn0t5qwf*u9e-5cCcr)!YzgPD>RjBCK|D`d0ZhrI2 zOaAThK5xI>WT(aYIFO++YclRs)vWaHJhA=WpSsD%*ITOb9#44`Bvd#r!^ig7Ps1!3 z>4^7XNybH&HecPovfpNzL-j+U3Bk`D|7RX5co!5@__8#3mGbqv^V0eIKO0#_ZJzSV zq|w6m+@0h4miI#PSpPh~I?=m-{=T|XpP$P;5BsgB%CNlu?y9Vq-#6EuIslI{bH1Q#ju6KI~B8$ve;Ei*-NVtcpLm_pfqsj5lB2&S@fZ z?CWg4T{-@}WNlTVJ_myXkD~B|Y3C--xV+@?kIifUN!8_MUXAnk0e3$s%ocNDRex>gBlq~H7LW#l?W-;EM<9}*b=u?aTH@6;nuqDZG zc~xO%{)xTEv(?n6Ye@yKR{Gvo{N8lAo^JoDz=Hv-ow->Tt_BxubB{k)@9zJ2`*Oi! zxh-}~hB9`)UMy~}Zu~d@-`(h^?)QIQ_4BP#{S-e(8C;iGpSpA|Xj}H{JG1{yJAePt z&YAPSze_)V%75R_&z|?|H$1U4jobX~{`3B;Hg#*C`~8i4o1F9Ym-qj@-#=#UJ9hj7 zQ!%(AdAXl`$`*9YP_!5Rd=J( z{~QNigg9jA-9Bp>U7eYHvh>lds)H5`UvyoWgnp)p?95$yBwxO8N7ypsFqel>EJjsR z8fKixIJ%YnN{ZjiV-}3MOI9?vh}SapgI)M#;rH)F@BcCvRp~NzT1C3%icbjtQtA4e z;l)I*6ADHwT#~mcw4$pQs=l9IwN38y%H!pJjZ5{^6av+!u6V1ZT6UWuf%m(`0yWVI zezhM@{(jo+e=q-TPmq^peBCd{pPw%CtJ#|0_SK87&OE*~2%M=HzJ1(M%KXeqhVSXa zhYz3bxBvfRZ}<7?$8XEys^5I>zrXv(kFeb6$KC$-^zYZbW)F?4))f4CZT9{Bl|9~^ zhc8{1iU0m|x%?g5V;NQa6|hXTwyyql9pi@et2sT+CRBM}7vhz(R#V~U=byYt;) z#r^+p?*I86bn0uFZ)8&G%je7ceIqZG{;OWM_unm}70F6Px{5o${Hi|Avcgw@?|_(7 zxI-W3agpfv?{ED6-m|XslXdvEZwWdCxmH-7nT##BY9iw)}}H_lw_u&7STt zSO0cY@tN%PyT6_cxo$R5zw)fm%~f1CZ*f02VqbWRZ^H41i~H?%NgMvX{r_hgsCB>9 zy*jO1=EK&U+dtX9WuKq|eDd4(Ge6(2mS6l0($EUF1vRu@ zYAeK;J-xhfnhHzx-e(@6jN2aTzkj_(a{u1r_ja-=ee``H-DUUCJwM(}x#uNEZA!H6 z`i0Ztm)&?=?f#WHBB_W;sPs|KExnAh)r;qu>ylcAFRNyAd6ZntzXopR zwTkZ%e|57;C%gWp`T^B$p$RL5{jZcUI)uGj>yWFZuxH9cwaE*6mv7oSJ@?8Ez8LTR zt8)C0xi`!|%IR_Cq*c~#ug<$>->(1udSO-l-u`TD-TjU-4f|F!Oz_**pc-AR*fsIK zwfBDCzxRsW<$@LZmIu%OA^-2U{k=`H44Nyyd^vuDDJMIK>C;8~UteCGmy?rQWt!HK z+*`5dVt?h^9ow7cc-!y(_Qw*`xwY+!+^rkjCm*`RR&e4m-JocOii1LHIF;_+FqY#_ zuIk=+)9qPGR>(O)gRZNb9%ng?Uu}%Y@BTdT=?ux+7jDgY<>_Yob!oZsoYjKAIF2l0 zGP;-{{3YY>-DX48O=qq@2Y2lfd_sjLteDz;V)Cbs)60yu2tJrK@!5uZt0y=_YbhA_ znEgz9k-sf9Lh{&`X>Z;>7oC4^tKTx;UweBjFZ90?o^V3=eMhK3$En}xJ8h5YeF|Et zdAziiaZivgqh#t!k=H3JBU1LWZQgFbSvC26&E5-#Ep+}eIW|nRF?2j9yf;hmZ-qo~ zg6(IH36WP-BLY_|sJ)8V6r$s{Gtcd1Ixnopx8=%Txe2;GW`+IN?%PTPXPmAUSTI+8 z>5;W&F1BI0%6hX;U2t1gsCWGFoa3Oj@yZ4rlUq;bE!;mX(J=JOXQ{olTQ+_zeYlJH z+b1JN$%VHBw#F{)iDXT*eLnL=%;KFtotzT5A8IS8?W#*%8L@*+QLKIgAjO6TT zACFwg@|k=3EvRT}z27qLV21e`p1)gpwC4#bA#o)u8BiC$EGxY}Hd!P!5q^ zv~Bg2h=VLSnXk6Kl$!UvW>3$3qhq`Y(krzT^4R{K3flO=HR1N_TAr%+@;i6PHHxiM zQ&3x4xhPzBkvxBf`sd%3U$&+HappdtCpuw;_b#7J8&h^p+?AJLv-RHh>htoEw|T$3 zO=C(rG&6n6N2#^@7r*{l^Zm|tZ?`{R^y>F8btG@MRR~o7f5Lnc#0MqECO{jK>$krB z^6|u5_6)_VYF~KVc3(_+u|758P3pn`5Wn`{4EWQF2ekYi`BF#dAgNax#=TPyO9*dJr~k`~5f^|=%=LwF< z5l`&g);GDxSucC}QbrFn+;gC0=K1Pp+n66`MlpW8F1zeR(8i39(;wOP3%>lm{hj}5 zGnW_E3~M%OFcvb;fdu@8pe0ZAE>+t@BVTIPd&bTv*3KH|4v~U4s?O3g(_dMZzI$#d zum5=a8IH$hPV$X2W~nPImdIUn{=)r?(;JL>ZeFXBZ@%|?yZPgreH+=YRqXoG+J1PU zjg3u6rpwvnt0G%tmtM(_ezH$4HA6W?dBPt3Tk_gja>-{6>;M10AO8REhBgVs{-c~8 zArqUgoXC~FD)#(HrJ50^JER#@{?_7|<&CiO?>B~Wp5SNuWO;o|s*KV#lqs)rwK@&3WUf zsfty<7fe%ie6G>>%J!I|da?C}kQrPanuV(slvyuI{+hM0cj=M*=@YC9&-~lhtezs1%kt=@ zZQ#w-_0Qt73S@g%zvl9IqF`Ed+wJP*v@f<_*TLL^7XC%a-mwe}2@*2>9;dGh%HGFG6nj|Gy9Gawe?R3z_0$!$@Fd*-=gLG<(s3g7Q@%8a>36tEQ>8S9J?Hp#MTzLT0!u5mNvv^PcolJt!3I3 z$9(eI->kpC6?Y3htBqLn+V_QIkI)Rc)ED_}W=?6_g=SBjJP* zceVw7-6FZSG$Hk_-IwFG+!4u>RU?#HuE2b$Fxlf|?2;n};52wG_*p?huREv5kpl%S zsr5_>zV*r!-xLtFnt z-jpo|Oh5yxg3G$3eEJn$tKW*X?yD4xNWRRXlC@Rw)y6F8+{kcE%Ud&i&pT$HukBv) z)Z+S|yT$!af8Cn@Q@&`&j0TQJw+z31Ou5;kcO%gs)Dkax>&>jZeW%)Y&8TADXWM=X ztr28;b)vQ>j=J|nd4#arg2Zjl-8VzqPbuqViv3s2~1OuVAyab)8yueN<@8OfTJ zw<`6j6qu)fsk{5`=Kh|~Vmo&}`}HWfqWP56485rf_efO<^xvp`^s`ikcd|3%li>t9%dY zNWG2{feC$b%sZ}S^{*`6(zkQg#Y+A)#+rs|b_M3g2u^-GJ{#u-m-1d&{U0Ep=kz51{m7XZpPFURSS>pB}z<9#Rl+*iG zfLb_4T|M8OemzO95I!O0pbz$*L}TgiN{Q%a2LBneO*|bIg-I`xTfOb#w9=`Q7WWz) zuRK)n{(kkgrAs|>cd7?RpP%X9Xqu*~(6pnhr`G1&Nu%ja>sI!sUJZ_~GC#CaYGMDy zo#h6*(!4jgaokh-ZdfI%^67>nKd6O#Z`w}D2y6Z`ehx}(ZHsm0Cdta5?wfwrutV*8I;d>y2FO<$83o4CWr4_3?J~8+WVg?*u1YUc{o3lpwK{OQ>*- z+q0T8mx~oH7vERPv^=M~-)Cd{>(eouAHRIs_r-9}$sRF>^cVRpX5R$fq-;%jvw8md zsJHt|=jbGF`NGYjoNYUw@o)CL1{dUpN<;7@=>_WD!UB#l*2nDT`8;1T-64%1)YMtg zr}J6-OUje)v7fm-G=mZDy0ad-q4JRtsk7VhWdt9a#6WDs>@*|`{KEWFaEl{*}E~q|6rtl?aSC{#i{R@H*xP|Sv_UP z)wUJKSLGf_4VJvcVVc6ZMgQWrU1usCxb=l6%rjryp9J+COPsiFq(MK!R+kz6hr%4Z zB$X?=?;ICgt*}Q(mm%2_)Gl7_`|Fwag7AK!3G-GffK%S=i^nf`C)_zCmn{A>dBt*> z>tBzC-SK|m`U2#u?GRt-D@k0KK%r9QNT`X5D zcYr%wctXeNDR}GZ&~W5)#{$l zR2r_ooz&pM!?RfLWtT;ma(5VO=ZW~e@u0biH_MlQH$Nbjr=}ptytE^?D+k=RR2E*5 zzxb(n2lE%NoKH9Myf-MZwFPR63m$)!0gjLzZvKrAFYWtc!Y29E;GgYzL58h&eI2U! z_qiF|vOII)esu1Z9`$8m$**Gaj^DVn`^9&sV^gz)e_iCb+P31YR_Yloj?XFgEo35> zZ0s$Gi`sH@59@|AOIVJ$fAYIr{ogIk_*Ydh^AQinT(;+rQ~yje%=;~!`Hxx7JCac| zbR>58c( zW2c0MYff+qxC_Ag>cpHSj5#aAVy>oeh8;Ozko8pQQG{&ojvOs#>FgJl46k?QPw)Bh zGB&&ZJIDLNhG}W43X56dZKdDJq`i1Q%dAh#=khhV>$9_^I+UvZOo+VY`@$XC^fz3s z5O8XfLuA2Urz3?1?-|~tmoYt3u3Y|dZ@uzn$-VW0%qb0Fcjm9qtz}&za`1M{#noaL z`=?J`Fl*kG9rMm|Gvu21qIklAPbmLe!n?LgF;$evi557~yZm@@o*YBQ`kz8;Ko#04 z*CQLPq`+ybPp^tWc5m$l^J1-@#6l*eAE)xS6wg?=|2k7pqt->&y>5&5KWB8ivWF?? zG9or)TzL-|8!x+UxSdINt(QZM%6pTEzr}avO7_^*F&){}lP;^gU!BqD#VV$tQxc4c zum%)RIFYb_S@3hBUQm@~XN1O#_uH5|P)wD;($uQ&$jdUJprP zulDX=%lzur{{5x(QQH)q?!R6a9 zgTJ{K@cS>Wos#$7G3LoX*F5PB^Ok6^e>S+VJ5L)_1O~XjOa7we@nmDO)FySAd-EA; zxn_cLihIPRqgA$ZZohGSt!w*TSLpGcxNns#52h_&`ekp8R?=)G>9wZ>_SSCa_;llP z-1X>d-<26Ix2|cJB4liUT>YlZRXw<)CSU#tf;leezF zcfXopk6sSzl4XLccmr>To~k&#%j@Jtw}$95i3h^uR243+QrOF02#yVhxM!jaZ7Uk4 z7`Zvf?(Dy~T4CaGJ*Lx>UUl0oyXdj2!HR)_`x9s_z-{;XGY1X&t_w}bxZ2&(_>jYU zSH${f)eS#;Zr8o*-D=6#5PUeq!AtPXc~fwso+0D#UdC5m6G1*-9OkIhcQwrDi>b48 zr2p2ZhSzNvw#WE5RK?jHwE-8{yWLhV*nK@=f9d|H|8)!Gz8fy`4rE-J*^=darEIFv zJ#f27@LEAFv%&GJEGki=OTH`U75!J*-utxbSNHcz`+O?rdht8NJeoYGZ8eHt-p#w_ znEm$t{ayAk)4$p>IaHeqBYEKb&Q#r#vJBHxdi2}YG)z%an3D}|xTh9rUYPqUBCPt$ z(?8`of35e*Gpu;(`I_yFsG-Noo6A-l@6vOQH{LR_Zs$LSjz@W{OP)UsK4T0nss(0# zS8}j#i){+^y7N~$us`&61|;-3 zswk3S&GFJVESIl{eY9d<;6EAWVh!)*5yy9)&Gr1Gp2)JU&_2QCaJYk)pujm(uc;3; zs(!x{{NrbSDI#^>GR70SrJ%+Ga=Kw*h$}e1E<23r(&tZ_&m`Z<^j*6jtQ^W(W%lYT zw}Z{geH{hbf%_Q@UTw@;eRtc5TH8|>j;&eLpZnz-e4 zL($K?4)Q_o8CT}EG*}hMFV4^Fw<#+)x0TBwq#K$<7V!y+i%lfPj|5>bms}dThLN7KVNiPf0Bpc?`b)69Y1&qS@CzSaKLww zn*5v7PfVTHab1DI=V5Y%e#fti+XMSUXZJrjn|b6j8^f9HS)5^8v^=it_vt@y<8YZu z@|~o2teak@@q6S#dOEeAE1qoZeiHP+=Ih2a+g@~M^ES*|4tjOBqT1Ha7veUCFJ7!Ei%!%(?bE25 zs`%^Uq6r*@{{7c&8E#k2Z1^JM;QBiJ3hxua<5?+9|5F$B&i*dKU=y~NDM{GU9h}d& z4;Z}@?Rgi-q|~rW7t*QPoYTb<6UTkU>}T&{5C7F9`Q!*5^CeC1{Me6z*wGDp2> z|DEG6LMNO^4)K zl?^%yH|DE@ow)3u-z%eK4C_0pSG-JOx|H1@yD=Wz3GUjF#r`_5x&A#TLqz^$-xuy? z6N^p2d5D1_I5xKF>g)Ie%I`EKA4Y8bx*=y(`SeK}R`xUY&z#>dFJ~XSO40#;X|SJe zOF!ph*p?{#i%Xeh#>C$%xR@Av7Ht3VB#lXEZI$3#3)9|BC0#Rgns4=eS7NYP# z2Q>^1)|29w3ds6d~ab^GG4;y3zsvYa@l z_QlKXMzP@5*rhjY_O-@oX)K=a&d`xo1a(;8*L(IBSG_N>Fi86LT827k3B5TF8UG5H zoGsk2_l%cA74HJ2Z`!XWt?Ni;bzkSp(6QbVT-XTS7P*=6c%aNw8 zaFcmOw$eB4EO6^1((LN;?9TpTW`>_WzvL$9y8PkeyCv~fX4{+h8Ogj1N0NnqvB5?V zLLF5^8G2Mc+0M)qQ&qV5t-!_FFJ$lcezR{s)T*xQGJIKlQ)tb-pR2#vRI_ZfmDiuO z^6%?f8HR@Ix^bXbx~vR!qHD|~-Uh2X)hE~elmi7EyoEIP)C>lP`}20)+^+}fZWRd@ zuIY2T-NVN)!4cE}sttFXk-nu^V&VR2Zj6gFZ0|Gaw|F>InL)n=uy zZI|x~>0F(Xsq|gH=r#jGgga{rJJYLei^3gaJ}SsD+FdGBG?3V%(_=cZbgGS?WowtT*D%f0nt>$I`N)ivQF3uUGEJ{bFRe zlFoUp4;o6V6c`u;S2PG%P3XI0)*v?{xpA+jLz$TqwA#FQ{N1D#Z&?|VHnC`L6r5JV z$Z$biRN#=buH~&&`|WOWt;k$bDY?R%X;RD;EsrNl7A{W>u2vHbJg?3$p<6X#iGbz8 zn};&~vN9Z7$aE-8iT$E&s3SvFdR^;24~GhsA_dugGcHXt;2F}yYJL9EU=%J;OM&VFf+pgGf{y{opD=N_*14;a*mTlw^Jm28IpN-WwPi zVt+nX@9||iq?0Gbz_2EfQw$^_D!{-n>qGkoLr;eW*E=Q*4XQc^nHU(#9?!nO$k1>% zqKVZZSnDH0a^%#89hnRa48=E?nHU(}923%EXwd$%Q0&#@h6}ppybKK$P<_c2P<;&L z5xNWk{@*z}X0tIc97zN_WcE941qOyKkNfY=ncTo2zB7@5A$kJ~Hv_|s-u{QI3=Cz- zoMH?r2}hYOaC4sEyJNz@@PM`2fq|jn?urHm1_uFU5q1>?hN(RTml+ziV%T`0AylKs zi;0OFg9!MhSen&T+f+$nbj;B!q1h z7#I%Zsenn4@6D1|niu#n9SQ{{(<^DnE(Jv*!Uo5+q40!KP1uwF(6@mbzz@#6s5mi*)H`?~K5U@N=h z|NpxF|2o+5;`YC9p8t3La{Rwf)Bk_!|M#N*-@}ImKiK1Izh0djg3_Whadj9arp4z$?fg!hd&-Y{=crGqC&URvR00PVZ!N$1r@n7uRJXH@#;@{`{9QV zfBcxN?!V7UhL7KWp3To!+3~+`$@lf!+SvTrfB)aN?f-v^@BeZ1|F5(8b)SF#=U;V} Wvux(SwEYYW3=E#GelF{r5}E+rzr5f8 literal 7745 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 Z5my%4zIxHG!oa}5;OXk;vd$@?2>`Kn*!%zh