From 9b618b0e3fbfeb4babceb5bc93352d23d168298b Mon Sep 17 00:00:00 2001
From: zomseffen <steffen@tom.bi>
Date: Mon, 20 Jan 2025 10:18:28 +0100
Subject: [PATCH] shader refactoring and float pos for lights

---
 shaders/compiled/frag_rt_quad.spv | Bin 27676 -> 28684 bytes
 shaders/rt_quad.frag              | 156 +++++++++++++++++-------------
 src/scene/light.rs                |   6 +-
 3 files changed, 92 insertions(+), 70 deletions(-)

diff --git a/shaders/compiled/frag_rt_quad.spv b/shaders/compiled/frag_rt_quad.spv
index 70c2c6ae56ac85eb260c6364ec334c1f470bc6fe..c161614af1f3c7a74aac100e1e0b7072db833a5c 100644
GIT binary patch
literal 28684
zcmaK!2bf(|*@Z7KlZ4)z)X<ys9(pmLC;<e72*V_qNd_h}VKNCxM1)WUK_DniBsA&0
z3l>m71O!B+C?YBfB2A^K;Qzk&-j(b*8UOn{``K%)uk3H{v-i2@T!t(#|C&Q<wfSlb
z*A}ha(^9K{maNT>QbQY3??>))z&;yK?jN`DmRoJA!(z1s>VEnxUR$VUm~CQvSC59F
zkOgTA(JrCgMq7dyx*CIl7GQ*0?LiW>5I=ICwvqepJ93{r+s00s)Hb<)dUr=#cUMnG
z+qka2j<Nk+Q#<q<R`_-GjP0H>u5@U{!~ChCm5~;PPwAP|KK7`#vAx~Bed|rxYy?uR
zmGKv%pW5CHUbMC}cyjy1NetW5(KUX;nBKm&&c5D>ZIj1#P(@cyXRo1Cr))l=o}ra>
zS;F|<?kN*HD7d|^A4;y)+LH8r?UVaE`r0P-PHv2~6k2E9zDR9F`sP^mn*P6m9A`QF
z2ODR3^y)Y(pf$!BR$C1`zN4RY96zDoQo8!PdV3lxV4bUCZ`ite#&t|X8CqLoK+N1F
z(|`Cp{w=k2(Z1N%KDMi8Je9WAIZ~~oXIy>qLs0c`pQzO{f}^_!)Eo1gtGm0@I~%Fz
z_<MbudVg=<T>sXlK6d)pZnnytT84lpv`=oE(A7_M3)MD(_fv02TVMP1`W5ZmV#HKh
z=Vo5mIoEc5{N`QrA+-(A>ld2|H?D5uns12S+^W4E0M~0H`ibq+oI|}<wNEF$tx>7k
z#!bJ}Zk^kp&AE1tHRn=T?9|RJ*~RXSE%6(y&aE=efI5fPwnp#m>uTm}YivU_&(3z{
zYVY2RuFiLA@Xf<_Z}2U`_iAuUz<+4%0Q&Ym*0pV1$K<hna}I@dehJ$F9;LlGNxMzy
z?Cj{PUn6xt9x#pyd0K0S($771joe3|H4aN-gd8}>9fz&IcT!`C+9r3+=xCdQRIh2m
zytb*ad7Z}e_V;tj8>yS2=JYVnYnxinIRjgFM`!=QsK$854`OpbbDl!a(sLFE3|F_E
zF_?`&<Icgxy{Kofxbp|IHRCS9HfGM9Z|=gF^NK-isq<QFuIHQ^VX-bZ4{CE=hSlyg
zXJb99p>_Lx|I1#lcUbKK?Dch>C)#xwR(oV{yJgqyPtZ5kcisfXKl4BAjd>5Ny@0*3
z&V$Fl{6Fl8e-(Ruz2^<D*Z0QY_GbM<YVTqnxQ`px|2^ZX`xMP{^$~q#FQN~veT-h+
zYe;q5eB6wy`>A2$4vwv|XX@iDh+dvQ?!on3%cIY;SL)*otF2_NLH0xHSPlEU*Sk^U
zn%D-pmh~~$#Wu)ws@pbnO!xeNYhcdS+9ue_yNAyJ`=d?a#v?uyJhhHnYGc&vM@Cyq
zty5dUkCeA}Pw~6P^*#YU_`Ppv?Nn^#+LiaN)3FV_=5y~|XU%JC?v<gnS=i>;6NFmJ
z1%uie_pVE@RrX7LK;teS#Mao`Lu*%KtL`TQjk{qm8-dzx#a7*GiMwksTQlxHY?XaD
zr_LV_Vr$gdT6+ka>*+14vCmp-kLusphjrP#@B~_Y9h#16Pop*F*bvp8MQhYQS9`&H
z?y(~FCA8|^`WP*HtCa_x?5#z?<=$FSTd}v6mCxB*Ew%OGliK^*C)W2`OYK1T+-HR$
zwS)C<Jcl+O<m!GyYKP3#dH8Fa)>w}rwZjMM)1!|asQWd?3bfR^(5E#YcH}*E-ZQ1U
zyJ7ExPcQ6K>wK<#27E?gKd#PWZ>`OQ&wWZVXKU@GdX79fHMCReaRaqk^;n+P$MHZ>
zueY@}yB<4GyP+OiYC~)Hp!IZgjGN5OVp{VtIdgs;TVKcIDcw8>SkGH<o+0Nvk9xm&
z8_fp|@jKw0l~2H3Jv{zT_RXcYXYO+%&(}QI{x92}|I;?4HX2*K%G}rL<F?e=(96Bi
zUg2W~@FBHMc=PF_{<f3(9y!3TrPf{H69@1iwb^i=Z5!_oJyRNcv$b{wdR4m;tvP1X
zZ%FO>W_%aR)b1kH@4KzFThQld^*OfI?wyk}?<qrS56#i$K6Se{A4Z?M9<8;<=J?es
z;99lR9v|S-QhO3U_gc5qp03!Rsqkkj{J9E$zQSJ|z*}pd!0T(*(KEiE2UKgCj~AP6
z-WeO$gYRK@W6k<{r;MM_(=mB6enaZ-)t!Cq;}5Ez_XFy$o$9`8tM6Zb?;O>9mgdb`
zz4;F1I19t)u1`yC(F$LD03TXg3O@Mz!qD1qY|Z!23GLmTJnwf*;xg9jTw|_nTo+$>
zJ!3oS`kHg~Nxd9|hJR~qL-c`rg!d=3DQ&%-os&D7>(W}=25o9Z+YN16MLP^_dPO@H
zZN>ntrFK4AMsOYdt-|@Tg7vrMoR7=U%XPb=!mk{_TkF4f^iJvD-QOI{F_N`EnBMnM
zTx)x=8hQ6w6Yggu_YpO=N8R7|pfzZIjF%6maeJxz`Wwq)O`F*FdA@S$HupnpVr_mL
z!#xq3SX;(){_@5cE%kXMc4<`g;dtvWUY5F?)9N%otHb?$$ELnKd{`5cn%I`wg7j+o
zXkV0GU-KDnZQ9g_V_BSDyIO4O%fgc<`f^mZ68h>ibFWM<w_e9yg<j2Ej<r@3tI5}H
za$}aEqIKw3rQ&tz^~qeUM<08AhU2pyy?*94uPyo1tjCvY<6H~J^W|Ebx^vosKJ^)|
z-8CLTzdCI`+J;TO19*jk?*g{I*!Kkc8<pHT52V?z!fIqMt_pU~$*t!Qdar}ph$eU6
zsU`1dupj-uOs~zn8D|VQb*UdoOWpEGwB(cfz3KHy{IOuyCwwNjwcuxhU9;F{firLO
zT}X3}#eON+-}=I@0{gpQ`1RmL3Vtity%+o4VE0$}55Vrp@SlLob$%4SWMO|2yi~!T
z1utFj-+-4X_$y%dcJluPyj;QG1TSCk&0SnRE3;~&z^;MU+Uv6)+_h3SpL=f)7r*wk
z-L+2uYhQ;Jdw1R5;O@I~;Dpbyf45=Zc>}JRareT_^%}jo)@}M4`&TsUF}HjvF0|KL
z{|<ouUb~Gz_D7>RpR##w`p_NAeX)LX+%wUV_iV6bh0lU#4>|5daQDzgRO9)&3hq49
zGWToH7kX~Z9m1c2*J{V_Y`sHB=sGwb&xYLluA25?P3+#$F8AK6J^tQr<G(uC`CFgy
z-)Y*cPk*`h<M`hSwjA#j+U5SPuC_I^bN<l!N9{ut=d7>e_}tMLufgZTIoxaEGe@|+
z&kEu0f1ee??R{1V_deybLip<7;RRnCyUzrr-DiRDwXpjP5N^ER|0VakKiqtN@0Z-~
z{F3{9AHEj;e%FWFUsiDKey7LoeEd$A@5&YTKKEbN$a~@FX4{c<buZA>Z98!#Tw{4`
z^MlorV*z+_Xp3J9SerS#F7ntG0lUw%c}?Wn+-Hk{-DBFkKJvsZ0d~J>^IFNbV@95{
zCBZAwo6k7y`nd<R?aIz^?n{H!Jdeq{3|xH@HLQfsvS78-h><S`R`WiSJj=t)<99*w
ztN>R}o)y7r$@3|&TA61hxOw~zNuHJA>dCVTSS@*01*@576tnXDtOmDE$I$LMcmD2S
zZDRMY*IMk}_1@r^Bhc1@Yd?uO%hv{b4^ltAsjUN6_x_o<b>U^)dT`^^6SqEC-MHl6
z0B$~Q*5lbx6MJsFpJj|s!yV(eX0028)%5jD$v@)WunE2Q2>bW(-Hd*7njh_3H0}1u
zy(QQj;ah<n>vrbs{dsG!KI;D>r+ibIxgATK*lodOo!i0HtkbhDw~p=UjkUMV9q4zY
z`O&^p({7*KJA=&;z6-dlb62=N>eeYAK{K~wiH&tX?+*6*C)XZe*Pyp)-xI8Ma&!NG
z25gMFG2SCaf<24ZHP>k`u$t%U8hl*4z2WK~F#pfd`>{6l&(hSaO`N>@fXlp}hpTzc
zT${w$zsKHpoG*YK$2sb6zSOWUSi3dsNAJfP)JM_OtU;U__6L_W8~|7IInEjqW1kwn
z2zDIn(%*ck;Xtr<YdDzRk2R<tL{qZ{accMyxUAt2xY|r&tsyb?so_wt<5-ve=DU`w
z<uxA-*6w}5XM|kaFQa*VwYyJuqgS&I;|>Rxd!-Ft?v*3pYRT6QHby;j83QioG8V4p
zJuhoC4zBJRb<+EBjnq46YOawudB=mxyc6JRK7YGLiLuWbb%7nnb<^K`S)(Jt+N*1H
z6q@tW?i%^Mtd=$E2A69z5xxyA=cxy*mNn`H8>61NOahm4IU253o~J&zx@*)=@5eP#
zpG;G8jl{`21zhHx3RlZ{N{oHh=oql$xNiEJFKaXnti8HM)6txl_N>bcuxoWf^FHzw
zu$sPEN45BW6<n_4aqw~-zXn&!Ivx);Mm_UA0bI^^CS1+4o4s}-T-|j%nck1<sD2Vn
z&2<zf?<wFi@2POLoX5o2XB|(|PIGPbH(zS_I#|0koI#%&)K90WS%Ww=d;?t8a3);M
zbL4(cjD2c23+y=7rN8-7!#Ba&t>GN{)S!MgP0bp_so`93S;H*2TFzWz>{G*eV8^j8
z{mqyC^ewRV>VEn*n%7smd*xVqHS6%cbOCs`f?o)Buf={5*qBk=|9t<r7;KDw+RS-A
zy}B{_d>4F4!7l~t<Nnn?8?29d*5h*UP@4HJqnC@Xpx0kNpU<uWFV(bNNiX-=)x6&W
zZ$odqaoUX=fp#@`O<L|H*MQYBuWP|-X+9&G^Ex#1YR~+x2X9Erd~N`%>1)l})Z9xu
z(tGXgQ_GED&tsnJZUU?MTxYyCHRHFZH-3jE-@M7~lkaBmMzrL+1+12Q+SJUq3BCC?
zqtAS92V3)g%-KD02UyKdv^$%c@0`)@YHE}{=lS_=G~@Nx?tXMmw}G{N%v<ZWG~Y{o
z-|+VqKmIPW4Sv2`_?wJ1`rAw1QMUu<9n5~G3g5lL_iA$I=yTTgH1j^lxbhvF+79&A
zXMVN#?+n)er%nG|!D_qEl4CcpdU9BkT5{|GE^~YauC^yFIYxrjlf!waCCA?2GRJ4(
zYWgR~=fLX8;oQ}dV;`_u_~*fn6aEFTwTJHuc0GJ2@*0hznZr1JwSU6(QO~t>P5tf4
zkH3NCS}xJV{!ZX;U(x;D%WLfKTe-#ufXi!qM1_y5@Cg;(Q{n!{fimBW3O~NWPpR-T
zD*T)ZKfl5+sqiZ*{Mrh?xx(+P@cSzKfeL@5!k?({XDa-K3it0;%Jq4*!r!RycPsq8
z3je6WKd$ikxOtT0`8Opc_isr`?%$A<+`k(sxql~8a{o4@<o-QK$^9FUlKXcb;r<@F
ze}(&ZAF<nysc`@HqqO_CAM%`|FM{3w-j_We2hr604K}~~90tzsKBK{jJshkpv29@E
z)xBSNR@CC(4pxi*Sg_g{n*K-7tHr+qtbgk01g8#d@f#1;W)9DvJhm=yIp$GtwIgZC
z+YL@$?TMWT)@EMMu{^e3aGCdLxY{II^7es~S9@Y7gSDC0`++>RDc~~iF>p1XxsrDp
zIC-@vb~;#_dA+a5WBUrY%==Zi+Of3cJr10_+7tUVur~9~pqIyX0=Ue3B3x}IEqPA@
zC$ILzo($Gz-s9=zv7HJo^PUD*EBEEs;mNB#v8RKznb-TJJhpFu%e-g7)y|})-fx1F
zS9@a525U2~_g#5x=Yq?;=fTxx(USLD;N;bw*l&Zinb-TbJhltKW!{V6Y8TRy_hNAJ
zYESHUz}n2~_kcXM?}E#`v*Bu&(vtTwaPrOuC-!o%HuGLWFOTg?aGCdeaJ8#w$$K?8
zd9^3@8n8C=UO_L9?K*Io_XfDy^|a)@5uCi*6MGX_n|ZILm&bMsxXgPST<um`^4<<k
zUhRp!1FX%wH`B{wy9-?Ay$7y#H!XSZ1t+ie#C{*F&AfNg%VWDAT;}~DT<r(6<oyvi
zd9^3@$6#&dy^mfV+k@aT?@!@sKcOY>L*V4qp4f-M+RXa^y*##`fy=x<hpRnGOWw!8
z$*VoFkAt<D_Yrz|Y`*}Pd7px-JxNR6r@_gqJ+Z$8YcuZ?^zzt#1upac8m{&%EqR{<
zC$ILzJ`dJr-e>6LvAqZ`^ZpjD_8VIAz64HQ?TP&zSetoYpqIz?dvKZe4{)_tXvzCW
zaPn$T?4Q8e%=<FEJhnfB%e=3_)&4?D-q*p&t39!Q1#2_!tMu~N{su1dz6Do%la{=1
zgOgW#V&4I4Gw&Pp^4R_k9#`;xfG5!WZxBQ1|4GwF-S~H#TH@b__t3&W0Qb`p{~=f(
zb>rWoSBw9@z%vT|Z}9Q7#Qz7ZkGk<6(W@o?6Ywbo|1bCqTH^f=srslJ|1rH<;^zmS
zgA~31{Cs%gTj2Vr8}D<jTKtEAFDc@O!o3G4ei&RIb>n?5R!jUs;3JCoh2gGop7j=i
z>!Y5SMZvCPd=`W2ryifh!LC(&mVoQ09-k$_u19>9g6pRqpQXXhIX=sP^;3_}vS8;G
zpXI>%sXJ$%{ng^X0@&}9@D<^H4`j_g1=mO2c;6M&;=eN3`+N8*aPP~BUlp#8y79hS
zsKtME@B>BsaJcu$#IFI@N8NbeMbr|%7TEh=_}cJiiuiTl`luW4yNg=<*8_V$3SS@Y
zeI(;=0M|#|c;9u@;=d8t`$PDr;hyWnZw%K*-FV-P)Z)J>*lQBL8F(q;Z{W<YL%#)F
z&EM7i4buC-mSFWG!Rm?K3hedC*jt13RnLCd2JD#H61Oe59CJIkn)x&4_Hgy;m?O}<
zrWtbwu)gXUb4Re_YRi~Afy*&>hO12~#@q$2ULA8+H1|Qq+zqU+ddA!x?6}%8<{sd3
z%st_1Q;RV_16Qw(ITFpilQH)K>#LqI_Xazzwv72%a5?7Z;A+PfW9|c2ua5b7H1}J^
z`~p~C^^CbM*m1SFzkJtL%lHR?%k%w3czIqAgg-zn@jnP&o~MK1<@xv$-2Fa^UlK=w
z51~1RdCg_KG5T50{`C4J|7fuHm+&vcy<dbM2KW4j9}f3Chqu8!pW#QqJ#VR}9qt(B
zHJ9<m=x05L((9A>v0$%H{!U^X+?v(n(*agDehj@lw(;OHegfPv)Z^0yRyV$rULM;~
zV6R!m?*=bPJ>|Kch^C&H9<X_`FM7fHsK;j#*jjTRIU20y9?O~TgR5uXCEsK;b862%
z>jzt_w$wTWY^}y;+^J~l;m3fjHFZn_tCe+3hpSiXn1N<K?WyA{U~AEqXRTwwdDhaN
zvA+t|=DHtAFOTgwu$sTGiu3#GFy^u%&Cjy5{EoU@6E8-;e4(!Z_V?9K(dYNo6UaBT
z;HOsj=@oufh0m(+3o87Q3ctL<udeVLD*V<8zpKLUtMDIJ_(K)`XoWvf;ZIlivlaeA
zg}+qr{lFhrxc@ItxxW7YJSAVU!u|hwO1u9*k34%}Ci%U-*<&Zd)ec0<9y<x1JvO?C
zJsDkFVow1ZukOBcFQ{d#)4*!+|2kN03_108uc*cU46y#G;~U`Ap)G!Ag0-2${Uwj>
zo8WTHv*Bu<x8ywsp1j%<doEa;dEKY-*v<o&dA|i$^E*6wzYR}b?TI}ftj)accX@0V
zg3G)Y!PWepPTq^*$*VoF-vMhgujfV{+jqfb-b>+XeitY2Y<Ti&PwZu2ZRYj-$z!_$
zT;{zJt~RsCdlfu+wI}v_U~T5ToL(N=HQ+MuwQ#j^UtR}KUhRp!9<0s0-Vfxl-3Tu8
z-UL@Wv#9rGc=Bpb>@8qz=JmcJkL@;anfG?M+N>h)9q{DUp4dCV+RS?^y*#$N!DZfi
z;A$5ZdGCcMulB@#AFR#1-sj}8-48DF{s69aX_5Db@Z{B=*dKwlnb-TJJhlhGW!?wj
zYF8C`e*#Zl?TP&<Setph@5*C)80^^&e+2BA%=h-s!1|~g{}8=e{C^Jitc5=Y_KYO{
zaj-t>#y?807XM#>-TUEBg59%;e+sORy75oYtHuA9VE1D9Ghp{n;(rC!N8R|R>DA)@
zYp{DG{5i1KH1W@a^-(weS$ehjzX<kPh5rWZ8Ylj@V13k$e}P^t{=WmCTJV>_e*fp$
z=J#;5&1reYdIhYWXPe~u1De+-WB(DXuX?^4{seYRZHapoT#or?xLWx<^%uB$b<Ee$
zyrvoRb+Eqb8S}4T$JLfG-vF0m{td2HzN@_nSFeuw7MlAYW4;a6S3P6C19n_(8S`Cm
zIp*KtYUR7yKj7-sG5?9?-pQEnf%R3-nD2ufS6jyX09=mwAzZC|SNjOAULEsaXzsU+
z`ERhk>KXGtV8_+w{(6aCE#rRzKE2@o1<xutkC_9`-+b`$Jk1X;&&LAr`-soGQ48EL
z%xf;=jnU6~K1SCk^$Y=@g%&;(enG*9!9D-6F9`QMhc5*8e1<O!_q?T^Mc|HMUUM05
zjDFVRbDlnlUkvQ^$@|CRaBEhN&k|sD<9#la$F>x>j9(h=80zs^2CQzp&yn)jmIHgu
zGXC;#-vvDH@mWEwh*=SAp6rWHf%Q>O%t~Nu&3$BLu$p@;_mNfL>e+Y6w<?-BwP&BL
z2DVmhsdaU*wHlvshoh;7uK~8!)UhU5t*m1$xO%mYwb9I{J$0-Dwia!9zFHTY?>+4q
zdp)o=*WKrJd2Abi)wKESF5iyd$9z}Y5WFzGy6<xGyvwbOz8cNXDzv=ItqS&?ZFTyL
zu`zM#sdE!}>eLp$O~KlZtu_9xZ!@r3?3;tllQq}^uI73r_m=SF)}Gj{z}k{~Yp`1E
z+kng5+rrh#=k4v_$*n!H+k>?w_Xx0B{w{9^uyb)tZLXzSxt41%2S4Rn4u`vzYtm<|
zorzP=8tejBE1%zYg{MyKiQNsXE&ngc?qIe2za)Et)%Ktz<}=`OypeFV^0|I5c*fJ7
z*uBBpGTvvwY8mfyV6}3*ec<JIpNFf>WX`$9Uw~&k?HO-hu(pgh3apm#_5-UqUarml
zVCQWu+PyYvxi;%E?j|%p>(R2$*Kgvr=r<_vhE2RS{YFjf`|zg=yfN78x+#5r*Eo<d
z%lGJmEBufOKfJ=n7JLG@tHOIKysyHiR``qxKd#`;ZDxg^RN<#o_^b+_UEwzr-1_e+
z_-o+T3+_6-RpD<}_&Wvn8hujX{#zAUZ|!>)T-|?@B6fTKEsAh|r}E#T2)Fm&q6qH*
z`)^T%+xu@&gd6X_K@o26zd>Q2y?hY$x@WvEyEo*qeF^OT)8;;r$95=KE%%4fU^Tx-
zbAG<8M!dhZXiw~6U~T4gzsX~31DAP^fUA}F-gbEMYESGKur~9$Z{@L#1DAO_;A-W4
zw-cVc+7mk-tj)acf4Seu?$0B^p2a*rtOPy^P5t}L|Nb)(tkz94hi67DIeNj>9Fx%0
z?`Y;Y8myKao-?)Nm<%?D>tx;5(T}E{I;MctlEbs9mK?``t2w5jsi%(VV727%JgX(g
zSHR|QT~o)gXzHost6;U{@E)L+9A5)ha~zMRo;pqdt0jl`4YiDUBG~()>+L;69^1)<
z&HITwwo?n6_ZGQ-3w|2C_fmWR|GCrY&!G9y{*9*H-dz4SzB9p|sqnMF-ji=>Uej;F
z^-=f#1(AQ9W^Tt4C-!WxxpLml1*@GybB@~7;(s34vlad=aJm1#4Oc6_&(DWv|7%a|
z1z>G*|9j?zVE1sIYcB$;x%WH=d9J+}%~<WJ`#WH3)0XegOTg+UvM%o1OTlX2r8zh6
z>1wIxGO*`6{Bm$Pw=3Xk<+H<;@XSqnVy^;g%iO*P_FQCcSA*56bGru3SnZkHwP0)0
zmbqOAR?pn72dianv%zYq=SJ|@g5Lx#=XNt(Z6@oK`|K_7%uRc8-3r#0x!nf#tYvPu
zgVm~Yy93Qw?U~!1U~AKsx!na;&)n_?t7UFCfYrQ)_t4)<OD*3A_t5hH1>FZ$`vBh`
z(EIUBsNYXh^Gt}%;Xe5x*u9ba#*e@opqKaJAET+K#s|R0sVDA1u=krX?k8yKd8Yd*
z*jV-4Q`9{Bsm(s~dk8$0miavlR&#zoqxa+d)E}X#IX`jc_b7NaEp`4J?EJi5@p%kQ
zJ@b1UY@B-Ho&Z<x>%Tx#&-|VQ8>{a8PNG+HeyPnq^Lq+>94+&E8m#90o}u^S{M3I*
zQ*(ae)cz~5dn9!}3wD0xcgL^M)HA>5z{aU3?s;(a`{D&O^~~=@u(9gS?-Y79=a<^-
zQ`>LAGYkG(u-_*?Y~H(Hg6pH6nBRe2xA2$2Wz6s4`lw&s%<~G^T-p-%2e9>p{}Ei~
z`4e0p_2hXKY%XnHgTK)G@fv9RGwn^9*FfyrO`v~+_B!paG}lG$Idxr5r`O*&ZEw+g
zM#OIy_?;$Bz3;-ywfj5Vb-BMe=YN3pQBTZ2!DY;QaMvI)?}PPG&zwI1n@gK>{)j$v
z*7hMy%{ho2%kQs$fxBqN{D(d<>i?#FOfyEDdHX%-n&_`hpV-{5rA;5l^0$lsg5A@Z
zCqvGer}p{a?%lIk8~OZjHT_O#Y72nPqs=it0jp*Iw}92k`$8+4`XW4uc&{7+=F-)h
zwu#i|Gs;k~HtUlQ10PPVnT#!85U!7UuDe>sUI^^i<(XX=O+8~T0?ydlGWMeS&@%R7
z;IYNni^KI%cWn2WTGn<6uwz@xTGYBE+`T*+tiN2J<X;->9@gJ?pk<o={(Cz5%k}YE
zX5ZKw?;0+P&3zoc9NaydJ-R$xANBaG04`%zgqQpJQ*eFMv#(bIn@gK}bQO9(o@H$-
z)70FDV#jh{uL|y?9%EJq`!Pm+HQI2RF=FTITFk`9`RcDtpV)kUDsB2Wmiu%~aJjG7
zf@hxE*M^t-dL6i$ekU~d^}1m5Xmd>8mDRGh)&r}R-^=U6)w8!Y0B3J$%ih`$tj&7e
z#~XnUsn55uuRjgfN8Pc#pQ&Z+jlqsx?(0q9>KS`eaK_e_u{Q&2%h;QP%YD5CTpxAE
zc3-PyZMOtFwzasgw*r^@TCPv>Zw)T@^)^la>}$C`Ud!wod*j{L+k)Mb;oHH>eZ4(g
zANBZ*0GBa4z`g!C3p>K~QO~~K32ZKH?$KT7{kTW9?Mzd1ABr8zeZ4Dq2Dy#d9qh*#
z_1$QD(2Nmh@49E4um0NfiOu_DY17BC+_#?rm-~7oJoD7P7rflpd&AZA%f9|B*gV=C
zb5DA;?5)p%)yjRn4_rNa>+|63Ep6FbUjS>fUibCB;BsG&g6pI1*zRk!jJ+S&vCHp@
z{o(2v`v7pp)|Roq2-cRd4+NLr6$iofQFm<jwOZEpV6bCnUw;W)?rXU|$$tpA+}DRT
z{j;y-`gkpOq4zr5C;rP|=O2C;+?qylt`=qO4u|Wb9-kw?2jgS?ZD6^$onHU=jRjkq
zwlQG2|8Kq5WE^;DdgG1LuHR^SZOJhnT-G-MUe?zI*GD}uM}bq{kzl#GyXp0hUk^C-
zO$5vH?^gAK{rfoMjni(9PI_(T@W0DU0;~D&?ex)4rl}oGyBHtOW`9%nY)%FH@ocJ3
zp`A|ix`<QTF<{r?dh(iM8d%NqV4fLZKjzUkopu_{JmTc}3fMf>?wZJBI~J^#_t&q&
z)f^-5&Bwv>-mE>bUju71uV+gh+wtHs?+I`<&r|ZwgeR}|#GVM&W?s*YJhqd-W!{tF
zYJUGD?<w%))t=Z>!P?C0_l(>#;X1lzuAMy3^XhW1mv*m_xxD6QfW79P(GL1=&^)8(
z(9AE_N4xJ2XEp74e~_O^E5~yjx$h*7XD>ga$?fH*HMw<WZs!o|x;UQCZ0EwQ=WKfG
zk?W(s-(}~4{q73?7ToWpMTpk^ZMgR~f4kLJdwkCad#{i01%<D1+O5Ob3&GYgi{3iq
z`ls%T!3Sbb-QR)he-XX@a((n)mwcBr?f!QmasIoI-#OdR{A@wnhFI5O%O<WrA2jji
z^jp(h<8A5l-+X41&zSHl3U2(B1=sKT3csbo?=86T4;9?_hYPO#v4U%Vyx^~~CQlYz
z`_lzC{+SAYw%}fi=L&B8^A-MLljj^=2G2PfjeoA$<>=bHKCYQu?0V(9dNcgL2X~$K
z<-~Y>u7<1G{J6iE)|_{`Yti+&hIRt`$C&HDSJAXNhSxwXwcG%<hSYo`I5m3~<98Ff
zw*2OLGuT*l^Lj1S#9l||;aR&C>^`yg_w3v0@1Xh7erMBepRw)&n<M;gu=(?Q_B~*I
z)V+7hZ=;#pvBZh}KG;2+`}2KpHUBO$KKH|2`}q6-te<+;<%i&`i}u9+2&~O{yI<w8
z{TQs4e@E^Cuv)%<eggL69JD=1Q*#bt*C%sQPu@qs=5<WZfZV@v@Ou9Y?B6k{>#z1G
zcq@8;+minruAjO&JXdPT{{%SsJwx*3{{?sra;O{YnNv&bFTt+2HqVzlb^Ho!9ojr=
z^4NY2whnEcJGt01_Y^JpUjVx|w0ZvIvHb?@KGEh`lyAqs)UqyP{ub<i_qHa-b_{cy
zLtkUOKj`PZ)bE^^z-oTyIEK#<zk{pi_sEyQYCccALhr}xss4MKn%7fo4$t);z~#CA
zBV5hqC+Av!uh*Z@U1$GoF!`%sW7OmGXRzy+XY0R!&9fU#TmD_K*TCK%v?um;a2fko
zcw)6B_6@M{+P%N{J@+@Ty4NUwgYYI;J<Z=nt@|xBYuBE!-v)b6%Khpcu$sPJ6K!gq
zg{-B$*T{SDyI`-;MKp8zT>N*iy7BH6d2IgxUqQ=R|0h_@=PLcRsm1?2uv+;0;MugB
z7~lQy0azb(_rOQ=e%u4vKBTF+2kN*u)9TLaj;7sSeruE8PVcy`-M_)Eh2Ps^zqkJn
D6zj0a

literal 27676
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
M5B}bO*xwuYKYtDv9{>OV

diff --git a/shaders/rt_quad.frag b/shaders/rt_quad.frag
index d075f61..bac8002 100644
--- a/shaders/rt_quad.frag
+++ b/shaders/rt_quad.frag
@@ -127,68 +127,71 @@ uvec4 sample_color_from_scene_info(uint volume_start, uvec2 raster_pos, uint f)
 }
 
 vec3 get_light_position(uint light_index) {
-    return vec3(float(scene_info.infos[light_index]), float(scene_info.infos[light_index + 1]), float(scene_info.infos[light_index + 2]));
+    return vec3(uintBitsToFloat(scene_info.infos[light_index]), uintBitsToFloat(scene_info.infos[light_index + 1]), uintBitsToFloat(scene_info.infos[light_index + 2]));
 }
 
 vec3 get_light_color(uint light_index) {
     return vec3(float(scene_info.infos[light_index + 3]) / 255.0, float(scene_info.infos[light_index + 4]) / 255.0, float(scene_info.infos[light_index + 5]) / 255.0);
 }
 
-vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sample) {
-    uint max_light_num = scene_info.infos[0];
-    uint light_num = 0;
+struct Tracing {
+    vec3 end_pos;
+    uvec4 end_color;
+    uint end_volume;
+    uint end_facing;
+    float end_factor;
+    uint end_cycle;
+    bool has_hit;
+};
 
+Tracing trace_ray(uint volume_start, vec3 starting_pos, vec3 direction, float max_factor, uint start_cycle, uint max_cycle) {
+    uint cycle = start_cycle;
     // setup volume info
     uint volume_index = volume_start;
     uint volume_pos_x = scene_info.infos[volume_index + 0]; 
     uint volume_pos_y = scene_info.infos[volume_index + 1]; 
     uint volume_pos_z = scene_info.infos[volume_index + 2]; 
-    
-    // setup light info
-    uint light_index = scene_info.infos[volume_start + 6 + light_num];
-    vec3 light_direction = get_light_position(light_index) - starting_pos;
-    vec3 light_color = get_light_color(light_index);
-    
-    bool x_pos = light_direction.x > 0.0;
-    bool x_null = (light_direction.x == 0.0);
-    
-    bool y_pos = light_direction.y > 0.0;
-    bool y_null = (light_direction.y == 0.0);
 
-    bool z_pos = light_direction.z > 0.0;
-    bool z_null = (light_direction.z == 0.0);
+    bool x_pos = direction.x > 0.0;
+    bool x_null = (direction.x == 0.0);
+    
+    bool y_pos = direction.y > 0.0;
+    bool y_null = (direction.y == 0.0);
 
-    // initialize color
-    vec3 color_sum = vec3(0.0, 0.0, 0.0) + (orig_color_sample.xyz * 0.01);
+    bool z_pos = direction.z > 0.0;
+    bool z_null = (direction.z == 0.0);
 
-    uint max_iterations = max_light_num * scene_info.infos[1];
-    for (int i = 0; i < max_iterations; i++) {
+    // default is max factor, that way we avoid collision when going parallel to an axis. The other directions will score a hit
+    float x_factor = max_factor;
+    float y_factor = max_factor;
+    float z_factor = max_factor;
+
+    Tracing result;
+
+    while (cycle < max_cycle) {
+        cycle ++;
         float x_border = float(volume_pos_x + (scene_info.infos[volume_index + 3]) * uint(x_pos)) - 0.5;
         float y_border = float(volume_pos_y + (scene_info.infos[volume_index + 4]) * uint(y_pos)) - 0.5;
         float z_border = float(volume_pos_z + (scene_info.infos[volume_index + 5]) * uint(z_pos)) - 0.5;
         
         bool needs_next_light = false;
 
-        // 2 is way behind the light position and should result in no collision being detected
-        float x_factor = 2.0;
-        float y_factor = 2.0;
-        float z_factor = 2.0;
         if (!x_null) {
-            x_factor = (x_border - starting_pos.x) / light_direction.x;
+            x_factor = (x_border - starting_pos.x) / direction.x;
         }
         if (!y_null) {
-            y_factor = (y_border - starting_pos.y) / light_direction.y;
+            y_factor = (y_border - starting_pos.y) / direction.y;
         }
         if (!z_null) {
-            z_factor = (z_border - starting_pos.z) / light_direction.z;
+            z_factor = (z_border - starting_pos.z) / direction.z;
         }
 
-        if ((x_factor >= 1.0) && (y_factor >= 1.0) && (z_factor >= 1.0)) {
-            // no hit, add light color result
-            color_sum += (orig_color_sample.xyz * light_color) / ((0.01 * length(light_direction) * length(light_direction)) + 1.0);
-            needs_next_light = true;
+        if ((x_factor >= max_factor) && (y_factor >= max_factor) && (z_factor >= max_factor)) {
+            // no hit, finish tracking
+            result.has_hit = false;
+            break;
         } else {
-            // if there is a border hit before reaching the light
+            // if there is a border hit before reaching the end
             // change to the relevant next volume
             // Todo: look into removing ifs from this
             uint hit_facing = 0;
@@ -200,9 +203,11 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa
                 } else {
                     hit_facing = 2;
                 }
-                vec3 intersection_pos = starting_pos + x_factor * light_direction;
+                vec3 intersection_pos = starting_pos + x_factor * direction;
                 u = uint(round(intersection_pos.y)) - volume_pos_y;
                 v = uint(round(intersection_pos.z)) - volume_pos_z;
+                result.end_pos = intersection_pos;
+                result.end_facing = hit_facing;
             }
 
             if (y_factor <= x_factor && y_factor <= z_factor) {
@@ -211,9 +216,11 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa
                 } else {
                     hit_facing = 4;
                 }
-                vec3 intersection_pos = starting_pos + y_factor * light_direction;
+                vec3 intersection_pos = starting_pos + y_factor * direction;
                 u = uint(round(intersection_pos.x)) - volume_pos_x;
                 v = uint(round(intersection_pos.z)) - volume_pos_z;
+                result.end_pos = intersection_pos;
+                result.end_facing = hit_facing;
             }
 
             if (z_factor <= x_factor && z_factor <= y_factor) {
@@ -222,9 +229,11 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa
                 } else {
                     hit_facing = 1;
                 }
-                vec3 intersection_pos = starting_pos + z_factor * light_direction;
+                vec3 intersection_pos = starting_pos + z_factor * direction;
                 u = uint(round(intersection_pos.x)) - volume_pos_x;
                 v = uint(round(intersection_pos.y)) - volume_pos_y;
+                result.end_pos = intersection_pos;
+                result.end_facing = hit_facing;
             }
             uint next_neighbor = sample_neighbor_from_scene_info(volume_index, uvec2(u, v), hit_facing);
             uvec4 color_sample = sample_color_from_scene_info(volume_index, uvec2(u, v), hit_facing);
@@ -237,43 +246,56 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa
                     volume_pos_y = scene_info.infos[volume_index + 1]; 
                     volume_pos_z = scene_info.infos[volume_index + 2];
                 } else {
-                    // neightbor miss, shouldn't happen with a light inside of a volume. Might happen with ambient light. For now move on to next light.
-                    needs_next_light = true;
+                    // neightbor miss
+                    break;
                 }
             } else {
-                // color hit, move on to next light (may change once transparents are implemnted)
-                needs_next_light = true;
-            }
-        }
-        if (needs_next_light) {
-            light_num += 1;
-            if (light_num >= max_light_num) {
+                // color hit, move on
+                result.end_color = color_sample;
+                result.has_hit = true;
                 break;
             }
-            // set up the new light
-            light_index = scene_info.infos[volume_start + 6 + light_num];
-            if (light_index == 0) {
-                // abort if there is no new light
-                break;
-            }
-            light_direction = get_light_position(light_index) - starting_pos;
-            light_color = get_light_color(light_index);
-            
-            x_pos = light_direction.x > 0.0;
-            x_null = (light_direction.x == 0.0);
-            
-            y_pos = light_direction.y > 0.0;
-            y_null = (light_direction.y == 0.0);
-
-            z_pos = light_direction.z > 0.0;
-            z_null = (light_direction.z == 0.0);
-            // reset volume info
-            volume_index = volume_start;
-            volume_pos_x = scene_info.infos[volume_index + 0]; 
-            volume_pos_y = scene_info.infos[volume_index + 1]; 
-            volume_pos_z = scene_info.infos[volume_index + 2]; 
         }
     }
+    result.end_volume = volume_index;
+    result.end_factor = min(min(x_factor, y_factor), z_factor);
+    result.end_cycle = cycle;
+
+    return result;
+}
+
+vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sample) {
+    uint max_light_num = scene_info.infos[0];
+    uint light_num = 0;
+
+    // initialize color
+    vec3 color_sum = vec3(0.0, 0.0, 0.0) + (orig_color_sample.xyz * 0.01);
+
+    uint max_iterations = max_light_num * scene_info.infos[1];
+    uint iteration = 0;
+    while (iteration < max_iterations) {
+        // setup light info
+        uint light_index = scene_info.infos[volume_start + 6 + light_num];
+        if (light_index == 0) {
+            // abort if there is no new light
+            break;
+        }
+        vec3 light_direction = get_light_position(light_index) - starting_pos;
+        vec3 light_color = get_light_color(light_index);
+
+        Tracing result = trace_ray(volume_start, starting_pos, light_direction, 1.0, iteration, max_iterations);
+        if (!result.has_hit) {
+            // no hit, add light color result
+            color_sum += (orig_color_sample.xyz * light_color) / ((0.01 * length(light_direction) * length(light_direction)) + 1.0);
+        }
+        iteration = result.end_cycle;
+
+        light_num += 1;
+        if (light_num >= max_light_num) {
+            break;
+        }
+    }
+
     return color_sum;
 }
 
diff --git a/src/scene/light.rs b/src/scene/light.rs
index 4893dd3..20a33ef 100644
--- a/src/scene/light.rs
+++ b/src/scene/light.rs
@@ -15,9 +15,9 @@ impl PointLight {
     }
 
     pub fn insert_into_memory(&self, mut v: Vec<u32>) -> Vec<u32> { 
-        v[self.memory_start] = self.pos.x as u32;
-        v[self.memory_start + 1] = self.pos.y as u32;
-        v[self.memory_start + 2] = self.pos.z as u32;
+        v[self.memory_start] = u32::from_ne_bytes(self.pos.x.to_ne_bytes());
+        v[self.memory_start + 1] = u32::from_ne_bytes(self.pos.y.to_ne_bytes());
+        v[self.memory_start + 2] = u32::from_ne_bytes(self.pos.z.to_ne_bytes());
 
         v[self.memory_start + 3] = (self.color.x * 255.0) as u32;
         v[self.memory_start + 4] = (self.color.y * 255.0) as u32;