From 061a9c025b548256b2936e4b57bb0d41ed46209a Mon Sep 17 00:00:00 2001 From: Jupeyy Date: Fri, 3 Nov 2023 20:06:24 +0100 Subject: [PATCH] squash me --- CMakeLists.txt | 1 + data/editor/speed_arrow_array.png | Bin 0 -> 35535 bytes data/shader/tile.vert | 4 +- data/shader/tile_border.vert | 7 +- data/shader/vulkan/tile.vert | 4 +- data/shader/vulkan/tile_border.vert | 7 +- src/base/vmath.h | 2 + .../client/backend/opengl/backend_opengl.cpp | 64 ++---- .../client/backend/opengl/backend_opengl3.cpp | 46 ++--- .../client/backend/vulkan/backend_vulkan.cpp | 52 ++--- src/engine/client/graphics_threaded.cpp | 4 - src/engine/client/graphics_threaded.h | 4 +- src/engine/graphics.h | 12 +- src/game/client/components/mapimages.cpp | 4 +- src/game/client/components/maplayers.cpp | 71 +++---- src/game/client/render_map.cpp | 185 +++++++++++++++--- 16 files changed, 271 insertions(+), 196 deletions(-) create mode 100644 data/editor/speed_arrow_array.png diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a4a47f1e28..024cbda231c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1399,6 +1399,7 @@ set(EXPECTED_DATA editor/entities_clear/vanilla.png editor/front.png editor/speed_arrow.png + editor/speed_arrow_array.png editor/speedup.png editor/switch.png editor/tele.png diff --git a/data/editor/speed_arrow_array.png b/data/editor/speed_arrow_array.png new file mode 100644 index 0000000000000000000000000000000000000000..f85db1a0f4c0dcbf8c0566e3f42c197bfabc38f9 GIT binary patch literal 35535 zcmY)W30M=?_dkx$WFZNl0aO-I5)}kR3>6g@V1i;@s0HhWq9oP@D{81(M8TP1QK+II zAW#=VYg=urf-5S^1Q%8@bQ2Iu0tBKJ%%+f$Vdi(~`}2IC|NnV-0-3qXx#!+{?m4gX zx_le?`SLNg6Kx>~8nbdm*cTAQ0e^BJz76<=P4-QLppykF!$Q|3!u^+0GPbsU9MTsh zOuyc-Vf`Eejpai;6uGAbiG4{6+Uw!|B|i2TwnzFM>w?pNOJZee9?J`dH|sN>`5c zmCU(sQa2|_$B;kh%5=lI!qB$=Nhc-`+BB%u_;_gaGgoRpVy2Se9m~WrXqst=vHb2P zjypGJ%WzqALFG*Hd)+jT`J*+I0V~i%n+9YT9CN_QlWgeTPT~B#0#OX-`Mq6_Ezwpt zt=F+cw22C6+Y85kA^Io@-(S#gQjJy|6*Vounz?{_sxPFO3*AhLzOGR%@M1kkL)64B z9g&13;Q0RyRqTV?Gv||sLrsR$QRrTq zbPh{cRm|*!P&+Y;JsvtClB?bB+czs5&2c-+@X1A?b5T2$Xd~omRC<+@tbFRdJ(KNV$r>NK&|;mdj#Td~&I6z)$u#bLmdFW=HM705bcP{yn2+u`m`$uM37C{$5 z-R-2CC!&6CsZ-X}Q^Teq#5eWGh8T|dT7!B;q~l^FZ5#QwQ}Whr$9~Qo_EMT{{DF4F z9z-N=r11aMCT?cvH4|e;K1`kauZP15asId*`PnAyc}X)d&!2e}NBFcqwSJh|Vy%dc z94AY+ae?lUqWmo<#!4GRm<<@cG*=lLfdbY2mW6#{{Fvb^#W~yCkI?Ag7KXbfc~PuC zLU^@xl%$R@`x}n+l!xV&u;{djBa@^8*Y%Jq71}VNOZH0y4ewG}F0(vIcu>dN1#z^Z z&+({Q2kB9PbKeC?F|)Pj@VC!OeQ@VuLdKbCSK{?oN696!L?`Jf9KTJPDzIKT-#3Ym z{@sE9-lzzS6_ zQ@&!ASPXM}^-_P{8JU0DnT2Iek!oxQ{=l73i3FYTwPvXUg8>0 z>oltb`P8FXxkL}1VNo*!%7`GrkIZ1x9EkX7p;Vd&!8Oqiex9;-yG{jxIH_`W*+EH zDE$=wmsVCH8i^AilW9ev$QWR{#5- zX5m#wW_i5-GglIxU^UlS-Zn)n-h)csIO-#2zPuOklMu$BC08;U}fX%xo5v`59~9k5C!)h1rl>jz5i{ z$BV&1B0n5S=gS+EtV~dOyu6a*{u$(j*_Mr$&wvWN)T`*V=0Q1EOs*Y$>X0XGKs=a@ zGgKeRwfIkvyA*)YoBcPW=^pFkPas^sNUk@D>m)QVD0S#`m zE^jzo%?Hxw=px`;%Dqtunq7-m22aQSt3P(Is}pCv@NkgMfM%7h+JC>szD~*7;Xs4p z`TvtX(ySQskXelz`}3hyC~B}Mq$Z%|Rd5bVOy(inmPiU{&O0!nJgcnYMMC~{`|j2LI0YKtlB;aszZbla^gjg#g)2~=rnJ%m{s5=&-IkTC?^^gB=x~ieE&k-_A zui%%Q0o{w?zhuy{M`aydtrPHFaDUOV`{mf4bzbqC57VELL+w8``HPYKgZxLD;uLNX zY_ybq(pVPE?6JB*YG&g1P$r{MeKxuZG(LF2YGm0V;$Gg zckINnlM^UrAc_0e6>RL3PV`^p@k2H^v_~zKaDNtK%yQX@)+}O*l#?_iebOF_WoJ>J z%QG>=KrHQ%h7a`d&runx!byf##!){!=~B2zPod70&{r6FAK=CEzagT5BE+E%>97E&ON0b))R0ew-p4VU@gE2aP&g^L`- z$GDNog^h-d-#Fe|WZ7?y7W8MI2aoM~T)do^FMG{@@>ToIOE(-%<^)K4BbM*D4Oy8R z&=d|V!HX7(Db*x7>W$+I=UOid#5<>;$!Dk-s4Ku9)sFGmW3vy9f?)6^1~O6ip?`gF zbC5IEL*LOgyCfeq-O#FL?@G4P{06Pv}4xUjX3dErle zj{cqA$J4o}g!Ph;!Yn02x<8^>iNjxc(l^SLKM1$aJo3eX>$)*HUZfiugL?wkiuw^8 zLhfKE9_DS=j~boZ7OIl!9slfXX&1iY(nNhRQ-w-is zVph^#M6AA7_*iK^RVZ74g^^r}QgG9?H~QU#rA7FLo8 zA1AJ%FMWMH2RVcBieQz*`X)9Wj^A=1^1#l&mz^le6Up_lsz#BW`iv?1L=1+c)%Q>I zUm|Ug$a%$Vh*&{Gw;hZZAlBGq|B4v&>w_wta@p4@)KPMovsj9z2B@AY!qB_aZDW5H zbvtZ^>Yf02$Y0#j`YFto{(gH1l}LZ2((J?)Haiuv8uHCjNu%Psu0?@^6CXgfk*Pn= zU)-c{kyJl$Gj<31AgcX>Mr>!j+3=)vrVoZx6eBC(d!fKDyZV-XnDp)u-K4S`4XxESE>hfDS-Pt{Y^G|t z7gEr#-hvKHER@Bc?GJIUCtPy~a7rznmu59*$GVuJZK8&^S!>*&{?C(zbrSiIpw6IE zPEBdc4$MYct9#nLd&|Q<`fn+iRPbs>yM9U@0#)qXO>6s$u}P$ty!?q?-z!^}5FSbA z>Gb5~+tJ+?;fKCc`XO`a;x(-?s{PbiUG_zd)6RjoN^9RP$iDW3IksUSsuv+c6Ph5Z zA%u@0>@&(j3~s+{DV>S>t!d{{k4uj|`B2(L_LNq6EkMKslyIs?qt_hmYW2|bY_=~w zvgv?t3>krD{xioDyX8&nOtX@~&~0HOc0r$Aw|^y_*gtP;cg0!LixBcy?am0g#jEAS zf!jMI;}4nF_7|Kb4-VvE>qh%$U&Ev%?{;)9CQk@Amj(};_a?+pDryDEZId1E=AE!C zZCKt_lBblHXFXHKDXGi1qHTI326fpR={%XLm|D}T{yz7gTxwezp}1`cD9Nx)vAsk! zc;K2jGb_BvyklW#lf1t{BtwJN-;DmWPgsvGeOycx$omcD?RiROT6TZ@{o@hz4xvin zb`CVO{T2{r%b+8%*o;?d9oi2M3Oz=s|~#V6_$KM1}u2oew61 zhoiiFz$f2HUa{j!jmI}50yO;2U5!)5t_bwxB}q+#@OD~&HjtNOx-bn&GQVy2TUuJR zbIYKv{7GyCy~Y#2sd)d9y%H_H1Ok@+X-4TkE{D_8Xg5yL}puc){D+4JX?%lbuf8&Cxa2QC$7g&@aCl_*ar*34N1mP9dj(dpH$ ziQj4F;GEY!zaBj!rV`0=`)GPC>qm|&9!!$v$G6!+toV`ydb|Rk&#QlK0qQNczt8Y| zYDQ-DnBRt%ZJlQ6nDDLayHN5RL(c+Q$Vc!?GjX=jmnJVHT0`5}z-m5nQb1lEOa_LFvT0<@%G1HyP{ z$&NSYGT(Z#&Jvx^!yT%rtXk~FIcmGHe0H);+}u~;UJ>E@!)8f?h~mkKelK?!W2|l* zt?W-;$4>{Hw!PxHs}(Nw>ZV9q?tVfh+n?yxSm0i)v??|}o>L?tD((B4L=x80bDDvP z=atkC;+craz^fi<$=A4eWq4^Uy+UQpaOks*5SFwSbf6@GwJQtuP$iAKas%j@}Winck=;-=0rQJ^JiaFx_s~0 zRBEyV!F#C~$|a`HXKVrBl)_K9P6)tBmmp#T=Z1wxuk@25`N^L6Y7}1VpSH2y-bO2o zOb(lxqt`F7)98U&uE#?s9Ihx5&hl#jT? zJt}odsTIZ91Tp*Nj*W$)8hbfCyx-;yKRALGwz=`cuF7rBF{)isqg|NX2bO0r(O$#s zNvPy*EaZWb!Tvu$H)nn0RNr=aAVnwo+J@ygYZelOtVez56a4f>p=3#enQaaa)7tW| zLpGksCY18k;SS&1(w7@c&%=@>>~l&ae18wONUw4E$Lbg>&XcYo zd0VklVVqBAVYR~k6z;Lt6Edai$?ZVHJv^+YBmShKI)|;4rvGZ|f8aG2?7lw}r#W}m z#mXruxftH1wQh7s@imv*`cJ8GKvAJ9v9e?e2M-nfz|GVXr}IU{nyF{SUsscVSS-EX zlbB@%7$IRexMfsJjVSdKnqpWOoE)v&AgC^(~fg2pC4*}|Qad{Cg5)d!Z3bcwVVBu!m2sSzG_A;oJV zQ4Kw!!Y|Y;w1{#7jMO3Wrkoma3fqX{>})WgM&TR)R%}Im9PKC3oB#*DLnc66(}-w} zt(6;~@+zsOpa3c9r}OX^a6pjXf{ry)AKgk6OB0fZGYUmb*@bc zW3$UvGzf$zHrm!_cp?5sLEyj`c&EC(whnu>UF)rz12K!9$yXZL+!m8v*lSy`;6V&f z1EHY;=W0R1aF8|0u7sO|A3*OzF;2vo8Cu@1mis(B7J7uVcH|_({Rkx*#rE2`vuESZ zIoO&23?2;7j;$`}`CQ;R3sKo8q9%KeQ<*Hap-CA3`sSoi$~n=dRyYZD4}b=x6l?r> znGDY&maKHapb~a?0uEd5TrSez->S^sTk;x6AzBq#fMX zF%j?|g`$3=f^yLV(5$6d7BK9QlP?X%qEp|HCNR>;0Yyr}FQx42mtT$L-jW|HD<5$KdE6Eqx<^2cgd+r&R$FS&P-|Q??d<( z9HUc&%Pr>32ujKq`u^WUQMfAflEDLq8S`gbxaaUAm z>8_y}W#mq;NU`)?hrJl>weL3CrDw`*YKbWIV-PHS&N=`_SK=v-w_bXFO8Juc$Wnz% z)e-OD$kbniSV26cg4?W)0v*{7fU0RpB}yw*=wsIe1&_~B z0q?f|H_^xvj+SSeb0MWb(+ma&QI*h|XC*z_SeTP@jRQN`_m#gUQ&>NCvSI57uN6l7 zq8(0IdcBuxJmk#J$pQE`vurQ(c1ZOT4Yc1DoI@RsTQG`-IUR!e&?dKco8pC7co zUFtuyk~ex@2(=?g8i`AI3#dlYZ+glKPv;KBf5~(dL!6br=Lo z-&tLt(Km=?ZDg@#mqVWDJ}--~(HgRfi4o_hNcy}Zsb0#m<=}$@xOx>D-K8AySHY3Z zitiwRGNoiOa<+A!jbwhl<_G=8mHt|2hof;C03?Pl_XWZm#(j&Ksf(N*a-R*`SXfUY zlXGPN-$qZFhU~;=WCU+RvfbV(^6dK3TzRcWhNg;pf)AxQBvy9&wq}SH0@=who-ayR30p$mn-gDWX<~ zu#cdFZi&RM-ashFUHV>4CMy(*8U?h&Ci~OgKzQBld17KD;Kp>Oj1n#%eK78v<^ZRX zd%_gGp)Z0?(@ES4nZz_}HeRmEy3~hN+G1m-AxCH))u{(Snre*kN^YE2$Lr}@vi#HD zgqTlt{;UDU8&LV*6(X zZrj!W`gjb)cTQ&5icl|xmuBa`U9=u=FUQ8IQ!2S1ZkSrLrsJJYZN+M}i#!Gzcrl4n zT=RHh45T`;+1yvcZQ}swtq%E)^N7orrLM(KZ^E;bvZNRsoUg#@v?50Ywa(HQNKg%5 zvgwu?xsk&GEAByNrz}ZLB{U6~_bZU~)(+lcj)`i}s6%c+cIy3~!0R4cEQ-+6^^8p< zblKKl2Gu#qKeFmALoTYV8zH|g&V7NnrUv=fK1(Se)zj($04h4{1P`FJT9EH}qR zZugKfvYt&&d^KsRZP~Vpc)cZBKpy&w(}oVs|)Lxe6kDDLf}#r@7um2)G)&+YXYb zSg&~3pzi;P>j@OSIWWQM6lJFcknS99%1L8fkIQ6gWYP~tqUzC@8NsA)w2wdwT2CAP5l+X>5RsQT%__CL5+24D|)HAOHC0)B(9&1ux z<~v#cLxBC473mMNcKqm8nZV+MiN=Ev%jpFY+~z{f+XBi>$`2lATs~pRbmBAo^aiK^ zG@Jw)raZLV7O9tUQ9be$W1rNpD<)J@T97b~ky89^zn=9O`gc}TD*82R_md=* zCHo%l22WeZjYM`-PQ5>iyle}t6xhFC3->TvRiZVSMU;uP;;auq-%J6cnn(u-zRR{4 z=o22;VJ1x`8%bFTbg!~HJ+Uj>whA97^+9~`L|Tq8Y_JjwPw88Uk#9o%psB=UZq#wxo2*{ZVb#9*G zAw{i_`L`dlHM8e2zb~pDIdmgK+QAQl9r#eF+r85cQk;LQfNCI?S#E<=gU}P#iBjhk zK|he6z)vigjcHhknZRi~@mnT3SJUQ5qwrKeyr7Ye=D>&kWm%8Fx>7Br;b@n09ZXY< z9Y?BIy6O=)gyR6trhp90B@_FKxUkW8XTl~BKeT;Cw{RU2hriVf zw{=9kddXHG4}7=4cg)QChHr*)*kh~gvD2mtP^hp9haOh{3f;2vk?w&9?`3LkIG9Uo z1>$%coch96yb}(JC40FJA8f_m#6`%-*fC)x`W;yJ@RHtEe+@K|$dk=WhWm6b5-5uN zTV1;IN^hYlI|@Iobb*W=NY%BtVZV}L^;f}uf<+7}^OZW5!Ip*3kaO z4KmkRCC};=8-vKFYSry==2KwmTOq1I_TC)c7=jS5uV9X?F~-5QJJ9XeJ}L%1Ywk(z z-T3V|DZ5_e%{)&Ye)C9bZn6_^Kp}IJK%C2P&dMe$kPll9!Nq%u^SAf{rbaV)O0)Tx z-3|&-c5B?SusPr;Yx96S__dN8SwUj|QF#2fn%hb6TpKVX779QC%V~XGuhOfM3Lxj@ zP>DBkWkHB1(M^!I=AsWM+p@u0O^)nqV&q*8HirCr8b0;iNNd4uUE!yY(f!L`$zKYX zf!sj6yWE+YciEUU=zYbine-!w=<_e>V|zssX(SmdC>z{N>c{OFSgaGt=nvhkZI`GD zeCySt)kpXG5H|yLn#Imf ztGzQ0Y?H?v!5MqTY6e`A}XvzYJCiyXzNcl8_x zVsJ@9(?d(d6)VECe$Uz)S6YaLta;I?)A&;Zcd_k%HWB)v?r~b)ix@FlV=m35=a9U5 z;U(*ASmz=}elD=y=%0x;ZN71ADfRBJ{{0J>i0KTUJU-^9B^t?*$OCSR--B#EBr@Vb}hKs`C-6Lb&oz z=!xnZ_KjmL(Jzh;#J#gnixT99<;lY}Rzsb>uz#c}EuZPBeF@A$Ct?2#mksL_w|^r^ zb!DEFYOK;Y5T@R`TeM+Kk^wwbh9shIkN(xk)79O=3~!%Gn2%V}S}H2=>C;>;%Qnct zoqA?(y$c}CUP38*`rK09E`&jb{7~tLcMwrfl}0o_xA+cK-xRT_@fG@^B+adP2l@0* zH`z%dA7%`_w*Nw-;eon)sNaX7;+WW-#M*YfX1J1ynm$HIXh<8XA~EAsb5@jddxCU<)JFw`rGN@{v|ZDe2Fe#$+X z4o1ob#}i)@a}$W6c5?tGFjMb9*lipahuO6auOJlz$9nenj~J;l6+b>0`j7=&G^%{> z!1wxM^{Y7M*8`gORI@&YGGnhv-{I<09mBIg2vVkSXQ%X#fA<%BvlBaVhC014p4xA) zYkQojq^n9BGUE)7%e9u<<_`Ilaj-DUBS7c98odjtXgdnZ5R~ITwFGE z*3A56>FDI$ccdHXV>=nX*1M6ZJ2!GdU)m3OKbEy4*ZN^=yYR^|=!{%+344P$;A6&? z4H=Gwo`^~E#{Cn{EAvIP*j{AAADj;$*luy-bC@j{*T^R@}QM97j)(cD&-S1pgiowch*0S zr<}R(7_{A-ZS>!3F})Qj0cGlhPPCr&I~Dgdc(dShdK;+oBh-91f<)fizqoECvkq9l zx2{Ym26)Yhnbm2fh-XcF!r|YkQHI3p59M(S=#-OEv#{AiiuZM9#OCyB=IkO@qfL+y zNms_!d1+rd6Tc54o+-QE!Peo00RE2qYecxBL?_b(`$I?wyZC~hw=3rb&sCn&tm*28CLHf|iP`35y-MLlCDzg8BN(vw5XrWg{1a8HFSpZ*zOrGD zm&r%Ey6Y^Kw`ZyCrjB|3#MTs0IBX&14Z4CEmJ(JIt~m0CN0i#!6kTV1Dj~^76SnyQ zMjnEaqCCy)Vp*Zi#Q+y$H3bKXm6u>bGn09zq71gy-`)6D!*&pOf%If#z<8orzI8}d z2K2j!yz7bGe=G?)jM~6`)tR?=R&&}a@kg!U_9xW47G6I*3V>{43C7YxDQ?=~W)T(l zsg7v^&j4O1#ND*ie0EQ%+gWV$pTT8kOGgxi{l;$CK^(-S_LaNw6?1E9L~ZP6uQYev z!V2+J^WzcbxSkO0u&J-XAQWML3Q*&Lr6MHlL6bVA8CsZcq4FdM+awY+3Io|NaB+G9 zpyHHTgCXs#HDV_7vXl2w5qzH*#D3Ae%^l*f9VSs{-IBM&0#^l~fGM1_$1L1yPwO}Y zVtq_?h#5GTox^|@SJ^D3Kn9^v19%jU3tGFdB_QBdTFvZ9jiL0Qhbu0NM6Ezg5m_Mi zeI)B4M~?Y(u$*A=$cyFcQiq$c=C#M6*Rn(H_8XkUEc6D&w{o3U7_ajJ+2;vU$y*SF z-_acP@q)xP?_Y=h0+f^RhuotZq{HZ-zi-d2{nK& z^&kSnDyUmYxZb57#+ANE0k%0gCVx^vWkjLqwEY`>>4V>c*(2p1yeA$wIRTtCzj7+3 zbh+d!&s)Z))M_N5VH9d}Gt5VZh9zm^Qi*wNDdzz7ZWCm@08$FvBa`re7( zeBYSMJvlScXU&Li)JWc=(Tw{=J`A(1HnAcn3c)2gyblwmiGOL}nKe@*{))>5r zE^>1v@}#QMrOs2*IXz86-z${rHb8Ux?4 zrKvD=dKk))Lr4X0k!R5|b?HBB3o*ufHjx@E)@p35DSCWG>Wrp{=2yIGmk%1|R~_#M zN(C5TJ1^B_yp6Z=2BBKvcgzCd&e&4WobP5@z!y#csTzj zA#>F6Xj)&n6ezNFylQ>e?n2HV=5jz11z7VTVG$=uII7_Gh$TnpH}` z@}yIQ49;1bY^gE8-k=v$xIkcI>`7AX!Y!60txY3n#GL|2e9GrQ6MF_<3FzLt1~)%`2M#+h8IOofHO52x%6m}VBbX=#hdx+zsjqh}z)4n5zT)6l9z|@UN2R|1b{f%*Gt;jw7z5o$@Y{kWuciy z_Gm>IVCw$#1kb2CD2JtUX|KDM4Zs;hhId6w*ey$>XZ7Sahj z{#Q|T(BFetmLQzlna*yM7$>a*%w^e3IGm4aJ$A2>mQY_NNyRns=ugm|75RK zk*+gn*k3wc(=l&@z*duc2@-A$c7z_@_x{s&{IS?sQur1arrw_q2QF%kIHw&;AA3QU zPrJ{137C0T-huU8#VeSeVl}H@jVjyv)hcNUXNfHy$?E*WoRm;Z{9Ger{olaUG=1$6 zQqDjpoWM7xs-KJh_?hs{@Jb3lQ)yJk=`j;m-L4FyaFGh z1j_W>Eim?vGupjNL5{!G%to}MC1pEp?0oSJXriFS>ybiWHMD+41-JM;nxF_Bc*x4K z9A2R+w589pdtyCTFdqJNvD<5*^rX{kmxq^nax1(}oxe^SsgO$)^6LN+5A_3bdvCeh zwMg_daY8~o3yvS34xn>AF>+zRE%HxYpkRD~C-LKd|#5v_RJ%$|ImLA@KZ~uo~ zEMo>lY7IT(suc3uLe_Xm>w?S13;cT!t(R2ES-;Ys;O$1GES6J=Qf3-by?77lLOXt8 zX}@e?$FDTE9x4RuaZ}i0=+wKEo{!pa09S-6Q&<9@ilLNPc_C*V2GU+Cls-~D(nG3y z{K}S9Ky%cpg9UiSInCJW`<&N0A|RUVBGqsG%C>&Nx;9ny8EbzDXSd}oUw& z{d{6rcMQPtOu4|5|G-J`NcJ0A6|!amWQ6X&b*Z=v{j=7xmWN~Y*e7Iow^@`(A1sg? z9m?l{3S@gaGDJG&>HoizLBCxJkq_`oo;YDP2 zmQtBgMEsbBDGQ-L)OZYhN3>7KC+ydmElwpC4+lGk7}lXqcC99WeFsXko(CC>wx)59aBaFcky%P);>(mELiW6oJWwoN?n-f})fj2^mY-^}bcE6ZC_uz-}jdAKZt? zlQ%BaaK2TkH#o@c{swv8{qTm{Z4QDKNlGvv6a-;~kS#!|S*SPkLpY8K-f<(71ug2* zXpnb)uVF6_FpC_hdACi0jmQ_N9zzsU6HJ9XjbX+=F)=TiWKB(1QdvP~sd>Rv!FsF9 z4JbkvT=oMLof*SioNBW3Y@59XBBmZh|Ib2K(uNFBlAgFdC`mB))oT=wxjNDFnr+`htigyR1&O%H{iae*UNs zlBFjwezU5fe*wje+pbIAYm!)cfx`|w753Eh=V=rB*xBlvIm${Q1dnGz083h{ty}Jc z$Gh3^%U&m`tVqpRCWr~{5q&LmMK(i6=-F`Ojk~YdzLkO-V2G**#>Mx`dh1RMMjm_p z+qaJZ?;3cO$d_=CYbE4i9|K7&JY);LrFJZu>|q38J^p7;j~xFYV%VyJ~hBA z@b{mN!^WWic+N|YqCGcG`~$v#%`oFv==LcIei7>Nf_zoh(Q#Bm zH(6PQ5Xen<0noWy!ych74EkwDFBw#9=Qn^vGz@bx9dP0aIQRY=w?Avvj~s{-^78L40u-@ju13f7@fSo${Wv%9>hcK$IeBgi4t zG^hn-Rwot5^%=6vNq!+J6`M_d`4?*)sd4Z>;R|hmP9tUyh~p}QAb3~niC65rGawBL z{&tb1is8Q5)aXkI91q_UOx^9oFKKa-szg;BWEFY|5(6(7hXg8%qWia!i15y9Z?>P5 zEXiW*di3G`AkW}ivz1jpJBITK>)GsTPQZVk78dRjdJ!7;Ol9r4PQ`^}$*X9BJP4Vp>JGy4RGXs(=0TWaBImlC_vRq3!=K&o)Foku0f)XU7u0f|{sa%%l z97eqdjbX*Jd|pN@;cyom6`)^&gl|Tl=2rSS2+Zdlr^*h5(+o0b5?J=ZSmC>fu{08Y zERC#3LaD`3qmXvG^@AE@zD&rsD$WYZ=^`cLTQ3*Ld$8@1wDKJF?&KrPF9Z<-4t_Oc zal*$--9OA%NxWLaXN$dx^hC@wtMhmrkCXW&V2n;m-O2Jn1gqN5^PXSBZF#8N3 zRkLVyBHd*rwgk}AKnCrbZeAxE&4UvJ-8_&3BYRmZ*054Cw6}AaYhvh;rL~fqFF%iM zYTxKA{lP8S#<&O?#OV&?VD-T z;SQAjFGBU)LaYzi z3~!mpWX37X;bJ`VF0YgBRtHfX5vvl4Wz%rrbuyHMK4GoW5ncv+tAFxVl6Yz*mm14i zu+t?*mgd1huh&>Z6UdGT>Y(!2XgUIix`sjkluuPDsMnnl^tdACIxxNgCq+8}O`DDl zF_xEh7h*kxzqy=2#aI;VVLIVpn-d?HE+|P6vWV=5L#y$!B&Gh!P>5?Dvh>|C5YY^? z$m6BK#=&vKplY_QCi2{dSTYfPgW8Pb+3=Rc&_*znAMBddRFf8@arViu=`IM5LJ zwR;rF*qN0r=HGTbsbUsa4}w=CAXQ{hASQM2`++OgBxWNQ)81v~(Jz-Okf##7mYGis zUZs*2cfVv~)Wq4$QF5Atw9C$D{)-v;RacwIo6@s998wy9iL`Y%G;jo*H1roL(Tns8 z(8R=n)zE3{tKlk}wqc)gEoh(HV*TZ=&`;X!qLRUA@jth^Bbe0Ek+^YER>Gcvlya=Q zkZGMwC;>ff&mz>tu|PvB7E{ClN-BVMMRId`L|y)J;Kt~MsU_5}ZYF=@WMZ(A`tn^; zF%VnEq9iY}7=n7)14a}ltR5L(1+mP&$?#k{rIl{|oQC?JMTn;D&64#W7S7YOH7iPq z{nkLdX<`6!k39X4t?I!!3}-g=mS50>P{eOjbah8O-fuR)olqyNN4$wF3{NX5#Jt6f zU~(O{pI0+a$DBd<7G$KS)dS2!sA~?$ryLsKjy?!!(NuL8AE6=`>oIkM1l2q?`>M*B zwIiAwepN}E$vKFfiy4G(^mwQEtmS#bY zqiu;viBsNjMF#8L(M1yOzzpUsg4^!0N~#Qnj=hC)jr-6a&2qQT(Ca%%qJ~&;v8-3b2 zM7CeA+Kk?eGlXSCCwViIh|Q=e4(o31G`SCdMYiV3Tv97Z`76|>7VUm|B@fe_hYl!0 zwnB}B+@PFNz0YQ{`8OM1Kr@TV(&%I$#Q0aQf13SC5&*!4UTj~B!o66#`jwS%H#b@1 zP(z{Yp_9%oCCZvK_|rO6uqx-L?ZQdSW4Boskl~9;O`9;{6Jpk;hwl%3&Vpa}7A_LC zs;Bl~JHd^;46o&=jqi=ce#E`ggxL+?_p`{`x)!VNZ=XaAxW$`KC4azfrTjH1KWNs2 z&E~5*OK#jZRz-g0CT8p6+-1E@%(@4ni!VKelPh}X5_6us6fH)hhn*RhbHvTTWYVR7 zWcfVg!QCNqxEf(ziVpXW{ApId=(Mf|258@4FVa4IZ}5z!Z8d#_^wPTIW83#z+$%K0 zc_yV7ditLRqA>=rPz+Ipv#XLcrxX&jG>JTXkNOuIUcM!j3N^Mxsb3E79|%9+J){B1 zuRl47-5NCG)Sv!6>$d5(K~^f&1O5F zP;4T$lQE4S4kiXs!v*X7gr4&IhM3EfplNz;XiJF$kPP$wq{X=OWjPF?(*6=LI!r8)$sS7p=#!l!QK?tzl!|EgWHC= ze&lsu@hXhF(S{rZ%&RF;3(N#oac2R2d;Zg}27e1BBeuK>ZL$9IaxuESlXx ze)rh;tO|=H{{iNGa}p|psL&R}NW{b>=3x2YZL?k5Y0a@|T48D}HrQEy_b^o(@*6cS zzhvVXjfgXn@x95t!sMQ`lrmG*oc7SRZei-Y>s8p_hGX97>0^h_xbauD2y6HALVLi) zjq<_$hQ)6TPYmzu&813WYwG?7X-0Ymed^xeK$YP~Vx00z@u>g0CGRZn-nXrr~u7K$hD>)lb{h4n%Edj_jaC0ot5HH$L3? zY7ld;=+T&yG?paO+o!Qh(R2LbluMuN3QT)CgMP{=3`v8v?!*_g1HU%f|^9z4oO_$^=DQ`%2=K+5Ctfj4e@TcZR=H74aZ z{LTZEbN)YDM>HHa;v7C0n)rL?@QCcFbQr6%`VJR>A`b7iCP_v*y2m+4r+04={Mx?w zpv}l|XE-xCOXkq?u6_7(YLTg(YA`H*TWffbG+2GTYMk<&cj*|C3l{zh`p)}6lsRZ9 zcQ?OXf-uPe3z}bSvBJ8y0{t%GBdO}Eq=Jh;VjlsC}#FSs@2A5fj`*x*CVM^C!O%ou`Y7G*VVJj+T7-@ za(D*!GuEzl(i1a-dyd(Q*qcThYMr7IF^lz$9_$=~g7ReqkM}Dud=tq!l`^+y9ZKpyFm~637y+o~6LuX~+Dxd{w5-!Z1 zh4C?SEGdlFX1|A3vIe1n*}^!s=V|85!A`34X?D080{>BBH&(W7L`iY}!8wVN>`Bw++` zy+rhd__Omh-PXgG&2<`f5VD9}%#^l){~wVnx<7T&$G(q;!xmY4n2~V0CBqVZRhW!2 zmW&W|gj}jb2YM!dw0_Vd#&18AyJF4oU67Mf{D1Ae`B&3u!#|vKp%joJA_yq0qlk!D zT+u;HaTygHK~Zs~I6C5pPH_ViYyvofih>B@O6%={jteL%I*2KPfS}ZIR6xa+9Tn&X zG=((zUd;D>&-?xX&pFR8H>ank4N0yoNt4fZks)xqDZMvdFaenk^y}M>Rr67vmYf+1 z5(m!ig32!kYc(MT`q~r(gI2g5e1tj6$?_qPhP<4<5k1}_`>@#}#Dq+f4y?1hjq7CE zcx(eHcwD%=X9x`~_4c5QV!*r768gyKiTY9m}k$O{Rs2c^4b8t{4Yu4*e1Lkd= zbG2bF@E~+p`zZMfl5WiF?QL89AjFU(Zu)`AIE)Y#9paWj_0wvkgoE`NL9L(<&t5AL z>%=~wX)LDRxvdof_kEm2E(|z=D-l48FQjcCB!n4g%O?)Nlf>?@OzE0 zkP}DUh!-gloVB*7&%=$-ek?Kp@F5?;IYgfa(4zybJJ6{sqDpyuDp5&g6S17u#YRzx z^d8V#B|5)aL-kdJ;vw_EFVOn!-o?3q$eW9v=-I~U$8z}qwi@6xFyE!{aZYLg z`H6W@`qIs^kQ#2pC=VW>qUw;^$flhV|4#QM5EUH{{YZXWw01nO>qog;0`;xJWIEwL zkG^TWHePB$oi8D0ha_HOF!)rYdUl;Ybc9S+_-qdaY$eclMB#?_X)pQN<(jT%cSoHD`0F)g^qeR_?ztV$ZSQl~;(iKG? z`L=2KGFbyN>J_j(CEDUI`5HGLsb0%JDMqzNpBYUZ0?vZQWrNGv-o96F%(L%WIkW?-|f+^6qn5_oG2s!kI+JY_VvC zqwTd(<42){EZ*W1gixbdL&rMQY<5+P-$i($YX0|LI zqJFpZi=L=~82>v@^y)~Fe(*ma5+}YFwp*(Wnpu$!#@RoD6f;S(scxwcz|^7TN$(-! zyo07eL#>AWDMlEvkc6neO|T!>y7sn~>q1Gzzen(bp01={(eJ@659#542b zeSebt4^Mene7*L2WHeK~SaPr>|ENN!Vy@)2SMy?cko~J{8NO{Eshq|H^u)v(o`CUl z65N(Tt9`jg+z!T3yC}7_qsX6Lc*u4uIKc~{Z>GJxtE{mmc3aAzdhfN4t6SIUONjTC zBW^=|PO58MyWw~?{}Hqwz(i447@uv#M35&DH9_rWXDPQ=tApkdm!Q8k+m9E)U*1~- ztB=+VS|}%eo*144YGYus?aXroAy_PPiQoqG%{?SAW3s{&nwns(MoR|bl13^hy@a7o z$>bdk<0t-%{?$8*_G)n|8L)IzQ2rq%JnY#(Du4l5Osj&|qSe$1+6=WtX6pR7*IPMO z^1virirezT=ZAE?g84r~??v&@L~J>9lSpJt94?x;h-yDO3_E!mGGD8_f1BjP zJU@RF2MX|o;L5>x_nBD%2!$KtI2_f9K?UJYL)qofjf%YGJ#93tz zd?lE_{1mnaW+YhOO|brR!aF`|D=40J4EMx#%$AA{A49Dy9U`bafFz5?uXWALg3N8` zy1mwM>L}A-Q2GnP_yDkZohs&;ocYrJ)db~V&}+X;2*+{X+DFW+;BVtqjhBZf=}?~B zFfT;EA)1nM0W;CS#4JAq6+j4kyB41&ZPoHpBl?2jM1Mt)Pk55ne)5;#v2$_CTOeY1 zZd0?WEbYsca!=93H`E^zC!_{Yl|lV|zJ8topPxT6Nw}t?VNGET%%G|GAMqppBZf+5 za4R&hKbiu4JiZFrWx?QXXKWX?x^=20OA0Q`+;FNNTg#Bn@IZ$NpSv<{OgIb_{r2z- z+HGxK(b!-X!_uETzOVocfhfrm@FCJb2)1ANT*C_a*^c`kCy_T59@~&M}9y`hl;2QI34Cch`AV63mex}jbmR;tEf z%aRsN!Mr{*(GOjmDHvyr{VKiVswWK6K@K=lg#3}dzvaTXldR6kbOp|T0)gJJ1-eg# zTZG9wmMFu&!SzDLGAx=;g8%GqL5A`gSWm}vC#!zQP)sNVj6#j7g!6erNN*EhKmmlF zG*G1IC13GbT}`o)0KhK@0>s};rIJ!V;u6ccOfo!3kxmr8Sq7pKdVSqT#g!E`@$1MB zCb}OW@Ao8$C+I~Ubb8eSS;vq~$#?7|KsROZCu0YxaBkITX&(n0NoXJ=mWzuS8xET4 zzR&3d=B~3j*eUlVzBt$Jo7)?M(OT~E?O*N$VCud0^(;FDZ%G6&4=CsF0`$?b0uJE! z4^fhr$rLYtjo{D*oH65$pj4wZLX%2)C-}f7!Sa>1f?DKEfDeG} zg)6ufhCvy8eE{^u`IL&G53`%HYc; z@2F}tegT1e&sO*|wx71eXFUjh$1d;z#WClZ}I*><#z+SGzDrK9_uBP7cw(3cWriLnCd1=zck2abae3k*Cu7#P4B z^ViuNYzejlDwK=RpGSA%V_^pzDg`&B%b*jRuqn3dv6ClIb)=%vC0905q;t0egh8ZW z3I^T;STn-R#1~_`J~nj(3`2>{Y|CQZ0qI@9Vj0I$$y!n;gC{8FHOb(Mkn2S{oDK$? z$-|*iU9kx&cg z3s#CS6MYrEvP2B}2y}>LnYX}QLpwfg622Z{`$54v;Ek%_V@qI19J(`{&LRPaMmtwo z6-3D3tDqVUzVgYZO#XhgASh}J|CFlU8Aw`peT3Dg)V)C)P zM3cuw83K)dm-d`z>66QkV;=jFsYBpa5Y)7-tBK&BB`*VmTmWtP<13z}e3qX8hN)q5 zAgS$Wtdk?xAud@e{SuJM_77un606_a=;|E|?ld#LWCG5U22ij>y_=^}2BW-A~ zXm3j|#Sgk<1a2|n;O1T3VrUKH%E9h(Wp)wA7$FUOCWEkA1GrXZbhkepX-EJ16msf6 ze`OToRs8|!8t8?vG&t}PICs+Y!P&IS8b%x?18D9>9yS465@W4Ee`s^cg49q1!$t_d zfjbSQCjK3Eyk2ZS27=+OT{>b>*LXnt^mfg}-O)ClKvCW$l=tCpUux>xNRP)5vl>Sr z{-qX3dfh6bjN!J(2@05eRwprZrLi|Ipj7j_Q2#;qB-IybQiDIu{Xr2&seaLZZwR22 zi-C2^2k7t)j}+z7e_N3&`_G4j4|$8xf;K zll07d%svJ3!nVS*V$PzjTaBcL<3bE(Tato=B)x$He*(!YtL`xw%U-x;BE(oCPYRb8 z8W6O#MmSj^ilI8v$&XtYmJ#VDBmTn}hV0DKb;)PYEh)q~#w!Cl)?U-6#vOLk2uf&rKlG-Uj=D|mEM?{ks6t&k}`%w;@#`uivL>_ zK1&%CQ@{Wh`)9WUtP1Xxk&=~NKJ-5>hxyxlDdC#7bTTnQ?-d6#SZm3LzNXdFKYz?0 zFyI9Hh74HusBYmiRVaNjy4K1F!RmfZ-l*wt z%0Y9{*msPH>h!1mN^bxDW{s0bXDoTq8hjDh3PGyNCo%b~vel`eA3|Q+J~jUVP_DUt zLoq)R)KkCvS9Ed^Z(&p{b1R`o*v4{cXtT3^Y%#0>Xyx z>n^vcu4kh)-!ti6YY+-{CUT}^Gw>SHMmanBW=9=Ab)spe2;TVdQ!q#yYE!ZwfSatj zemUz1X12WXT%FYUq?qW(yt_!k`etr2cKW=bo2zH0{?7s8iCMO5=d5sqheDW4G zNDG>OAHcQf4KmYNiyYclH^D)1zG%>5>|~&(K-16y``&>p=p!T04%{Q5P)r7YVgN=S zJT44)O11>qjYWIOo(&>73)bJ#dCO}oNos>4?41o{YQxzH?w$dPPvRu|t?cMAL2vfX z#INZG8F7V_M)tidKeA{Q#q*+HpWl#8M?=(|YWfuD?Omp_9P};=@QC>V)^eR8KVT1F zn9kXk8}Jj|@wuuR;Q{WqxM4QUb%mUX0gsID$u-a+?s|Jpgh;v$?seb(G6(CwAZccF z24(Ed58|%f(U$IoMP>fJuI`=D3)<>V>caXpuByZJANh;Vh)>w}mSoE-e8*NuM{km@OT+IE z+V3lFzisa`e27?xt(^^6V_@dpWx7H;-d>lKz@43YdW>3<4JpxtaDASIALJVU+8+~# zLM(TA`!gqo_JX7W4R`OXw^wVVH@8LqeW&Et^HG}o;q-s>Xfsjwv$VlIGM41+?1rT` zq56LJDs)8iPGZH+-vu*XM=v242%$6pz+W6@oE7)yZbQZ=K}(L4!1!~0gL_prR%n|v z{Y-LOnm#fwk2S}&hc~}+6JS+iJ;{pj=0L?W-KUSPxN7j5S)yMI46sRQhg8Ig#zUiA zj0=a3plSVuyd>WGcs{_^&&c}&Lh$~%xEFjPIb+cjG)@}E_(+cMpnKgPuVBo(LvnI2 zWQhxbuOy%3nL*-59QS?#AixZ#^-;^EL2Y=~2WsmC$~#w;UjqCDhfee7;7W8;KRHY@m zN5#MH$fl1T#>LW8L3%`akesH@-^dF6)tIf_a1@zG9(5Y~WbmwCchC#rfOxR8Smh>lM&}ZJjUC@} zXH@9R?siFwFX?Jd%L+A3!Pix+rqQ-3zI}BiZDq2Ai`~*3;zeac&vfdsE~*&qCidS6 z%IH7-WR9$;ZD(zVqe}9ZziiAr{nRqPwo)=lLKU^0eZrbmFNwf~RIEFckVwz|)FiV* zK6b~D-@2OUK%|*xetA^Z&!QI(Y^J|2CNI;yxbArRy+(RGiG<9R*`b|Ew+>~)Kk3@V z^yxJ5i+Lvf_hOzO=}v95m38YXF}z;W+Vj0BEFC>t5{yKGS3XNrDgF30>Ytl-_tyCjO6>erf@@a~nGHjgk_i)6IbZehS;OxgtXV;*0RN~ z!qdgW$rsCqT9qfFPJA{85?2w9c5i?0t)|mD4-8#^TgpD0#pafr;kdndPWt zg?Zv5%Dd9Jbr(x|rzh;7I&5Qtr2YdnkYlZ~(Wz-f-U6bqGpDel$HSJU`)^aIt>+!GDxm z-!!r8kWuTwzfu@USZgAQEBFFp`q%u0=n*_a`bt`=eex4_%6zIFAE+~nJMaO6oO(sf zydl$hJeBpp=JeGFVV|Qbq+oYN-@2 zuxm% z;>5khCN6D56F1=)a64G#SyB^vf!_YRoWDBXfmHLM~R>>cYpIB`6_WtvHh>TrLi}5gfQ>F z)_Q0+@bDxzA6lPJ9V(TKl(PIoG+qNp&@lTWsw@4X^@MQdM1Q;C(pLYFyN}&`jOfBa zP$>8q-CyT&_z(J)@<7=MEd;IEl98Qcw61yZVdGfyfVXv~%?j-K2-~iuMZ6pYoUMZbd~D5DLjk<~W=-;A@ASoJn7? zAlNf~wDG;zm){5c1lp8dMbkH@dW71QPd%BLVS%5jlA`pR77e1i(2FT#vxqh5NA(8t zSbw=z<20HKE^-4VMqetU33-W+qz#JGp~)TnHuTTx*gK`vp?!3FmxN1g-ax+)9wNgU z4u;`}c$VaEO_d3qU#&}Ew6DO8>@Drss`dRdQ6cX3^bfH>6IFk5`q}7w!Y|ou{Kmai z8g?@=TWn7r3Ahz?k$ydMJD>9KE&d|pCp0n&o=aS%T4YB^S3r|ToVIZXF`Up;G<9qx zBDHxI#LdJDe0(lpOS~1E4g_e&m1$yN&NQR3W?lEc$HQ@u{g{>q&@e{ za;p{`vDy*RPWT|^7B`k$hTYu|Zar^6YiM^Fe^~Y&$mHWkA2|4XW(vR1WxP~9Nc6#v z2Z*_`wqCb=B;4$uZUMo{^%CD~twE8Ge#OM0~`jZw_{>8X|B^C=f>v1txl zKr}mj0h@g);Y@jy*N-*($DI)n@yuwv5$9+x2w`oVi`wZ`en61mXd}H^J`bnu(?TKZ z*es+&D4!fqJ;oJd2icJq4>vimsP#+^x*e)e+FRl%w8mtP7e#b9K%hS37(RJ|xRHn5 zEh*!tJa)tx!Nnx4u8{Ry>1lUH;6^ctAQoXtE;ZM3J6PD_KSh2|SRBH3Yq@?-V0|Q|8gOHGkNfwrN zA(ku$2Zy8`mLsh!EtiEG)@NNG*Z%6YN>{t(k8wR4KAx5+H3{*W*YBPG>CS|qr2g3qBwrTK`x9%dG{kJJQi#&=mKT8r>R}IDuc9(D!-YdI|KP-y$x=mcd%`p^TPqJki==4FETNkUWXpl(dhUBFcK_TRPyKTB|ZWaUS|U z;GHoAVm*6GDE9;{-97BfPV%ku=v4a7L2J2_C@_dTpSW^OlF9jv{W1`yk@y$uik15P zltd7q0V?wFM>LuJ*kH_O?5C(L83(K~gj8kdqtM@j4;0sG5(k}A={LF#+(Hv6pf>Es z;oj+%b|MIU46>S>x$W$bBm8m}D}*XbcM{zsU^wd>;8r`yO^lhZRgwTuIVcO=^9ITN z)vwKz6>Ig8E+o96=}evKE?M`6Gd z3^NOUAp@mw)M#!pDiqW#3ATJo+LM4!LJUY_s?YT3xM) z3<-x$6$y^qXH5Kq<-%Zvte5_p>LhY@2YuhC8+2AMwzsm+I*CR)DN4EWG>|pYY%Lgz zWqr1PWi7V=0T^%B7qNV<)n%)StFLvjs~l0WRQO(@2?AVzb$wVEbO+pRilV$l?ao@j zn}9|NF+H$LF0_{0f%IV=2)m9bnl6TCDzS3`X@I4EJzX7XhcYLgW374=4y_Kwx(Y-5 z@M#OJBiI>^ zLU>vDWCBSE?eRu>Z=a-#{vdM-t)O2wR^fNj(I*g-Sez#2+C@ZpV(DqnLRJR13;^~Y zRzW$|iZ;gfpVlY>8B@ctDY=Oq$`x3`O9Kh;norO3*GiYl zUjcJyIBQM0rsi2rM3KEER`8Y_GZ7-3myrwMRokfrZPSE_K2&^QC&dKZUj;~WI;qcb z5+%UBj0Ygty6n}@r_9nI&z>*Qvx(<;9OYs z6sjqsC)oEM*drANbdP=t>AfWIz`Q?6_cj#H5|_zVKu7(35iztG{>f1^JH-K?*31ZD zq)iqrY-cR_Et~#*#2`R?S>&f$khZio$-qd>R(x_HnBzMyxez&Akq{%R*FovmNuc@k z8%Z168vOChmB7=H+6wFi;}mma=Tn;P)J{g#_zrJ*Et+reos9hjeP`UT7G$EWCU?>L z1dF-26XdA|=F5fQ=5CTpWM5+}>H2CE|8@?YBKqhBU7{C(M(xPPtpyjwzb%JgC19sk zF0sp%If*8sUtB{V0LjMOZPgm{HXcO>&z(g7nMnUVpZd{OWG}iT^Tw*HtbHhGnU!GT zC4N)bkM!|cA^cp2d;`JYmx+8Gc@}bUY3Hwbj?cuIzp_QcI0}B=Q%;F_l@GPM0{<O=j`%!XIZ`VQD(8*HVED)oygVNM;DbE3_fT4hnu&O>BlSK8M9;B9{(gQ>uxZpFqgRgX^hVI zRtUsQk&kO*4#})9^Acs_MH8vbj%l(7Dhbs#p2?@1hXXqHlg zyY9uqtb+VM&;^Bc6BKWnD^*x^IRLK$g>E{-HQ$?1%VQXJ2!l*a?d&#qlk_ELA*jgf zk=VFY6f;U|=@GbbHa%!+0IWm~poD(iQpB){$on0E+cdKgFkK7q|9-_8(YX9XHxZAc?wMsN2VeC0Lh)-_gIsI5C1TdmY*S{Xwwo&!`C`wfWT^ig$tghKQ?oBLWx z5}`V`httv_L0_On0otpDIdX90n#n}#}7^z&JP$=7haif&c*^txG=&70zXK~WX zpt_{bA#Oc3_w9JUlI0fsq|{NAD`s3R0g-cBbT<; zC72jz^H_)GwyjElm#s+3y+K~G5@J9qmt;wmbTS^xS*OUszu7(kT$ho$N)X!TzU1a& z={d#&IcqrS8|Wyy4%&h*gRchK3GkipO55*e#N-Aab^nEQ;t4}x@M>0i;@3y6fN`lqPDJm-RL|I+Bv3Xi2qst3V&WC+5#bAz)~~oPL=(>te-)W$SU{kGxT0+txV3c zBYz2#DhPMPQM))h;+{t)VAQHFqRU?9_Z=aPg$BB$2%8k(+#yWdFJyOBX zG)#B5%n-M0mDw0chJ{cdx+vP>LLHI5#I!nBRhZXWcaTXLualPMVKz--a?2>MNw94B zoKO;adIe&*LmjFWSh;Kgm5TIxXS{`Q&wx%!Ho;aggI*bmmmlPDV-trupX(}e+69w52)6@exZ#xMm<*-J&zMM2n!`VMl-1PZe+ zFX66$XWxQ25sz7^GEXRhYe(lPTr-@JwT$s7W{#E2KM6^1L!MzS?XtqbWFO#Uwz*-S zA>)I(PRv^>z0FD;GnXv3_qn@X`oc;6nrq-s>X z`6J5k9TqPdvd5DxKeoxhL0;F_lCXtg8X;z6ot|y!e@SoJ1KZW&=L)^t5t||iuc_!V zuMMOo9CQefdgsgztyNYd-wv08!#{5hkIrN@9A8=|x!E;r@@pj{I z+;%=7O-#R;Kr(8K`$e-&2!`2b92cK6qyYuhl z2rd6`PIXQw^&(rK6n_&4`tyc&>D=r27Js(*x{IF7>)@Rc$49mJ#%pK+L!aMjW7T7J zZ0q1L!$GKfMC_d{tATCAfDAi@NE73ghNwG4gHV~j`tT;x$j5z)^)fwJ=yWNO zVD^XWJ$UrV63H1=!C%DdEpZtHz>`@{J8$>CS-rtb?8jCSbCWpU+nm@)(}-PmUdPuk0ZQw6AMcdu1DDh zv+tm>A2Tk5PPu--dYhY7TbHf$UYHV54c=)&Ur_O$G2T>zQ+^Zu<2bw_UYVcj{}ToH zar1}5O2dNbvr7)6Q>bZ%4gH=NvG4m;(;XtT*<_ydLi$0=Z2m{Pcc^FBhQSh#auB@L z?`9_paso+G&8IuU<|0$(nXR^o^T2(kVx2jD`Sq5dMC2d4aQ+A1_gNy{akIgBFpN&2 z)8oJlbbiE(DZeiweWx2Pl%P9IFWmm3rDK)UQ=7}=dT=|6J|&ou5xIxPVSl!UkzaD0 z&{sCEzJw|BM@g5Hrqx~3g-razQjNLhYS$$Y(cfgeH5c)wNUJS%R3_8yS zon$yRw)wcMbWyJCGkO%cSGOKAKLesvo4Btvx}b!Be?JB3j*n4CF3M2FhYt*ltoUMz ze9q5!R&Vnoy(pZhT+s5BeDBZfa8c2FhdDr%Uw*)^dQ@qgCLD5A=Mc@t+;;F7bl_{y z-CFUf-nK;ww4s=3vp88`Q)Xe~qgBxsHKRQ@@5vbEqWd&*Y) zEQ1_Zn@d~JKUqu4Bq9s)N&0Jyeiw_;zYk3IH^mBeeyzcme|TF|n_C#$PY$Dxh^ZrJ znGn3_J6c|J`pd}Mekk>`>BO}>&Ac+aDF<&-X>0!P3!h33!)nose)JzrXr!~$wAYu^ z`;x9wlcA245~+~IKSR*}-!|WEXQLhY&fzwDJCv#hA!C{k$DrkYxUkk?Lkb``S8s0 z%{xaih`k+}`25BH#QKGmYvX?>zfqoLs%z?SZTj|s-(9DvRa2AOW`4DG_#CQH1eeb2 zwoT|DY9g4!o)SjT>Psm6vpCu22e*Wu^RK7lHbf1E+st~SIEsQA?kDzYboK9p{wWh% z>_@3-Y9W)FW*L>rxz{w;1U7C=u2k7qjrn&mc$33D(PJW&s^m(s1?ipm8UA+*2$~yr zgdYobOBixs)ER=*rG-#5XQ(7iz|e9Cdi^(Xpw~1ALg%$$6>1s;DYPwrcYxx^Ulp>U zHME@%`#SKz7UR=@_ww&5S7Ha|q)SoMS=%8@{tNkcyI0Szgqa#BDjy;D8>=chdQIMm zM~EoOWB}`Igdn$)gYM>GagB{*mh2+056TKye#3htM2nCKL4VCXcm}eF0EdEo8cn&M z1&?~x6$}W1tg+P=3Qww5HKu^oB7w8~Ap-|eAk4UM3sHxJyNz3cX5#Er_a(1|6?_O{ zswXkE6G63#peAv2nn5-Ta;lxD`hWft4Tf%?7KyJMtmI)}s7=&A7V75>9fM3L0*;nC z3{#kfMVAnU4kgk&40IC{(x$e15V{VfY^aH9B_Hx}O-FrEiX3Vb=pt8g)+h*TqJ{C1 z>dRmEFK$|Q;Z@Jw+m`d4M~oYFTp$R^1oP9vu4_Xk9vc=S5ZFzeXld#2e&sKo@`%l| zPEW9GysIl2tX2KJp|*f{)i`HwhxyB1jUgIxJ<#LyOf~1+(#&V%$?PkcpBA8|7J9w5 zl8=6YP*TUYhM>;w8ciG!s_a>*Kk!mY=HRsLV!e=SG^*y0dn2#pQ>5)|wk23O5=^T* zDn~8ETY{>oM^7h%#L-4lhz^cf{?>dV_RWS-<3hHCC^X*IhkwCgM936n-VIw1cxY;F^w_%To9OF z@LJQG3-n+q*vnJj&KLN!eJooM1*M{G-kBDHGCXr8f$Z{wR*|s?GzLGDZbQc~<>2F! zvZN;dROlKEK{k+6oAFkrxGMsR`|&nzD}QJs2pVwZL^MOKPFUL(lWT3U(a5n=&3uO@ zGU7f|ml9EPm{q%K(D$ zsdTXmH~gEjA;_}^bYxI#@bwbo?obi%%KP_?5;k_Cjmg#A{Vh-avX z>ti8*z&MOg#k%^$&?OybXzP)+2giskz%}c~N!W!<5Q-3Y^t2e-&*D7xYZKxuwZtaE zzURj7&HsFYrU@YE%~JSd7I~+&>F1GP_$RB@e>WFS*EBZh`xgc3= zazD!>9g*6`>x8|{`Mz4SAt=Ka8mVv86*azCO-iy8A>2>=V+2obh z(_VMK_>Yux(Y?@A(ra<_;bN^y&O~=_qJQ&dE@9H|?6>kn40=VQ*_Q~pQZ@l(YCzcV zrNRJJHhI5P2ZBmwVD;2jc9k2}DhtPUqNjQ^#YGdbN$_T7D(FVJ9h!&&HnnlX)6xYe zco!bP;3_0|!ur`=_6SLsOus%!n&GP_aNANH>D4ow`k_G;D+z&OH!?o!^4bvQCc>KB z`?*c?*taBQ-UrL6*V4dc1p4Z}eUho8v@{VppasqpAH=(UKaIBv`4A%>*YEQxER8jfr?ci#8>&zNl=NG4&VNG zuqCAf9~?IdeWAk}7&pev-bxx&@|6rm1)ua%OP-)%)7oq?%5{6{DYPE^FhFnQkoSH| z|4w^8F%F|= ziib)s>a$S3{r^h8&boMpyuKB^DOCJKd8flF)z!rKAo?E`+G4jcf;=h&A*9sf!Ht#l z)%UJf2`|ZSw`VWqi^>azinlBHzMyk3Q+4L^ItuDHySg#+f{LwGs<}rdG2euX;2E~1 z>`EaM{6xKP>2sN>zUvNuPz6*nGEzpfsrX$HVQJi``?lSQU`2qnU=NmdfxD zc;)#46<3@8m@{zvfzpj8?H#^JoA7*H^NiiZ19SE<^c^(*NDLUgpD_3IL_=nWdwNU) ztNY_nAB!*07u$vR8)G%Jc_bP1p-t$xJFI;x+II3M8&k(gWDmbioYn;jw}HJ+CIZ+T zP7mr?G$vrAaTR@7IZtgszu>s$F46P758cP64G#w{xD$7q=%*vlxnJKc zjHLa<&&}b_;!~(!w#I_fkX4Wlk1-)TO)D>gtZLJtmwsMz89JvsjU(&)U(nJQK%7~q z`K&^d|0=HFt4dty!Bf;@qel4Czs-k?qv95)P{A9di+egUk*v8@UIEWgrtz$ACpd@d zh|?O-nC)M4XGpo^?n+ejZ;6k8ce|lA-xiiTxd-nF!ZdeVA6t{IPol^rdz@fuY7ej3 ztW(BT^1;d&`|9W_&zCG7 z?8;UzcoUm$bb5yL5Rp0Zrq8;{O=S8Qze$kgvHu7Nud;6bDh^gOeVC&fias)2-K(S- z<_rDxraJW5CcIxnS2ou7d}b={j}vt-=v-L5MLiJP(-#%o8{ZSffrMqvQ=^9wb}?X) z@pD~%2@Gu!{nco9Ra`9X&K(?h=ma`-Ns%ko8&#)i$OAiMfa9!9%6!vVcUQG{Xe|)x z1iv*~$hrOB>+b%$pm%6NEzSDW7gd+P36Fse+Q1*Tm@VwgABUEV!Q94S{cCY}As#cd zgd?c14B?B8*$4(6en*diW#Hc7zkmOGJy73}%=~u<0;mtk8xQ?=H2(L7;=d*Tw+H^m zdf*<1GxX#SC6RYHPX_+|_&>Jq|L*9&J@DTi_+ROP9Xwm`1PDPa(*~i>{J#H{I{Z%+ bYWZWp{)=T-|C~Rx!=;OsFT6WHBI*ACOYz;^ literal 0 HcmV?d00001 diff --git a/data/shader/tile.vert b/data/shader/tile.vert index 97099bce3d2..6288371e995 100644 --- a/data/shader/tile.vert +++ b/data/shader/tile.vert @@ -1,6 +1,6 @@ layout (location = 0) in vec2 inVertex; #ifdef TW_TILE_TEXTURED -layout (location = 1) in vec3 inVertexTexCoord; +layout (location = 1) in uvec4 inVertexTexCoord; #endif uniform mat4x2 gPos; @@ -14,6 +14,6 @@ void main() gl_Position = vec4(gPos * vec4(inVertex, 0.0, 1.0), 0.0, 1.0); #ifdef TW_TILE_TEXTURED - TexCoord = inVertexTexCoord; + TexCoord = vec3(inVertexTexCoord.xyz); #endif } diff --git a/data/shader/tile_border.vert b/data/shader/tile_border.vert index 8202a08e484..f8f71ebda51 100644 --- a/data/shader/tile_border.vert +++ b/data/shader/tile_border.vert @@ -1,6 +1,6 @@ layout (location = 0) in vec2 inVertex; #ifdef TW_TILE_TEXTURED -layout (location = 1) in vec3 inVertexTexCoord; +layout (location = 1) in uvec4 inVertexTexCoord; #endif uniform mat4x2 gPos; @@ -20,6 +20,9 @@ void main() #ifdef TW_TILE_TEXTURED // scale the texture coordinates too - TexCoord = vec3(inVertexTexCoord.xy * gScale, inVertexTexCoord.z); + vec2 TexScale = gScale; + if (float(inVertexTexCoord.w) > 0.0) + TexScale = gScale.yx; + TexCoord = vec3(vec2(inVertexTexCoord.xy) * TexScale, float(inVertexTexCoord.z)); #endif } diff --git a/data/shader/vulkan/tile.vert b/data/shader/vulkan/tile.vert index 5e78358cc16..7dd9d35fdc3 100644 --- a/data/shader/vulkan/tile.vert +++ b/data/shader/vulkan/tile.vert @@ -3,7 +3,7 @@ layout (location = 0) in vec2 inVertex; #ifdef TW_TILE_TEXTURED -layout (location = 1) in vec3 inVertexTexCoord; +layout (location = 1) in uvec4 inVertexTexCoord; #endif layout(push_constant) uniform SPosBO { @@ -19,6 +19,6 @@ void main() gl_Position = vec4(gPosBO.gPos * vec4(inVertex, 0.0, 1.0), 0.0, 1.0); #ifdef TW_TILE_TEXTURED - TexCoord = inVertexTexCoord; + TexCoord = vec3(inVertexTexCoord.xyz); #endif } diff --git a/data/shader/vulkan/tile_border.vert b/data/shader/vulkan/tile_border.vert index b7ae599815d..5463fdf39ed 100644 --- a/data/shader/vulkan/tile_border.vert +++ b/data/shader/vulkan/tile_border.vert @@ -3,7 +3,7 @@ layout (location = 0) in vec2 inVertex; #ifdef TW_TILE_TEXTURED -layout (location = 1) in vec3 inVertexTexCoord; +layout (location = 1) in uvec4 inVertexTexCoord; #endif layout(push_constant) uniform SPosBO { @@ -25,6 +25,9 @@ void main() #ifdef TW_TILE_TEXTURED // scale the texture coordinates too - TexCoord = vec3(inVertexTexCoord.xy * gPosBO.gScale, inVertexTexCoord.z); + vec2 TexScale = gPosBO.gScale; + if (inVertexTexCoord.w > 0) + TexScale = gPosBO.gScale.yx; + TexCoord = vec3(vec2(inVertexTexCoord.xy) * TexScale, float(inVertexTexCoord.z)); #endif } diff --git a/src/base/vmath.h b/src/base/vmath.h index 37205b108b9..6797e5db1d9 100644 --- a/src/base/vmath.h +++ b/src/base/vmath.h @@ -4,6 +4,7 @@ #define BASE_VMATH_H #include +#include #include "math.h" @@ -399,5 +400,6 @@ class vector4_base typedef vector4_base vec4; typedef vector4_base bvec4; typedef vector4_base ivec4; +typedef vector4_base ubvec4; #endif diff --git a/src/engine/client/backend/opengl/backend_opengl.cpp b/src/engine/client/backend/opengl/backend_opengl.cpp index 35e7335a5f9..2405bddc4a0 100644 --- a/src/engine/client/backend/opengl/backend_opengl.cpp +++ b/src/engine/client/backend/opengl/backend_opengl.cpp @@ -451,7 +451,7 @@ bool CCommandProcessorFragment_OpenGL::InitOpenGL(const SCommand_Init *pCommand) pCommand->m_pCapabilities->m_ContextPatch = 0; } - pCommand->m_pCapabilities->m_TileBuffering = pCommand->m_pCapabilities->m_2DArrayTextures || pCommand->m_pCapabilities->m_3DTextures; + pCommand->m_pCapabilities->m_TileBuffering = pCommand->m_pCapabilities->m_2DArrayTextures; pCommand->m_pCapabilities->m_QuadBuffering = false; pCommand->m_pCapabilities->m_TextBuffering = false; pCommand->m_pCapabilities->m_QuadContainerBuffering = false; @@ -464,8 +464,6 @@ bool CCommandProcessorFragment_OpenGL::InitOpenGL(const SCommand_Init *pCommand) pCommand->m_pCapabilities->m_2DArrayTextures = false; pCommand->m_pCapabilities->m_ShaderSupport = false; - if(MinorV >= 1) - pCommand->m_pCapabilities->m_ShaderSupport = true; int Texture3DSize = 0; glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &Texture3DSize); @@ -474,18 +472,6 @@ bool CCommandProcessorFragment_OpenGL::InitOpenGL(const SCommand_Init *pCommand) pCommand->m_pCapabilities->m_3DTextures = true; } - // check for array texture extension - if(pCommand->m_pCapabilities->m_ShaderSupport && GLEW_EXT_texture_array) - { - int TextureLayers = 0; - glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, &TextureLayers); - if(TextureLayers >= 256) - { - pCommand->m_pCapabilities->m_2DArrayTextures = true; - pCommand->m_pCapabilities->m_2DArrayTexturesAsExtension = true; - } - } - pCommand->m_pCapabilities->m_TileBuffering = false; pCommand->m_pCapabilities->m_QuadBuffering = false; pCommand->m_pCapabilities->m_TextBuffering = false; @@ -815,8 +801,8 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He glTexImage2D(GL_TEXTURE_2D, 0, GLStoreFormat, Width, Height, 0, GLFormat, GL_UNSIGNED_BYTE, pTexData); } - int Flag2DArrayTexture = (CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE | CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER); - int Flag3DTexture = (CCommandBuffer::TEXFLAG_TO_3D_TEXTURE | CCommandBuffer::TEXFLAG_TO_3D_TEXTURE_SINGLE_LAYER); + int Flag2DArrayTexture = CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE; + int Flag3DTexture = CCommandBuffer::TEXFLAG_TO_3D_TEXTURE; if((Flags & (Flag2DArrayTexture | Flag3DTexture)) != 0) { bool Is3DTexture = (Flags & Flag3DTexture) != 0; @@ -882,46 +868,32 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He uint8_t *p3DImageData = NULL; - bool IsSingleLayer = (Flags & (CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER | CCommandBuffer::TEXFLAG_TO_3D_TEXTURE_SINGLE_LAYER)) != 0; - - if(!IsSingleLayer) - p3DImageData = (uint8_t *)malloc((size_t)Width * Height * PixelSize); + p3DImageData = (uint8_t *)malloc((size_t)Width * Height * PixelSize); int Image3DWidth, Image3DHeight; int ConvertWidth = Width; int ConvertHeight = Height; - if(!IsSingleLayer) + if(ConvertWidth == 0 || (ConvertWidth % 16) != 0 || ConvertHeight == 0 || (ConvertHeight % 16) != 0) { - if(ConvertWidth == 0 || (ConvertWidth % 16) != 0 || ConvertHeight == 0 || (ConvertHeight % 16) != 0) - { - dbg_msg("gfx", "3D/2D array texture was resized"); - int NewWidth = maximum(HighestBit(ConvertWidth), 16); - int NewHeight = maximum(HighestBit(ConvertHeight), 16); - uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToPixelSize(GLFormat)); + dbg_msg("gfx", "3D/2D array texture was resized"); + int NewWidth = maximum(HighestBit(ConvertWidth), 16); + int NewHeight = maximum(HighestBit(ConvertHeight), 16); + uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToPixelSize(GLFormat)); - ConvertWidth = NewWidth; - ConvertHeight = NewHeight; + ConvertWidth = NewWidth; + ConvertHeight = NewHeight; - free(pTexData); - pTexData = pNewTexData; - } + free(pTexData); + pTexData = pNewTexData; } - if(IsSingleLayer || (Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DImageData, Image3DWidth, Image3DHeight))) + if((Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DImageData, Image3DWidth, Image3DHeight))) { - if(IsSingleLayer) - { - glTexImage3D(Target, 0, GLStoreFormat, ConvertWidth, ConvertHeight, 1, 0, GLFormat, GL_UNSIGNED_BYTE, pTexData); - } - else - { - glTexImage3D(Target, 0, GLStoreFormat, Image3DWidth, Image3DHeight, 256, 0, GLFormat, GL_UNSIGNED_BYTE, p3DImageData); - } + glTexImage3D(Target, 0, GLStoreFormat, Image3DWidth, Image3DHeight, 256, 0, GLFormat, GL_UNSIGNED_BYTE, p3DImageData); } - if(!IsSingleLayer) - free(p3DImageData); + free(p3DImageData); } } @@ -2084,7 +2056,7 @@ void CCommandProcessorFragment_OpenGL2::Cmd_RenderBorderTile(const CCommandBuffe if(IsTextured) { glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, false, BufferContainer.m_ContainerInfo.m_Stride, BufferContainer.m_ContainerInfo.m_vAttributes[1].m_pOffset); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, false, BufferContainer.m_ContainerInfo.m_Stride, BufferContainer.m_ContainerInfo.m_vAttributes[1].m_pOffset); } size_t RealDrawCount = pCommand->m_DrawNum * 4; @@ -2136,7 +2108,7 @@ void CCommandProcessorFragment_OpenGL2::Cmd_RenderTileLayer(const CCommandBuffer if(IsTextured) { glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, false, BufferContainer.m_ContainerInfo.m_Stride, BufferContainer.m_ContainerInfo.m_vAttributes[1].m_pOffset); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, false, BufferContainer.m_ContainerInfo.m_Stride, BufferContainer.m_ContainerInfo.m_vAttributes[1].m_pOffset); } for(int i = 0; i < pCommand->m_IndicesDrawNum; ++i) diff --git a/src/engine/client/backend/opengl/backend_opengl3.cpp b/src/engine/client/backend/opengl/backend_opengl3.cpp index a460c5723f0..315dd887d7d 100644 --- a/src/engine/client/backend/opengl/backend_opengl3.cpp +++ b/src/engine/client/backend/opengl/backend_opengl3.cpp @@ -600,7 +600,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int glGenerateMipmap(GL_TEXTURE_2D); } - if((Flags & (CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE | CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER)) != 0) + if((Flags & (CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE)) != 0) { glGenTextures(1, &m_vTextures[Slot].m_Tex2DArray); glBindTexture(GL_TEXTURE_2D_ARRAY, m_vTextures[Slot].m_Tex2DArray); @@ -620,47 +620,33 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int uint8_t *p3DImageData = NULL; - bool IsSingleLayer = (Flags & CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER) != 0; - - if(!IsSingleLayer) - p3DImageData = (uint8_t *)malloc((size_t)Width * Height * PixelSize); + p3DImageData = (uint8_t *)malloc((size_t)Width * Height * PixelSize); int Image3DWidth, Image3DHeight; int ConvertWidth = Width; int ConvertHeight = Height; - if(!IsSingleLayer) + if(ConvertWidth == 0 || (ConvertWidth % 16) != 0 || ConvertHeight == 0 || (ConvertHeight % 16) != 0) { - if(ConvertWidth == 0 || (ConvertWidth % 16) != 0 || ConvertHeight == 0 || (ConvertHeight % 16) != 0) - { - dbg_msg("gfx", "3D/2D array texture was resized"); - int NewWidth = maximum(HighestBit(ConvertWidth), 16); - int NewHeight = maximum(HighestBit(ConvertHeight), 16); - uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToPixelSize(GLFormat)); - - ConvertWidth = NewWidth; - ConvertHeight = NewHeight; - - free(pTexData); - pTexData = pNewTexData; - } + dbg_msg("gfx", "3D/2D array texture was resized"); + int NewWidth = maximum(HighestBit(ConvertWidth), 16); + int NewHeight = maximum(HighestBit(ConvertHeight), 16); + uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToPixelSize(GLFormat)); + + ConvertWidth = NewWidth; + ConvertHeight = NewHeight; + + free(pTexData); + pTexData = pNewTexData; } - if(IsSingleLayer || (Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DImageData, Image3DWidth, Image3DHeight))) + if((Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DImageData, Image3DWidth, Image3DHeight))) { - if(IsSingleLayer) - { - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GLStoreFormat, ConvertWidth, ConvertHeight, 1, 0, GLFormat, GL_UNSIGNED_BYTE, pTexData); - } - else - { - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GLStoreFormat, Image3DWidth, Image3DHeight, 256, 0, GLFormat, GL_UNSIGNED_BYTE, p3DImageData); - } + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GLStoreFormat, Image3DWidth, Image3DHeight, 256, 0, GLFormat, GL_UNSIGNED_BYTE, p3DImageData); glGenerateMipmap(GL_TEXTURE_2D_ARRAY); } - if(!IsSingleLayer) - free(p3DImageData); + free(p3DImageData); } } diff --git a/src/engine/client/backend/vulkan/backend_vulkan.cpp b/src/engine/client/backend/vulkan/backend_vulkan.cpp index f43ae43ff4e..d6b31aa5668 100644 --- a/src/engine/client/backend/vulkan/backend_vulkan.cpp +++ b/src/engine/client/backend/vulkan/backend_vulkan.cpp @@ -2593,8 +2593,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase } bool Requires2DTexture = (Flags & CCommandBuffer::TEXFLAG_NO_2D_TEXTURE) == 0; - bool Requires2DTextureArray = (Flags & (CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE | CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER)) != 0; - bool Is2DTextureSingleLayer = (Flags & CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER) != 0; + bool Requires2DTextureArray = (Flags & (CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE)) != 0; bool RequiresMipMaps = (Flags & CCommandBuffer::TEXFLAG_NOMIPMAPS) == 0; size_t MipMapLevelCount = 1; if(RequiresMipMaps) @@ -2638,44 +2637,33 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase int ConvertWidth = Width; int ConvertHeight = Height; - if(!Is2DTextureSingleLayer) + if(ConvertWidth == 0 || (ConvertWidth % 16) != 0 || ConvertHeight == 0 || (ConvertHeight % 16) != 0) { - if(ConvertWidth == 0 || (ConvertWidth % 16) != 0 || ConvertHeight == 0 || (ConvertHeight % 16) != 0) - { - dbg_msg("vulkan", "3D/2D array texture was resized"); - int NewWidth = maximum(HighestBit(ConvertWidth), 16); - int NewHeight = maximum(HighestBit(ConvertHeight), 16); - uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, PixelSize); + dbg_msg("vulkan", "3D/2D array texture was resized"); + int NewWidth = maximum(HighestBit(ConvertWidth), 16); + int NewHeight = maximum(HighestBit(ConvertHeight), 16); + uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, PixelSize); - ConvertWidth = NewWidth; - ConvertHeight = NewHeight; + ConvertWidth = NewWidth; + ConvertHeight = NewHeight; - free(pData); - pData = pNewTexData; - } + free(pData); + pData = pNewTexData; } void *p3DTexData = pData; bool Needs3DTexDel = false; - if(!Is2DTextureSingleLayer) - { - p3DTexData = malloc((size_t)PixelSize * ConvertWidth * ConvertHeight); - if(!Texture2DTo3D(pData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DTexData, Image3DWidth, Image3DHeight)) - { - free(p3DTexData); - p3DTexData = nullptr; - } - Needs3DTexDel = true; - } - else + p3DTexData = malloc((size_t)PixelSize * ConvertWidth * ConvertHeight); + if(!Texture2DTo3D(pData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DTexData, Image3DWidth, Image3DHeight)) { - Image3DWidth = ConvertWidth; - Image3DHeight = ConvertHeight; + free(p3DTexData); + p3DTexData = nullptr; } + Needs3DTexDel = true; if(p3DTexData != nullptr) { - const size_t ImageDepth2DArray = Is2DTextureSingleLayer ? 1 : ((size_t)16 * 16); + const size_t ImageDepth2DArray = (size_t)16 * 16; VkExtent3D ImgSize{(uint32_t)Image3DWidth, (uint32_t)Image3DHeight, 1}; if(RequiresMipMaps) { @@ -4898,7 +4886,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase std::array aAttributeDescriptions = {}; aAttributeDescriptions[0] = {0, 0, VK_FORMAT_R32G32_SFLOAT, 0}; if(HasSampler) - aAttributeDescriptions[1] = {1, 0, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 2}; + aAttributeDescriptions[1] = {1, 0, VK_FORMAT_R8G8B8A8_UINT, sizeof(float) * 2}; std::array aSetLayouts; aSetLayouts[0] = m_Standard3DTexturedDescriptorSetLayout; @@ -4913,7 +4901,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase aPushConstants[0] = {VK_SHADER_STAGE_VERTEX_BIT, 0, VertPushConstantSize}; aPushConstants[1] = {VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(SUniformTileGPosBorder) + sizeof(SUniformTileGVertColorAlign), FragPushConstantSize}; - return CreateGraphicsPipeline(pVertName, pFragName, PipeContainer, HasSampler ? (sizeof(float) * (2 + 3)) : (sizeof(float) * 2), aAttributeDescriptions, aSetLayouts, aPushConstants, TexMode, BlendMode, DynamicMode); + return CreateGraphicsPipeline(pVertName, pFragName, PipeContainer, HasSampler ? (sizeof(float) * 2 + sizeof(uint8_t) * 4) : (sizeof(float) * 2), aAttributeDescriptions, aSetLayouts, aPushConstants, TexMode, BlendMode, DynamicMode); } template @@ -7049,9 +7037,9 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase [[nodiscard]] bool Cmd_RenderTileLayer(const CCommandBuffer::SCommand_RenderTileLayer *pCommand, SRenderCommandExecuteBuffer &ExecBuffer) { - vec2 Dir{}; + vec2 Scale{}; vec2 Off{}; - return RenderTileLayer(ExecBuffer, pCommand->m_State, false, pCommand->m_Color, Dir, Off, (size_t)pCommand->m_IndicesDrawNum, pCommand->m_pIndicesOffsets, pCommand->m_pDrawCount); + return RenderTileLayer(ExecBuffer, pCommand->m_State, false, pCommand->m_Color, Scale, Off, (size_t)pCommand->m_IndicesDrawNum, pCommand->m_pIndicesOffsets, pCommand->m_pDrawCount); } void Cmd_RenderBorderTile_FillExecuteBuffer(SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand_RenderBorderTile *pCommand) diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index 9b7252b3e6c..d2c8eef6c55 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -454,10 +454,6 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(size_t Width, size_ Cmd.m_Flags |= CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE; if((Flags & IGraphics::TEXLOAD_TO_3D_TEXTURE) != 0) Cmd.m_Flags |= CCommandBuffer::TEXFLAG_TO_3D_TEXTURE; - if((Flags & IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER) != 0) - Cmd.m_Flags |= CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER; - if((Flags & IGraphics::TEXLOAD_TO_3D_TEXTURE_SINGLE_LAYER) != 0) - Cmd.m_Flags |= CCommandBuffer::TEXFLAG_TO_3D_TEXTURE_SINGLE_LAYER; if((Flags & IGraphics::TEXLOAD_NO_2D_TEXTURE) != 0) Cmd.m_Flags |= CCommandBuffer::TEXFLAG_NO_2D_TEXTURE; diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index ea838c22f2f..5f69b6ca8e2 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -147,9 +147,7 @@ class CCommandBuffer TEXFLAG_NOMIPMAPS = 1, TEXFLAG_TO_3D_TEXTURE = (1 << 3), TEXFLAG_TO_2D_ARRAY_TEXTURE = (1 << 4), - TEXFLAG_TO_3D_TEXTURE_SINGLE_LAYER = (1 << 5), - TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER = (1 << 6), - TEXFLAG_NO_2D_TEXTURE = (1 << 7), + TEXFLAG_NO_2D_TEXTURE = (1 << 5), }; enum diff --git a/src/engine/graphics.h b/src/engine/graphics.h index e0251d4dad4..5e1639ba941 100644 --- a/src/engine/graphics.h +++ b/src/engine/graphics.h @@ -57,10 +57,10 @@ struct SGraphicTile struct SGraphicTileTexureCoords { - vec3 m_TexCoordTopLeft; - vec3 m_TexCoordTopRight; - vec3 m_TexCoordBottomRight; - vec3 m_TexCoordBottomLeft; + ubvec4 m_TexCoordTopLeft; + ubvec4 m_TexCoordTopRight; + ubvec4 m_TexCoordBottomRight; + ubvec4 m_TexCoordBottomLeft; }; class CImageInfo @@ -246,9 +246,7 @@ class IGraphics : public IInterface TEXLOAD_NO_COMPRESSION = 1 << 2, TEXLOAD_TO_3D_TEXTURE = (1 << 3), TEXLOAD_TO_2D_ARRAY_TEXTURE = (1 << 4), - TEXLOAD_TO_3D_TEXTURE_SINGLE_LAYER = (1 << 5), - TEXLOAD_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER = (1 << 6), - TEXLOAD_NO_2D_TEXTURE = (1 << 7), + TEXLOAD_NO_2D_TEXTURE = (1 << 5), }; class CTextureHandle diff --git a/src/game/client/components/mapimages.cpp b/src/game/client/components/mapimages.cpp index f5e0e475bea..54727939b7d 100644 --- a/src/game/client/components/mapimages.cpp +++ b/src/game/client/components/mapimages.cpp @@ -356,8 +356,8 @@ IGraphics::CTextureHandle CMapImages::GetSpeedupArrow() { if(!m_SpeedupArrowIsLoaded) { - int TextureLoadFlag = (Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER : IGraphics::TEXLOAD_TO_3D_TEXTURE_SINGLE_LAYER) | IGraphics::TEXLOAD_NO_2D_TEXTURE; - m_SpeedupArrowTexture = Graphics()->LoadTexture(g_pData->m_aImages[IMAGE_SPEEDUP_ARROW].m_pFilename, IStorage::TYPE_ALL, TextureLoadFlag); + int TextureLoadFlag = (Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE) | IGraphics::TEXLOAD_NO_2D_TEXTURE; + m_SpeedupArrowTexture = Graphics()->LoadTexture("editor/speed_arrow_array.png", IStorage::TYPE_ALL, TextureLoadFlag); m_SpeedupArrowIsLoaded = true; } diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 7c72c7134b5..ad49f9eb292 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -1,6 +1,5 @@ /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ -#include #include #include #include @@ -144,7 +143,7 @@ void CMapLayers::EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Channels } } -void FillTmpTile(SGraphicTile *pTmpTile, SGraphicTileTexureCoords *pTmpTex, bool As3DTextureCoord, unsigned char Flags, unsigned char Index, int x, int y, const ivec2 &Offset, int Scale, CMapItemGroup *pGroup) +void FillTmpTile(SGraphicTile *pTmpTile, SGraphicTileTexureCoords *pTmpTex, unsigned char Flags, unsigned char Index, int x, int y, const ivec2 &Offset, int Scale, CMapItemGroup *pGroup) { if(pTmpTex) { @@ -196,20 +195,16 @@ void FillTmpTile(SGraphicTile *pTmpTile, SGraphicTileTexureCoords *pTmpTex, bool pTmpTex->m_TexCoordBottomRight.x = x2; pTmpTex->m_TexCoordBottomRight.y = y2; - if(As3DTextureCoord) - { - pTmpTex->m_TexCoordTopLeft.z = ((float)Index + 0.5f) / 256.f; - pTmpTex->m_TexCoordBottomLeft.z = ((float)Index + 0.5f) / 256.f; - pTmpTex->m_TexCoordTopRight.z = ((float)Index + 0.5f) / 256.f; - pTmpTex->m_TexCoordBottomRight.z = ((float)Index + 0.5f) / 256.f; - } - else - { - pTmpTex->m_TexCoordTopLeft.z = Index; - pTmpTex->m_TexCoordBottomLeft.z = Index; - pTmpTex->m_TexCoordTopRight.z = Index; - pTmpTex->m_TexCoordBottomRight.z = Index; - } + pTmpTex->m_TexCoordTopLeft.z = Index; + pTmpTex->m_TexCoordBottomLeft.z = Index; + pTmpTex->m_TexCoordTopRight.z = Index; + pTmpTex->m_TexCoordBottomRight.z = Index; + + bool HasRotation = (Flags & TILEFLAG_ROTATE) != 0; + pTmpTex->m_TexCoordTopLeft.w = HasRotation; + pTmpTex->m_TexCoordBottomLeft.w = HasRotation; + pTmpTex->m_TexCoordTopRight.w = HasRotation; + pTmpTex->m_TexCoordBottomRight.w = HasRotation; } pTmpTile->m_TopLeft.x = x * Scale + Offset.x; @@ -222,10 +217,10 @@ void FillTmpTile(SGraphicTile *pTmpTile, SGraphicTileTexureCoords *pTmpTex, bool pTmpTile->m_BottomRight.y = y * Scale + Scale + Offset.y; } -void FillTmpTileSpeedup(SGraphicTile *pTmpTile, SGraphicTileTexureCoords *pTmpTex, bool As3DTextureCoord, unsigned char Flags, unsigned char Index, int x, int y, const ivec2 &Offset, int Scale, CMapItemGroup *pGroup, short AngleRotate) +void FillTmpTileSpeedup(SGraphicTile *pTmpTile, SGraphicTileTexureCoords *pTmpTex, unsigned char Flags, unsigned char Index, int x, int y, const ivec2 &Offset, int Scale, CMapItemGroup *pGroup, short AngleRotate) { int Angle = AngleRotate % 360; - FillTmpTile(pTmpTile, pTmpTex, As3DTextureCoord, Angle >= 270 ? Angle : (Angle >= 180 ? ROTATION_180 : (Angle >= 90 ? ROTATION_90 : 0)), AngleRotate % 90, x, y, Offset, Scale, pGroup); + FillTmpTile(pTmpTile, pTmpTex, Angle >= 270 ? ROTATION_270 : (Angle >= 180 ? ROTATION_180 : (Angle >= 90 ? ROTATION_90 : 0)), AngleRotate % 90, x, y, Offset, Scale, pGroup); } bool CMapLayers::STileLayerVisuals::Init(unsigned int Width, unsigned int Height) @@ -255,7 +250,7 @@ CMapLayers::STileLayerVisuals::~STileLayerVisuals() m_pTilesOfLayer = NULL; } -bool AddTile(std::vector &vTmpTiles, std::vector &vTmpTileTexCoords, bool As3DTextureCoord, unsigned char Index, unsigned char Flags, int x, int y, CMapItemGroup *pGroup, bool DoTextureCoords, bool FillSpeedup = false, int AngleRotate = -1, const ivec2 &Offset = ivec2{0, 0}, int Scale = 32) +bool AddTile(std::vector &vTmpTiles, std::vector &vTmpTileTexCoords, unsigned char Index, unsigned char Flags, int x, int y, CMapItemGroup *pGroup, bool DoTextureCoords, bool FillSpeedup = false, int AngleRotate = -1, const ivec2 &Offset = ivec2{0, 0}, int Scale = 32) { if(Index) { @@ -269,9 +264,9 @@ bool AddTile(std::vector &vTmpTiles, std::vector vtmpQuads; std::vector vtmpQuadsTextured; - bool As3DTextureCoords = !Graphics()->Uses2DTextureArrays(); - for(int g = 0; g < m_pLayers->NumGroups(); g++) { CMapItemGroup *pGroup = m_pLayers->GetGroup(g); @@ -626,7 +619,7 @@ void CMapLayers::OnMapLoad() if(IsSpeedupLayer && CurOverlay == 0) AddAsSpeedup = true; - if(AddTile(vtmpTiles, vtmpTileTexCoords, As3DTextureCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate)) + if(AddTile(vtmpTiles, vtmpTileTexCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate)) Visuals.m_pTilesOfLayer[y * pTMap->m_Width + x].Draw(true); //do the border tiles @@ -635,17 +628,17 @@ void CMapLayers::OnMapLoad() if(y == 0) { Visuals.m_BorderTopLeft.SetIndexBufferByteOffset((offset_ptr32)(vtmpBorderCorners.size())); - if(AddTile(vtmpBorderCorners, vtmpBorderCornersTexCoords, As3DTextureCoords, Index, Flags, 0, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{-32, -32})) + if(AddTile(vtmpBorderCorners, vtmpBorderCornersTexCoords, Index, Flags, 0, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{-32, -32})) Visuals.m_BorderTopLeft.Draw(true); } else if(y == pTMap->m_Height - 1) { Visuals.m_BorderBottomLeft.SetIndexBufferByteOffset((offset_ptr32)(vtmpBorderCorners.size())); - if(AddTile(vtmpBorderCorners, vtmpBorderCornersTexCoords, As3DTextureCoords, Index, Flags, 0, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{-32, 0})) + if(AddTile(vtmpBorderCorners, vtmpBorderCornersTexCoords, Index, Flags, 0, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{-32, 0})) Visuals.m_BorderBottomLeft.Draw(true); } Visuals.m_vBorderLeft[y].SetIndexBufferByteOffset((offset_ptr32)(vtmpBorderLeftTiles.size())); - if(AddTile(vtmpBorderLeftTiles, vtmpBorderLeftTilesTexCoords, As3DTextureCoords, Index, Flags, 0, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{-32, 0})) + if(AddTile(vtmpBorderLeftTiles, vtmpBorderLeftTilesTexCoords, Index, Flags, 0, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{-32, 0})) Visuals.m_vBorderLeft[y].Draw(true); } else if(x == pTMap->m_Width - 1) @@ -653,29 +646,29 @@ void CMapLayers::OnMapLoad() if(y == 0) { Visuals.m_BorderTopRight.SetIndexBufferByteOffset((offset_ptr32)(vtmpBorderCorners.size())); - if(AddTile(vtmpBorderCorners, vtmpBorderCornersTexCoords, As3DTextureCoords, Index, Flags, 0, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{0, -32})) + if(AddTile(vtmpBorderCorners, vtmpBorderCornersTexCoords, Index, Flags, 0, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{0, -32})) Visuals.m_BorderTopRight.Draw(true); } else if(y == pTMap->m_Height - 1) { Visuals.m_BorderBottomRight.SetIndexBufferByteOffset((offset_ptr32)(vtmpBorderCorners.size())); - if(AddTile(vtmpBorderCorners, vtmpBorderCornersTexCoords, As3DTextureCoords, Index, Flags, 0, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{0, 0})) + if(AddTile(vtmpBorderCorners, vtmpBorderCornersTexCoords, Index, Flags, 0, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{0, 0})) Visuals.m_BorderBottomRight.Draw(true); } Visuals.m_vBorderRight[y].SetIndexBufferByteOffset((offset_ptr32)(vtmpBorderRightTiles.size())); - if(AddTile(vtmpBorderRightTiles, vtmpBorderRightTilesTexCoords, As3DTextureCoords, Index, Flags, 0, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{0, 0})) + if(AddTile(vtmpBorderRightTiles, vtmpBorderRightTilesTexCoords, Index, Flags, 0, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{0, 0})) Visuals.m_vBorderRight[y].Draw(true); } if(y == 0) { Visuals.m_vBorderTop[x].SetIndexBufferByteOffset((offset_ptr32)(vtmpBorderTopTiles.size())); - if(AddTile(vtmpBorderTopTiles, vtmpBorderTopTilesTexCoords, As3DTextureCoords, Index, Flags, x, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{0, -32})) + if(AddTile(vtmpBorderTopTiles, vtmpBorderTopTilesTexCoords, Index, Flags, x, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{0, -32})) Visuals.m_vBorderTop[x].Draw(true); } else if(y == pTMap->m_Height - 1) { Visuals.m_vBorderBottom[x].SetIndexBufferByteOffset((offset_ptr32)(vtmpBorderBottomTiles.size())); - if(AddTile(vtmpBorderBottomTiles, vtmpBorderBottomTilesTexCoords, As3DTextureCoords, Index, Flags, x, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{0, 0})) + if(AddTile(vtmpBorderBottomTiles, vtmpBorderBottomTilesTexCoords, Index, Flags, x, 0, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate, ivec2{0, 0})) Visuals.m_vBorderBottom[x].Draw(true); } } @@ -685,7 +678,7 @@ void CMapLayers::OnMapLoad() if(IsGameLayer) { Visuals.m_BorderKillTile.SetIndexBufferByteOffset((offset_ptr32)(vtmpTiles.size())); - if(AddTile(vtmpTiles, vtmpTileTexCoords, As3DTextureCoords, TILE_DEATH, 0, 0, 0, pGroup, DoTextureCoords)) + if(AddTile(vtmpTiles, vtmpTileTexCoords, TILE_DEATH, 0, 0, 0, pGroup, DoTextureCoords)) Visuals.m_BorderKillTile.Draw(true); } @@ -754,10 +747,10 @@ void CMapLayers::OnMapLoad() { char *pUploadData = (char *)malloc(sizeof(char) * UploadDataSize); - mem_copy_special(pUploadData, pTmpTiles, sizeof(vec2), vtmpTiles.size() * 4, (DoTextureCoords ? sizeof(vec3) : 0)); + mem_copy_special(pUploadData, pTmpTiles, sizeof(vec2), vtmpTiles.size() * 4, (DoTextureCoords ? sizeof(ubvec4) : 0)); if(DoTextureCoords) { - mem_copy_special(pUploadData + sizeof(vec2), pTmpTileTexCoords, sizeof(vec3), vtmpTiles.size() * 4, sizeof(vec2)); + mem_copy_special(pUploadData + sizeof(vec2), pTmpTileTexCoords, sizeof(ubvec4), vtmpTiles.size() * 4, sizeof(vec2)); } // first create the buffer object @@ -765,7 +758,7 @@ void CMapLayers::OnMapLoad() // then create the buffer container SBufferContainerInfo ContainerInfo; - ContainerInfo.m_Stride = (DoTextureCoords ? (sizeof(float) * 2 + sizeof(vec3)) : 0); + ContainerInfo.m_Stride = (DoTextureCoords ? (sizeof(float) * 2 + sizeof(ubvec4)) : 0); ContainerInfo.m_VertBufferBindingIndex = BufferObjectIndex; ContainerInfo.m_vAttributes.emplace_back(); SBufferContainerInfo::SAttribute *pAttr = &ContainerInfo.m_vAttributes.back(); @@ -778,11 +771,11 @@ void CMapLayers::OnMapLoad() { ContainerInfo.m_vAttributes.emplace_back(); pAttr = &ContainerInfo.m_vAttributes.back(); - pAttr->m_DataTypeCount = 3; - pAttr->m_Type = GRAPHICS_TYPE_FLOAT; + pAttr->m_DataTypeCount = 4; + pAttr->m_Type = GRAPHICS_TYPE_UNSIGNED_BYTE; pAttr->m_Normalized = false; pAttr->m_pOffset = (void *)(sizeof(vec2)); - pAttr->m_FuncType = 0; + pAttr->m_FuncType = 1; } Visuals.m_BufferContainerIndex = Graphics()->CreateBufferContainer(&ContainerInfo); diff --git a/src/game/client/render_map.cpp b/src/game/client/render_map.cpp index 541f6435f62..5e858292d4c 100644 --- a/src/game/client/render_map.cpp +++ b/src/game/client/render_map.cpp @@ -459,7 +459,10 @@ void CRenderTools::RenderTileRectangle(int RectX, int RectY, int RectW, int Rect pfnEval(ColorEnvOffset, ColorEnv, Channels, pUser); } - Graphics()->QuadsBegin(); + if(Graphics()->HasTextureArraysSupport()) + Graphics()->QuadsTex3DBegin(); + else + Graphics()->QuadsBegin(); Graphics()->SetColor(Color.r * Channels.r, Color.g * Channels.g, Color.b * Channels.b, Color.a * Channels.a); int StartY = (int)(ScreenY0 / Scale) - 1; @@ -501,15 +504,39 @@ void CRenderTools::RenderTileRectangle(int RectX, int RectY, int RectW, int Rect float x3 = Nudge + Px0 / TexSize + Frac; float y3 = Nudge + Py1 / TexSize - Frac; - Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3); - IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); - Graphics()->QuadsDrawTL(&QuadItem, 1); + if(Graphics()->HasTextureArraysSupport()) + { + x0 = 0; + y0 = 0; + x1 = x0 + 1; + y1 = y0; + x2 = x0 + 1; + y2 = y0 + 1; + x3 = x0; + y3 = y0 + 1; + } + + if(Graphics()->HasTextureArraysSupport()) + { + Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3, Index); + IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); + Graphics()->QuadsTex3DDrawTL(&QuadItem, 1); + } + else + { + Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3); + IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); + Graphics()->QuadsDrawTL(&QuadItem, 1); + } } } } } - Graphics()->QuadsEnd(); + if(Graphics()->HasTextureArraysSupport()) + Graphics()->QuadsTex3DEnd(); + else + Graphics()->QuadsEnd(); Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } @@ -918,7 +945,10 @@ void CRenderTools::RenderTelemap(CTeleTile *pTele, int w, int h, float Scale, Co float FinalTileSize = Scale / (ScreenX1 - ScreenX0) * Graphics()->ScreenWidth(); float FinalTilesetScale = FinalTileSize / TilePixelSize; - Graphics()->QuadsBegin(); + if(Graphics()->HasTextureArraysSupport()) + Graphics()->QuadsTex3DBegin(); + else + Graphics()->QuadsBegin(); Graphics()->SetColor(Color); int StartY = (int)(ScreenY0 / Scale) - 1; @@ -987,14 +1017,38 @@ void CRenderTools::RenderTelemap(CTeleTile *pTele, int w, int h, float Scale, Co float x3 = Nudge + Px0 / TexSize + Frac; float y3 = Nudge + Py1 / TexSize - Frac; - Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3); - IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); - Graphics()->QuadsDrawTL(&QuadItem, 1); + if(Graphics()->HasTextureArraysSupport()) + { + x0 = 0; + y0 = 0; + x1 = x0 + 1; + y1 = y0; + x2 = x0 + 1; + y2 = y0 + 1; + x3 = x0; + y3 = y0 + 1; + } + + if(Graphics()->HasTextureArraysSupport()) + { + Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3, Index); + IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); + Graphics()->QuadsTex3DDrawTL(&QuadItem, 1); + } + else + { + Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3); + IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); + Graphics()->QuadsDrawTL(&QuadItem, 1); + } } } } - Graphics()->QuadsEnd(); + if(Graphics()->HasTextureArraysSupport()) + Graphics()->QuadsTex3DEnd(); + else + Graphics()->QuadsEnd(); Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } @@ -1010,7 +1064,10 @@ void CRenderTools::RenderSpeedupmap(CSpeedupTile *pSpeedupTile, int w, int h, fl float FinalTileSize = Scale / (ScreenX1 - ScreenX0) * Graphics()->ScreenWidth(); float FinalTilesetScale = FinalTileSize / TilePixelSize; - Graphics()->QuadsBegin(); + if(Graphics()->HasTextureArraysSupport()) + Graphics()->QuadsTex3DBegin(); + else + Graphics()->QuadsBegin(); Graphics()->SetColor(Color); int StartY = (int)(ScreenY0 / Scale) - 1; @@ -1079,14 +1136,38 @@ void CRenderTools::RenderSpeedupmap(CSpeedupTile *pSpeedupTile, int w, int h, fl float x3 = Nudge + Px0 / TexSize + Frac; float y3 = Nudge + Py1 / TexSize - Frac; - Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3); - IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); - Graphics()->QuadsDrawTL(&QuadItem, 1); + if(Graphics()->HasTextureArraysSupport()) + { + x0 = 0; + y0 = 0; + x1 = x0 + 1; + y1 = y0; + x2 = x0 + 1; + y2 = y0 + 1; + x3 = x0; + y3 = y0 + 1; + } + + if(Graphics()->HasTextureArraysSupport()) + { + Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3, Index); + IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); + Graphics()->QuadsTex3DDrawTL(&QuadItem, 1); + } + else + { + Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3); + IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); + Graphics()->QuadsDrawTL(&QuadItem, 1); + } } } } - Graphics()->QuadsEnd(); + if(Graphics()->HasTextureArraysSupport()) + Graphics()->QuadsTex3DEnd(); + else + Graphics()->QuadsEnd(); Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } @@ -1102,7 +1183,10 @@ void CRenderTools::RenderSwitchmap(CSwitchTile *pSwitchTile, int w, int h, float float FinalTileSize = Scale / (ScreenX1 - ScreenX0) * Graphics()->ScreenWidth(); float FinalTilesetScale = FinalTileSize / TilePixelSize; - Graphics()->QuadsBegin(); + if(Graphics()->HasTextureArraysSupport()) + Graphics()->QuadsTex3DBegin(); + else + Graphics()->QuadsBegin(); Graphics()->SetColor(Color); int StartY = (int)(ScreenY0 / Scale) - 1; @@ -1184,6 +1268,18 @@ void CRenderTools::RenderSwitchmap(CSwitchTile *pSwitchTile, int w, int h, float float x3 = Nudge + Px0 / TexSize + Frac; float y3 = Nudge + Py1 / TexSize - Frac; + if(Graphics()->HasTextureArraysSupport()) + { + x0 = 0; + y0 = 0; + x1 = x0 + 1; + y1 = y0; + x2 = x0 + 1; + y2 = y0 + 1; + x3 = x0; + y3 = y0 + 1; + } + if(Flags & TILEFLAG_XFLIP) { x0 = x2; @@ -1214,14 +1310,26 @@ void CRenderTools::RenderSwitchmap(CSwitchTile *pSwitchTile, int w, int h, float y1 = Tmp; } - Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3); - IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); - Graphics()->QuadsDrawTL(&QuadItem, 1); + if(Graphics()->HasTextureArraysSupport()) + { + Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3, Index); + IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); + Graphics()->QuadsTex3DDrawTL(&QuadItem, 1); + } + else + { + Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3); + IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); + Graphics()->QuadsDrawTL(&QuadItem, 1); + } } } } - Graphics()->QuadsEnd(); + if(Graphics()->HasTextureArraysSupport()) + Graphics()->QuadsTex3DEnd(); + else + Graphics()->QuadsEnd(); Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } @@ -1235,7 +1343,10 @@ void CRenderTools::RenderTunemap(CTuneTile *pTune, int w, int h, float Scale, Co float FinalTileSize = Scale / (ScreenX1 - ScreenX0) * Graphics()->ScreenWidth(); float FinalTilesetScale = FinalTileSize / TilePixelSize; - Graphics()->QuadsBegin(); + if(Graphics()->HasTextureArraysSupport()) + Graphics()->QuadsTex3DBegin(); + else + Graphics()->QuadsBegin(); Graphics()->SetColor(Color); int StartY = (int)(ScreenY0 / Scale) - 1; @@ -1304,13 +1415,37 @@ void CRenderTools::RenderTunemap(CTuneTile *pTune, int w, int h, float Scale, Co float x3 = Nudge + Px0 / TexSize + Frac; float y3 = Nudge + Py1 / TexSize - Frac; - Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3); - IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); - Graphics()->QuadsDrawTL(&QuadItem, 1); + if(Graphics()->HasTextureArraysSupport()) + { + x0 = 0; + y0 = 0; + x1 = x0 + 1; + y1 = y0; + x2 = x0 + 1; + y2 = y0 + 1; + x3 = x0; + y3 = y0 + 1; + } + + if(Graphics()->HasTextureArraysSupport()) + { + Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3, Index); + IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); + Graphics()->QuadsTex3DDrawTL(&QuadItem, 1); + } + else + { + Graphics()->QuadsSetSubsetFree(x0, y0, x1, y1, x2, y2, x3, y3); + IGraphics::CQuadItem QuadItem(x * Scale, y * Scale, Scale, Scale); + Graphics()->QuadsDrawTL(&QuadItem, 1); + } } } } - Graphics()->QuadsEnd(); + if(Graphics()->HasTextureArraysSupport()) + Graphics()->QuadsTex3DEnd(); + else + Graphics()->QuadsEnd(); Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); }