From 9c19d178db29e98bc7dd3f4583bb961bb948d998 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Thu, 30 Mar 2023 15:19:54 +0800 Subject: [PATCH 1/2] Implemented color decay and color tint range support for particles --- Assets/Scenes/Scene2.shade | 8 ++- Assets/Shaders/ParticleEmit_CS.glsl | 14 +++- Assets/Shaders/ParticleEmit_CS.shshaderb | Bin 12469 -> 13381 bytes .../ParticleUpdateGrowThenShrink_CS.glsl | 1 + .../Shaders/ParticleUpdateRandomAcc_CS.glsl | 2 + .../Shaders/ParticleUpdateRandomColor_CS.glsl | 1 + Assets/Shaders/ParticleUpdate_CS.glsl | 2 + Assets/Shaders/ParticleUpdate_CS.shshaderb | Bin 7833 -> 8265 bytes Assets/Shaders/Particle_VS.glsl | 2 +- Assets/Shaders/Particle_VS.shshaderb | Bin 6845 -> 6989 bytes .../Inspector/SHEditorComponentView.hpp | 20 ++++++ .../Particles/SHParticleEmitterComponent.cpp | 64 ++++++++++++++++++ .../Particles/SHParticleEmitterComponent.h | 22 ++++++ .../src/Serialization/SHYAMLConverters.h | 10 +++ 14 files changed, 142 insertions(+), 4 deletions(-) diff --git a/Assets/Scenes/Scene2.shade b/Assets/Scenes/Scene2.shade index d284d4ea..6e794990 100644 --- a/Assets/Scenes/Scene2.shade +++ b/Assets/Scenes/Scene2.shade @@ -1,3 +1,4 @@ +- NavData: 0 - EID: 0 Name: Default IsActive: true @@ -170,8 +171,11 @@ Angular Ranges And Offset: {x: 6.19999981, y: 1.10000002, z: 0, w: 0.100000001} Rotation Speed: 0.0309999995 Rotation Decay: 0.0199999996 - Texture Asset ID: 63456868 + Texture Asset ID: 0 Custom Update Shader Asset ID: 0 - Color Tint: {x: 1, y: 0, z: 0, w: 1} + Color Tint: {x: 0, y: 1, z: 0.56387639, w: 1} + Color Tint Range: {x: 0.5, y: 0.5, z: 0.5, w: 0} + Color Decay: {x: 0, y: 0, z: 0, w: 0} + Acceleration: {x: 0, y: 0, z: 0} IsActive: true Scripts: ~ \ No newline at end of file diff --git a/Assets/Shaders/ParticleEmit_CS.glsl b/Assets/Shaders/ParticleEmit_CS.glsl index 7b6e60be..e3cf2977 100644 --- a/Assets/Shaders/ParticleEmit_CS.glsl +++ b/Assets/Shaders/ParticleEmit_CS.glsl @@ -14,6 +14,8 @@ struct EmitterParameters float rotationDecay; vec4 lifeAndSizeRange; // min life, max life, min size, max size vec4 colorTint; + vec4 colorTintRange; + vec4 colorDecay; float sizeDecay; uint textureIndex; float padding[2]; @@ -27,6 +29,7 @@ struct ParticleData vec4 acceleration; vec4 scaleAndDecay; vec4 colorTint; + vec4 colorDecay; float life; uint textureIndex; }; @@ -175,9 +178,18 @@ void main() particle.scaleAndDecay.y = particleSize; particle.scaleAndDecay.z = emitterParams.data.sizeDecay; particle.scaleAndDecay.w = emitterParams.data.sizeDecay; + particle.colorDecay = emitterParams.data.colorDecay; + float randRange = rand(seed) * 2.0f - 1.0f; + // Set particle color tint - particle.colorTint = emitterParams.data.colorTint; + particle.colorTint = emitterParams.data.colorTint + vec4 (randRange * emitterParams.data.colorTintRange.x, + randRange * emitterParams.data.colorTintRange.y, + randRange * emitterParams.data.colorTintRange.z, + randRange * emitterParams.data.colorTintRange.w); + + // particle.colorTint = emitterParams.data.colorTint; + // Set the texture for the particle particle.textureIndex = emitterParams.data.textureIndex; diff --git a/Assets/Shaders/ParticleEmit_CS.shshaderb b/Assets/Shaders/ParticleEmit_CS.shshaderb index f0e7b1918e2c3f3dfef1970fdaf6d6dfa236364a..16b1d3665551c0c141b9bb7fa44cedc67b772490 100644 GIT binary patch delta 3857 zcmZvfS#VTE6o&gInaRQyK!Qp^p_KXn4_I1S6l3ZFYA<* zPfK%KzL;+=fYa(`XEdXFR9R;bZBEw(ozaHsVIiRva(xiw}-@s@qQvK2u$JY%6!ybR|5d zgjdSJ4p{(xg|McWpDkV9|9lV(h%T+YD%wA=wsdpt+#u)^Z5uc|IyCU89#-c@OGklo zB%(Out>SdV_`~8HmhqM1Jj(C^njaI_XNvhZh|@jePl|JAjBgLzEsm2OsRTRZWD`~Z z3HQkM$AIZm#_0NS*$;}xJM-od%Fr40A3RLk=^GALf9Ns2ACdG5&I(60vjROIpK#iR z4gZM*qoqVD`AxV(^BA#4&1c22Z53wRpbes@P5PAf4*oNUb`BYPEw2!I%R-lEp4W@> z3Nb%(HcHn`uIJTZR#dz?e9o)GI5V#epYJN&QFpvwc&E&>H72P8cWI_);JKPli`GlD zPV+tDq2?tT9R4EB6IC$1zgHYTIyM70-F?Eoj!u|vejpbC2-&p^Zk+B3Ni)L3G*cjj zQ4quw^xMd=ijCPR>8-bSW5#fs^TP{03+sz7L%S8vtg>89s?&|R&*A~kv%^ez) zlvdPQVY?+fC2+eX>x2g>2D`;SDhwwVI{3QeRy_{Z;Qh8Hv8@-DJ&bP(qSZ2Br0fnQ z*eGn<<0`Wd@31F?@mcRS38S@VYqPNFcwzd_umZCx$mnvuxXhxlw#SaddFvIJzC0U)QjL zwhL1@cj}GAM;_j~J2`(6aZV(XAr7)D{-(Gk;#sr~yd{k9fD&zy{%v7wyn+5vo_E3e zoYTVi-qARq@vpvXz*f+1&fjkNE;)8<*e!ogm|KqB1n&#O?Uuu>wR?rp?9s3d>=VA& z20oA-pI&ucZ-$Z=NLy{E9}45+tT>MS!Yo7reC*hcdX2bK;=~YNlP$Fp;N-d@?o(K&7X@CPb`bUi8IX?!f5orTl1v|noVp65e5QH zbXph@KTT|*uf!3pO%{R^XPU2t(Ug0dZ^Y49C*Z`H<_yn2B7XnaLf?ub;>J@P{EUW) zz7s~nPeapuFOFt|1{yeVrujh_P1@7^C>|o3qk#wmfr$7u@RKkio>dm&E9_@+G_y3& iz==ac@?V6}@H-XF4&h%l(AZ-RC+@rpN)tveP5loe66MkW delta 2897 zcmZvd+iz4=6vp>y=hlV_47E*4XljXx36lhU_>7!Yp^(`gwTX6kf`r68vk zs&c7{BPxg#t9Zo=jo zY3aCfp9?WluaPc6b zu~v@F*R74a>w(j`LVhT>9FPor$=dGZ1D?0DI+g0_e$sPpBvZ~DP()lg_Ac{EK3m8= zlAj2KaTjyhTjFAFxOy|y(|O=O-qW}6guCcfONo}Yi*oZBDUIeU`BD*_a1CtFCOU)d zI=K$!3Z-nma%g!w$@Yyzn~yps-)J^d$n_QnAI@bn#3b~Oy|{3;R4A2qGHCG8Dl%0b(s{l$^7%0pvAL%FiT+jLAk2oQ0DnMwxBtmbM zcZhD4gU8dTwO(siZR3hlUQoJN;KC9{8TudiRz-YF0BJ|WS0DO#DNM^Kh}#nJF#>!8 z5ue)k1LvNIll}=D)auhzXH^Mv8qwM+&K&r(YDM{)fd4xNa`5SM^?{~7z%e%`eWx(Z z^tm<5j=Mz2%YoNwzufVc=QUM-UUhe^Vf9|mYpfR1>#8&9MV~@8D29jltORsw{GfO$ z!k-tXYui66PIJbm#JMFM%5qGYf-L_^;n(E5v9f^}8czQAWXXR?c2me11U~jJhZrsOQOAPtq->Yiu+=Z9u7(O2(Oi;KnkNE zk`vdf2TW%f;U!rLA_p8Dg)z!O;YC^Ym2oS=-!?Fm#`($lO zdEw}ko)M3BJE2gUQbBv{lViUuyw?xMTNH^3e~k!B+G8IfPZ4fY8WCnn6i8tdL~`PY z=iMO2iYN=?>(zXipg$_Y2)R`}Q$+X(G*Lx3DjE|v4bKw|KH^Bs`|_NyHN*|IT;sy* zg#`?`Ln4-paghukftGAS_;$$-%g>&5b41v3F+p_=tE11H9+d`Z~yFivavWnu04Zb6C8D8UIiaPk)Yu0*H6 z`rOpP?48tlTk8*fPk^nU8DV>!`8|c(>->svS~>7r{Hwxnie02M9Mj?Ze?}M)Uw78Q z>%zC|pejFm7WYOZj;UIwXNB1t(7gESd{dZn(4Y17hmIL%N$@RU#yO)!g>VFas%s`f z_e{a!&kIN6;peoX@#rXWQaRrdwq`h^I@6W%FUZM;C4E 0.0f) { diff --git a/Assets/Shaders/ParticleUpdate_CS.shshaderb b/Assets/Shaders/ParticleUpdate_CS.shshaderb index e7a3ec64ab4226c88426985ed6d2caaececa70b5..45e17306aad6c83403e7fe3fae6163642df9d953 100644 GIT binary patch literal 8265 zcmai%33Odm6^3t{yd*#iEiHpUYf7utLTj~vSb;X3l4!BTR&m1g^}U<+!s~nSy_d9A z)FR?6;yjN?tpm;jq9Ua@t*WSq^MJGBhzO`_xt9NT@A;EMOqZu?=j{ET{qMccKIfjK zy{mhZd~{4-*qtQPlB1KE$^8YC%uc2YNs?odu6*v_xMkzAR=c|Fth1Nna%|F(d*XAP zd`g--CA-R5orPm0vxI}qmh6+@i*)GUbj`QO=v3DJjYIvLHuY~@KU5hR8EUon*3zL` zR!@hjSu?G)v#}Jvp2#n&S8Aix*r6nkI6roea%A;tx<_+K7B%gt4fWR=+sn1V`dFh< zZfA}9;JSRhD>+{C=5n*0Rch(Fa=R>3J1B7UkwzjgNV=t{rxt8|T|0f>3t~6?m=GLsU7W~GZ`$de_GmL53@ws(DVZyLB=i9PlA@oWd8)pEGbZ;1{Qva@ zpQ-u+ex$yzcBH`4v^A4fJc)3lbg+*xA_+o8`Sa(Bi4-YwlCuW>HJSu;<}c@Ts1*j{d_#)2bLHFYQ7(Cn;59b_)fku^s4fU4kiB)1hy z`Mz$KP7Lim+@n$g#(-P&q$9bbfO5{=($|)E>BY$@>Tp*A#(3a&T*`6wJ2rA*nPzgf z`1<~V8e^X$&Bmo*oWnh`D^VWy{10L4cV+E%+T1+a+PSuo_k-5=g6?}%VIHoc7g3G9 zVf|>$l?^&=T3BE6^e)}(y9`hH=hU4`m(&@GBrPAq-?d8(BSGHG3XJ59@kxowPd34a}o7Y!L=Y7Bi zzd*v6t14D$p08-@HM52g8=+SlG_ywRe$CVkMz6330>=7a(4CtYmq@&K>}v3#7VOI; z-aEW&CCPcGZQ#tVlj<|uFCCja@6${jVAO%lI}gVC^+D$hux|=B`G|Y7X3lZG)(!?8 z4BuNc69=5w*oOkf`mI4P_+9y1P25=M8}BFYIGk?=4j3`9c|*xVJ$^so@eX3c`)=?7 zgNMyq2+#fdi}ZbxGgSfKCvPJdeMe3f?{Avv1$TNrjUet|L&58G?}oe0(^PrlRn625J|U)J#Bemz*i+C|F4{(2=~4012fe7c1C z;F1fwS7OdW>2Rh=%z21(IEy53u<9w{BpatR!4{LFcjbU2)gIcG_SvqAy~ z8$UR+G@mVj!+FEu{W@0yhj$GQHhyr3{TK#?LX&3+u$>+{t~u z1pG$DU8Q-o1dR9be#Ka$nelJ=uh!fr0plK{dyi|SQ!i&mZ0^uH2{?CeQ1jy?0}}2J z;u;<=owch~1H6qAxZsX|p>*P#hu;$<;8z6RrhvgWZ?kms=m|D{UcV@;b8lSt6QzUO zXG`#j_qJ6SxN|>AIv8B@o-Cc*@W_pgpZjsK^r`ys6ydB9hr94p331|cds@J+ln>|l zbO{(-^PVByJo01XM}FcyGpzG%@=p3ZhQgZtw#g=K*+=}#= zOC4bN+9wS@e1}zu;}1(`&3-$i6AQn%j-9euyDHR?Ne6>(?xoUWE_Hz6YoA)=bD4D4 zu}eB@_NzyJao-xkS#upD(!t=H`z-0M11@!d;p=c+;;dwWh;pM0M#7tWgBnCD6d z^BePg=?vZ&)}AK;IHwT1dMvoUGM9qlWVDDhQ$4NgLKxM?~T&Iybs4>zE{8f$p0n@`PmEp+fP-mRHIE%>}k z0!A(9K9l!IrxwnHdxcFt*ZN-Rte+~OkNALHE1{=dn%^(!3HI@tKOliajCq@P^*aJF!6()>jU zoRt#tVB^R7t(w0iIV9oy?ozf>G=EtFeu;!T#5wuyd__9(FIU&_{i+0vyF- zh>tHZ!0_YUTceqpm>uJX(usl1_wgf1{C)gb_5leo@%1_XL^{3_vHv82!`Z^&{{2}3XQhN5VB^PKJy-Hy9spjH literal 7833 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 Oz}!pwf9Qp}efuxR__+)K literal 6845 zcmai%`Ja__6~`Z#1rQJn6jGr9Uj_w{ifg3Iz`#IZ42xQ}4A*-fhHIC(w>x)6G)mNV zN+oQM_RVb1R?5sItZcL8Z|RqM^?pCkbB2d$eD&pZUgw<8S-$6czUTSQW!96ICfVwm zeZ`z4nU!3SEKL5HL&-(SY>*_GpY&#YXxF}78^$}e4cA_Gl`a=1U74poi->e}Lx(H% zG37PTE1{jxY3MA}#lP9`=Lza2W@y*Q(C*zsyS9x~Tdk4t&b^Ivq){JBM{4zUTJ6*) zQ~ldmZ&y~(`H-yS#H^>nOL(X_9XrnSMe zTDi9rYhNeRMzdP)2$OM67V9lls@1fSwzJ@}&AyFSD~)tu?0@q0V5>G8&G!EKSO>Y6 z^H_T?)TkfiX3p)w@FX;~Gto|W=H1B8zZsl2J;q z=M&qCQ0iHJWK{ z`dCBSsIpx=QK<{Kc!rD!Rq&oj7RybZBm=&@hu<^9BBKi`q^e(LULe)sq9y7#dTvVZXn zM?Py1n+4g!@KM(%?k9ZgUykK*p0gaMZd}}habnZstiK$mZrr0#)F2jd_BnESu9Mh2 zw{?c@xn1gh_s*qu^PPda?1d{Z?P6s=>lJhV@KYAc``VS|(@(qKn#=lKftgb*zw6x3 z7_qrf_?cVG-$P>Y4T`xuyO^<_&F^tF%v<%xkxO$$)Uw}!5>2Iz@@IGi3w64&diO|it6moy<>dv=oDOs1p#oeR$X*;D~ zrc-ikbHuGcv!0b?yRwk2|K-T$7u!_mYYHrCT8r+|{}piSvv&Q}eWS#*zZz~n_p%39 z!>vzD`!#USFCMjDkIdSM35Y!2hL!_|!&f*U7hocfLeiyrPop9Sgv z`od-|^*0oHf1&S%doJsaJGukeJwm?|*`9~~R%H7Z`T^vgl3qoQ{c6bOx0m5RT42`m zjzadXmZS4uhU`AwPy0QEU3@)Ry=#A@JCn|-6!?9G9=5>WS@P8;ZoZ?Cxs21t`mFmw z$o^T6Z=b!%=OzEWr7j+1ogYQFXD1-QbmK3_{w&&6vN#jS(}ay6>Ub^-PA`{<+-yUm(tlzRrgK_mit%1K(KE{qFp~P}yED={013 zdxzb5YL|59$KTswH~;Zzy1%u{_EUv^Gxhj3t%H1*j-q@1^#yhdr?GbRn~L{l1G0ZJ z#0S89!>)qXKx-jm)b$Jdwa8(2PrrrhAn}Kayf+q@@7W$O@8c#&+!feski}*}!&K|{ zvI){x+og~-*kkcHcJ96KeUNu+tTn0Y7cu*h&Er|@l`*$L#w>=6QP(eGZbvr8nTwb=A{*noW{kRi z5%VTwW1P*1c{8#xcS6Rf>lZO^K{m#@j+nP08{_+EjJkdiGlFc4vmY@PWMd9M#;EIO z%v|_gkTLe&80S5OjHyD#sOx8peg`3AoM~g^hah7{A!F3_i#qN`)^3lyL+|YEkoayY zagG`VChqcH?DGP4)qc3Zw!!svAHP*`=f&Eakozo#mO<|2Ia`o6WBi`gqqcEmW9)0x z)P}wUe<37?}m)K5YiSk-;ZqUTF9EsC8mGm zI)+@%^#HoL7DC6M$n_9%p2eAK=Fk3but6U?0Y!;n7W)^fbS2Dr1w zkUs{Ugq*qPZPfYk!XCb#DEY?u!uONdw1@AfO1|b^28HjZk+sL$_!(sPGKaR9<wg3;9{YR_xm>?}ihVwhtUY|cfE>QoU-tbXy7ut>5_0%jf7$oT=-Q+HuOPdZ zIkZLnUqz1k^|Ag_aPj!AzJ|ORviH{QH~)1=JihsF6qvZnoU+&xib-xey+|GcQEe7CpZRS-)q=vk3kY$Xh|rw1p}r~ diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 961e321a..2858b2af 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -903,6 +903,26 @@ namespace SHADE comp->SetColorTint(val); }); + SHEditorWidgets::DragVec4("Color Decay", {"x", "y", "z", "w"}, + [comp = component]() + { + return comp->GetColorDecay(); + }, + [comp = component](SHVec4 const& val) + { + comp->SetColorDecay(val); + }); + + SHEditorWidgets::DragVec4("Color Tint Range", { "x", "y", "z", "w" }, + [comp = component]() + { + return comp->GetColorTintRange(); + }, + [comp = component](SHVec4 const& val) + { + comp->SetColorTintRange(val); + }); + SHEditorWidgets::DragInt("Texture Index", [comp = component]() diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp index 74eb3727..f7ccc2ed 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp @@ -156,11 +156,45 @@ namespace SHADE cpuEmitterData.colorTint.z = tint.z; } + void SHParticleEmitterComponent::SetColorDecayRGB(SHVec3 const& decay) noexcept + { + cpuEmitterData.colorDecay.x = decay.x; + cpuEmitterData.colorDecay.y = decay.y; + cpuEmitterData.colorDecay.z = decay.z; + } + + void SHParticleEmitterComponent::SetColorDecayAlpha(float alpha) noexcept + { + cpuEmitterData.colorDecay.w = alpha; + } + void SHParticleEmitterComponent::SetColorTintAlpha(float alpha) noexcept { cpuEmitterData.colorTint.w = alpha; } + void SHParticleEmitterComponent::SetColorTintRange(SHVec4 const& tintRange) noexcept + { + cpuEmitterData.colorTintRange = tintRange; + } + + void SHParticleEmitterComponent::SetColorTintRangeRGB(SHVec3 const& tintRange) noexcept + { + cpuEmitterData.colorTintRange.x = tintRange.x; + cpuEmitterData.colorTintRange.y = tintRange.y; + cpuEmitterData.colorTintRange.z = tintRange.z; + } + + void SHParticleEmitterComponent::SetColorTintRangeAlpha(float alpha) noexcept + { + cpuEmitterData.colorTintRange.w = alpha; + } + + void SHParticleEmitterComponent::SetColorDecay(SHVec4 const& decay) noexcept + { + cpuEmitterData.colorDecay = decay; + } + uint32_t SHParticleEmitterComponent::GetEmissionCount(void) const noexcept { return emissionCount; @@ -273,9 +307,39 @@ namespace SHADE return SHVec3 (cpuEmitterData.colorTint.x, cpuEmitterData.colorTint.y, cpuEmitterData.colorTint.z); } + SHVec3 SHParticleEmitterComponent::GetColorDecayRGB(void) const noexcept + { + return SHVec3(cpuEmitterData.colorDecay.x, cpuEmitterData.colorDecay.y, cpuEmitterData.colorDecay.z); + } + + float SHParticleEmitterComponent::GetColorDecayAlpha(void) const noexcept + { + return cpuEmitterData.colorDecay.w; + } + float SHParticleEmitterComponent::GetColorTintAlpha(void) const noexcept { return cpuEmitterData.colorTint.w; } + SHVec4 const& SHParticleEmitterComponent::GetColorTintRange(void) const noexcept + { + return cpuEmitterData.colorTintRange; + } + + SHVec3 SHParticleEmitterComponent::GetColorTintRangeRGB(void) const noexcept + { + return SHVec3(cpuEmitterData.colorTintRange.x, cpuEmitterData.colorTintRange.y, cpuEmitterData.colorTintRange.z); + } + + float SHParticleEmitterComponent::GetColorTintRangeAlpha(void) const noexcept + { + return cpuEmitterData.colorTintRange.w; + } + + SHVec4 const& SHParticleEmitterComponent::GetColorDecay(void) const noexcept + { + return cpuEmitterData.colorDecay; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h index 47791c44..f43ebefb 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h @@ -46,6 +46,12 @@ namespace SHADE //! Color tint to assign to particles SHVec4 colorTint; + //! Color tint range to assign to particles + SHVec4 colorTintRange; + + //! Color decay for particle + SHVec4 colorDecay; + //! Size decay for particles float sizeDecayMult; @@ -77,6 +83,9 @@ namespace SHADE //! Color tinting for particle SHVec4 colorTint; + //! Color tinting for particle + SHVec4 colorDecay; + //! Life of the particle float life; @@ -172,6 +181,13 @@ namespace SHADE void SetColorTint (SHVec4 tint) noexcept; void SetColorTintRGB (SHVec3 tint) noexcept; void SetColorTintAlpha (float alpha) noexcept; + void SetColorTintRange (SHVec4 const& tintRange) noexcept; + void SetColorTintRangeRGB (SHVec3 const& tintRange) noexcept; + void SetColorTintRangeAlpha (float alpha) noexcept; + + void SetColorDecay (SHVec4 const& decay) noexcept; + void SetColorDecayRGB (SHVec3 const& decay) noexcept; + void SetColorDecayAlpha (float alpha) noexcept; uint32_t GetEmissionCount (void) const noexcept; bool GetPassive (void) const noexcept; @@ -194,6 +210,12 @@ namespace SHADE SHVec4 const& GetColorTint (void) const noexcept; SHVec3 GetColorTintRGB (void) const noexcept; float GetColorTintAlpha (void) const noexcept; + SHVec4 const& GetColorTintRange (void) const noexcept; + SHVec3 GetColorTintRangeRGB (void) const noexcept; + float GetColorTintRangeAlpha (void) const noexcept; + SHVec4 const& GetColorDecay (void) const noexcept; + SHVec3 GetColorDecayRGB (void) const noexcept; + float GetColorDecayAlpha (void) const noexcept; /*-----------------------------------------------------------------------*/ /* NON-INTERFACE FUNCTIONS */ diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index de57e45d..a1c185aa 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -520,6 +520,8 @@ namespace YAML static constexpr std::string_view TEXTURE_ASSET_ID_TAG = "Texture Asset ID"; static constexpr std::string_view CUSTOM_UPDATE_SHADER_ASSET_ID_TAG = "Custom Update Shader Asset ID"; static constexpr std::string_view COLOR_TINT_TAG = "Color Tint"; + static constexpr std::string_view COLOR_TINT_RANGE_TAG = "Color Tint Range"; + static constexpr std::string_view COLOR_DECAY_TAG = "Color Decay"; static constexpr std::string_view ACCELERATION_TAG = "Acceleration"; static YAML::Node encode(SHParticleEmitterComponent const& rhs) @@ -541,6 +543,8 @@ namespace YAML node[TEXTURE_ASSET_ID_TAG.data()] = rhs.GetTextureAssetID(); node[CUSTOM_UPDATE_SHADER_ASSET_ID_TAG.data()] = rhs.GetCustomUpdateShaderAssetID(); node[COLOR_TINT_TAG.data()] = rhs.GetColorTint(); + node[COLOR_TINT_RANGE_TAG.data()] = rhs.GetColorTintRange(); + node[COLOR_DECAY_TAG.data()] = rhs.GetColorDecay(); node[ACCELERATION_TAG.data()] = rhs.GetAcceleration(); return node; @@ -591,6 +595,12 @@ namespace YAML if (node[COLOR_TINT_TAG.data()].IsDefined()) rhs.SetColorTint(node[COLOR_TINT_TAG.data()].as()); + if (node[COLOR_TINT_RANGE_TAG.data()].IsDefined()) + rhs.SetColorTintRange(node[COLOR_TINT_RANGE_TAG.data()].as()); + + if (node[COLOR_DECAY_TAG.data()].IsDefined()) + rhs.SetColorDecay(node[COLOR_DECAY_TAG.data()].as()); + if (node[ACCELERATION_TAG.data()].IsDefined()) rhs.SetAcceleration(node[ACCELERATION_TAG.data()].as()); From 4d145bbc43e27007303862a32a22dd9499caf866 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Thu, 30 Mar 2023 19:15:03 +0800 Subject: [PATCH 2/2] Added support for custom VS and FS for particles --- Assets/Scenes/Scene2.shade | 8 +- Assets/Shaders/ParticleRounded_FS.glsl | 27 +++++ Assets/Shaders/ParticleRounded_FS.shshaderb | Bin 0 -> 1513 bytes .../ParticleRounded_FS.shshaderb.shmeta | 3 + Assets/Shaders/ParticleRounded_VS.glsl | 107 ++++++++++++++++++ Assets/Shaders/ParticleRounded_VS.shshaderb | Bin 0 -> 7377 bytes .../ParticleRounded_VS.shshaderb.shmeta | 3 + .../Inspector/SHEditorComponentView.hpp | 82 ++++++++++++++ .../Particles/SHParticleEmitterComponent.cpp | 40 +++++++ .../Particles/SHParticleEmitterComponent.h | 81 ++++++++----- .../Particles/SHParticleSubSystem.cpp | 81 ++++++++++++- .../MiddleEnd/Particles/SHParticleSubSystem.h | 12 +- .../src/Serialization/SHYAMLConverters.h | 29 +++++ 13 files changed, 436 insertions(+), 37 deletions(-) create mode 100644 Assets/Shaders/ParticleRounded_FS.glsl create mode 100644 Assets/Shaders/ParticleRounded_FS.shshaderb create mode 100644 Assets/Shaders/ParticleRounded_FS.shshaderb.shmeta create mode 100644 Assets/Shaders/ParticleRounded_VS.glsl create mode 100644 Assets/Shaders/ParticleRounded_VS.shshaderb create mode 100644 Assets/Shaders/ParticleRounded_VS.shshaderb.shmeta diff --git a/Assets/Scenes/Scene2.shade b/Assets/Scenes/Scene2.shade index 6e794990..4f925833 100644 --- a/Assets/Scenes/Scene2.shade +++ b/Assets/Scenes/Scene2.shade @@ -172,10 +172,12 @@ Rotation Speed: 0.0309999995 Rotation Decay: 0.0199999996 Texture Asset ID: 0 + Custom Vertex Shader Asset ID: 44202416 + Custom Fragment Shader Asset ID: 42315398 Custom Update Shader Asset ID: 0 - Color Tint: {x: 0, y: 1, z: 0.56387639, w: 1} - Color Tint Range: {x: 0.5, y: 0.5, z: 0.5, w: 0} - Color Decay: {x: 0, y: 0, z: 0, w: 0} + Color Tint: {x: 0.46696043, y: 1, z: 0, w: 1} + Color Tint Range: {x: 1, y: 0, z: 0, w: 0} + Color Decay: {x: -1, y: -1, z: -1, w: 0} Acceleration: {x: 0, y: 0, z: 0} IsActive: true Scripts: ~ \ No newline at end of file diff --git a/Assets/Shaders/ParticleRounded_FS.glsl b/Assets/Shaders/ParticleRounded_FS.glsl new file mode 100644 index 00000000..6de4dc8b --- /dev/null +++ b/Assets/Shaders/ParticleRounded_FS.glsl @@ -0,0 +1,27 @@ +#version 460 core +#extension GL_EXT_nonuniform_qualifier : require + +layout (location = 0) out vec4 fragColor; + +layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global) + +// between shader stages +layout(location = 0) in struct +{ + vec2 uv; // location = 0 +} In; + +// material stuff +layout(location = 1) flat in struct +{ + uint textureIndex; + vec4 color; +} InFlat; + +void main () +{ + fragColor = vec4 (texture(textures [nonuniformEXT(InFlat.textureIndex)], In.uv)) * InFlat.color; + + if (fragColor.a < 0.01f) + discard; +} diff --git a/Assets/Shaders/ParticleRounded_FS.shshaderb b/Assets/Shaders/ParticleRounded_FS.shshaderb new file mode 100644 index 0000000000000000000000000000000000000000..59049d0c1cc9d068cc27942f802b250d3523f06c GIT binary patch literal 1513 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 literal 0 HcmV?d00001 diff --git a/Assets/Shaders/ParticleRounded_VS.shshaderb.shmeta b/Assets/Shaders/ParticleRounded_VS.shshaderb.shmeta new file mode 100644 index 00000000..68577bd3 --- /dev/null +++ b/Assets/Shaders/ParticleRounded_VS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: ParticleRounded_VS +ID: 44202416 +Type: 2 diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 2858b2af..7bb5c552 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -1004,6 +1004,88 @@ namespace SHADE } + SHEditorWidgets::InputText("Custom Vertex Shader", + [comp = component]() + { + auto customShader = comp->GetCustomVertexShader(); + + if (customShader) + return customShader->GetName(); + else + return std::string{}; + + }, + [comp = component](std::string const& text) + { + }, {}, ImGuiSliderFlags_ReadOnly); + + if (SHDragDrop::BeginTarget()) + { + if (AssetID* payload = SHDragDrop::AcceptPayload(SHDragDrop::DRAG_RESOURCE)) + { + Handle shaderModule = SHResourceManager::LoadOrGet(*payload); + + if (shaderModule) + { + component->SetCustomVertexShader(shaderModule); + component->SetCustomVertexShaderAssetID(*payload); + } + else + { + SHLOG_WARNING("[] Attempted to load invalid shader! Custom vertex shader for particles not set. "); + } + + SHDragDrop::EndTarget(); + } + } + ImGui::SameLine(); + if (ImGui::Button("Reset")) + { + component->SetCustomVertexShader({}); + component->SetCustomVertexShaderAssetID(INVALID_ASSET_ID); + } + + + SHEditorWidgets::InputText("Custom Fragment Shader", + [comp = component]() + { + auto customShader = comp->GetCustomFragmentShader(); + + if (customShader) + return customShader->GetName(); + else + return std::string{}; + + }, + [comp = component](std::string const& text) + { + }, {}, ImGuiSliderFlags_ReadOnly); + + if (SHDragDrop::BeginTarget()) + { + if (AssetID* payload = SHDragDrop::AcceptPayload(SHDragDrop::DRAG_RESOURCE)) + { + Handle shaderModule = SHResourceManager::LoadOrGet(*payload); + + if (shaderModule) + { + component->SetCustomFragmentShader(shaderModule); + component->SetCustomFragmentShaderAssetID(*payload); + } + else + { + SHLOG_WARNING("[] Attempted to load invalid shader! Custom fragment shader for particles not set. "); + } + + SHDragDrop::EndTarget(); + } + } + ImGui::SameLine(); + if (ImGui::Button("Reset")) + { + component->SetCustomFragmentShader({}); + component->SetCustomFragmentShaderAssetID(INVALID_ASSET_ID); + } SHEditorWidgets::CheckBox("Is Passive", [comp = component]() {return comp->GetPassive(); }, [comp = component](bool flag) {comp->SetPassive(flag); }); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp index f7ccc2ed..392e18a5 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp @@ -124,6 +124,16 @@ namespace SHADE customUpdateShaderID = id; } + void SHParticleEmitterComponent::SetCustomVertexShaderAssetID(AssetID id) noexcept + { + customVertexShaderID = id; + } + + void SHParticleEmitterComponent::SetCustomFragmentShaderAssetID(AssetID id) noexcept + { + customFragmentShaderID = id; + } + void SHParticleEmitterComponent::SetMinSize(float size) noexcept { cpuEmitterData.lifeAndSizeRange.z = size; @@ -139,6 +149,16 @@ namespace SHADE cpuEmitterData.sizeDecayMult = decay; } + void SHParticleEmitterComponent::SetCustomVertexShader(Handle shaderModule) noexcept + { + customVertexShader = shaderModule; + } + + void SHParticleEmitterComponent::SetCustomFragmentShader(Handle shaderModule) noexcept + { + customFragmentShader = shaderModule; + } + void SHParticleEmitterComponent::SetCustomUpdateShader(Handle shaderModule) noexcept { customUpdateShader = shaderModule; @@ -276,6 +296,16 @@ namespace SHADE return customUpdateShaderID; } + AssetID SHParticleEmitterComponent::GetCustomVertexShaderAssetID(void) const noexcept + { + return customVertexShaderID; + } + + AssetID SHParticleEmitterComponent::GetCustomFragmentShaderAssetID(void) const noexcept + { + return customFragmentShaderID; + } + float SHParticleEmitterComponent::GetMinSize(void) const noexcept { return cpuEmitterData.lifeAndSizeRange.z; @@ -297,6 +327,16 @@ namespace SHADE return customUpdateShader; } + Handle SHParticleEmitterComponent::GetCustomVertexShader(void) const noexcept + { + return customVertexShader; + } + + Handle SHParticleEmitterComponent::GetCustomFragmentShader(void) const noexcept + { + return customFragmentShader; + } + SHVec4 const& SHParticleEmitterComponent::GetColorTint(void) const noexcept { return cpuEmitterData.colorTint; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h index f43ebefb..d32ac2fc 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h @@ -115,7 +115,7 @@ namespace SHADE Handle particleData; //! Freelist data - Handle freelistData; + Handle freelistData; //! Indices data Handle indicesData; @@ -133,6 +133,16 @@ namespace SHADE //! Internally the system will bind this pipeline when it detects that this is not a null handle Handle customUpdatePipeline; + //! Custom vertex shader + Handle customVertexShader; + + //! Custom fragment shader + Handle customFragmentShader; + + //! Custom graphics pipeline for drawing particles (created + //! from the VS and FS above). + Handle customGraphicsPipeline; + //! Emitter's data on the CPU side. To be copied to GPU. GPUEmitterStruct cpuEmitterData; @@ -154,6 +164,12 @@ namespace SHADE //! Custom update shaders, similarly with textures, will be identified through their AssetID AssetID customUpdateShaderID; + //! Custom vertex shaders, similarly with textures, will be identified through their AssetID + AssetID customVertexShaderID; + + //! Custom fragment shaders, similarly with textures, will be identified through their AssetID + AssetID customFragmentShaderID; + public: void OnCreate(void) override final; void OnDestroy(void) override final; @@ -177,6 +193,8 @@ namespace SHADE void SetMinSize (float size) noexcept; void SetMaxSize (float size) noexcept; void SetSizeDecayMult (float decay) noexcept; + void SetCustomVertexShader (Handle shaderModule) noexcept; + void SetCustomFragmentShader (Handle shaderModule) noexcept; void SetCustomUpdateShader (Handle shaderModule) noexcept; void SetColorTint (SHVec4 tint) noexcept; void SetColorTintRGB (SHVec3 tint) noexcept; @@ -189,42 +207,49 @@ namespace SHADE void SetColorDecayRGB (SHVec3 const& decay) noexcept; void SetColorDecayAlpha (float alpha) noexcept; - uint32_t GetEmissionCount (void) const noexcept; - bool GetPassive (void) const noexcept; - float GetEmissionInterval (void) const noexcept; - float GetMinLife (void) const noexcept; - float GetMaxLife (void) const noexcept; - SHVec4 const& GetAngularRangesAndOffsets (void) const noexcept; - SHVec2 GetAngularRanges (void) const noexcept; - SHVec2 GetAngularOffsets (void) const noexcept; - SHVec3 GetAcceleration (void) const noexcept; - float GetMinSpeed (void) const noexcept; - float GetMaxSpeed (void) const noexcept; - float GetRotationSpeed (void) const noexcept; - float GetRotationDecay (void) const noexcept; - uint32_t GetTextureIndex (void) const noexcept; - float GetMinSize (void) const noexcept; - float GetMaxSize (void) const noexcept; - float GetSizeDecayMult (void) const noexcept; - Handle GetCustomUpdateShader (void) const noexcept; - SHVec4 const& GetColorTint (void) const noexcept; - SHVec3 GetColorTintRGB (void) const noexcept; - float GetColorTintAlpha (void) const noexcept; - SHVec4 const& GetColorTintRange (void) const noexcept; - SHVec3 GetColorTintRangeRGB (void) const noexcept; - float GetColorTintRangeAlpha (void) const noexcept; - SHVec4 const& GetColorDecay (void) const noexcept; - SHVec3 GetColorDecayRGB (void) const noexcept; - float GetColorDecayAlpha (void) const noexcept; + uint32_t GetEmissionCount (void) const noexcept; + bool GetPassive (void) const noexcept; + float GetEmissionInterval (void) const noexcept; + float GetMinLife (void) const noexcept; + float GetMaxLife (void) const noexcept; + SHVec4 const& GetAngularRangesAndOffsets (void) const noexcept; + SHVec2 GetAngularRanges (void) const noexcept; + SHVec2 GetAngularOffsets (void) const noexcept; + SHVec3 GetAcceleration (void) const noexcept; + float GetMinSpeed (void) const noexcept; + float GetMaxSpeed (void) const noexcept; + float GetRotationSpeed (void) const noexcept; + float GetRotationDecay (void) const noexcept; + uint32_t GetTextureIndex (void) const noexcept; + float GetMinSize (void) const noexcept; + float GetMaxSize (void) const noexcept; + float GetSizeDecayMult (void) const noexcept; + Handle GetCustomUpdateShader (void) const noexcept; + Handle GetCustomVertexShader (void) const noexcept; + Handle GetCustomFragmentShader (void) const noexcept; + SHVec4 const& GetColorTint (void) const noexcept; + SHVec3 GetColorTintRGB (void) const noexcept; + float GetColorTintAlpha (void) const noexcept; + SHVec4 const& GetColorTintRange (void) const noexcept; + SHVec3 GetColorTintRangeRGB (void) const noexcept; + float GetColorTintRangeAlpha (void) const noexcept; + SHVec4 const& GetColorDecay (void) const noexcept; + SHVec3 GetColorDecayRGB (void) const noexcept; + float GetColorDecayAlpha (void) const noexcept; /*-----------------------------------------------------------------------*/ /* NON-INTERFACE FUNCTIONS */ /*-----------------------------------------------------------------------*/ void SetTextureAssetID(AssetID id) noexcept; void SetCustomUpdateShaderAssetID(AssetID id) noexcept; + void SetCustomVertexShaderAssetID(AssetID id) noexcept; + void SetCustomFragmentShaderAssetID (AssetID id) noexcept; AssetID GetTextureAssetID(void) const noexcept; AssetID GetCustomUpdateShaderAssetID(void) const noexcept; + AssetID GetCustomVertexShaderAssetID(void) const noexcept; + AssetID GetCustomFragmentShaderAssetID(void) const noexcept; + friend class SHParticleSubSystem; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp index d99832a5..92405264 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp @@ -268,10 +268,73 @@ namespace SHADE return customUpdatePipelineCache.at (customUpdateShader).customPipeline; } - void SHParticleSubSystem::Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle subpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept + Handle SHParticleSubSystem::GetCustomGraphicsPipeline(Handle customVS, Handle customFS) noexcept + { + if (!customVS || !customFS) + return {}; + + if (!customGraphicsPipelineCache.contains(std::make_pair(customVS, customFS))) + { + SHPipelineLayoutParams plParams + { + .shaderModules = {customVS, customFS}, + .predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::PARTICLE_RENEDERING).descSetLayouts + }; + + auto pipelineLayout = logicalDevice->CreatePipelineLayout(plParams); + auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass); + + SHColorBlendState colorBlendState{}; + colorBlendState.logic_op_enable = VK_FALSE; + colorBlendState.logic_op = vk::LogicOp::eCopy; + + auto const& subpassColorReferences = subpass->GetColorAttachmentReferences(); + colorBlendState.attachments.reserve(subpassColorReferences.size()); + + + for (auto& att : subpassColorReferences) + { + colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState + { + .blendEnable = SHVkUtil::IsBlendCompatible(subpass->GetFormatFromAttachmentReference(att.attachment)), + .srcColorBlendFactor = vk::BlendFactor::eSrcAlpha, + .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, + .colorBlendOp = vk::BlendOp::eAdd, + .srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha, + .dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, + .alphaBlendOp = vk::BlendOp::eAdd, + .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, + } + ); + } + + newPipeline->GetPipelineState().SetColorBlenState(colorBlendState); + + // Sets the input assembly state for rendering particles + SHInputAssemblyState inputAssemblyState{}; + inputAssemblyState.topology = vk::PrimitiveTopology::eTriangleFan; + newPipeline->GetPipelineState().SetInputAssemblyState(inputAssemblyState); + + newPipeline->ConstructPipeline(); + + if (!newPipeline) + return {}; + + auto customUpdateShaderData = CustomPipeline{ newPipeline, pipelineLayout }; + + customGraphicsPipelineCache.emplace(std::make_pair(customVS, customFS), customUpdateShaderData); + } + + return customGraphicsPipelineCache.at(std::make_pair(customVS, customFS)).customPipeline; + + } + + void SHParticleSubSystem::Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle compatibleSubpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept { descPool = inDescPool; logicalDevice = device; + renderpass = compatibleRenderpass; + subpass = compatibleSubpass; /*-----------------------------------------------------------------------*/ /* INITIALIZE ALL PIPELINES */ @@ -499,12 +562,22 @@ namespace SHADE auto& emitters = SHComponentManager::GetDense(); auto const& mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::PARTICLE_RENEDERING); - // bind the pipeline for updating - cmdBuffer->BindPipeline(renderingPipelineData.pipeline); - // TODO: Issue barrier for output particle data. Semaphore should also be issued outside in SHGraphicsSystem for (auto& emitter : emitters) { + if (emitter.customVertexShader && emitter.customFragmentShader) + { + if (!emitter.customGraphicsPipeline) + emitter.customGraphicsPipeline = GetCustomGraphicsPipeline(emitter.customVertexShader, emitter.customFragmentShader); + + cmdBuffer->BindPipeline(emitter.customGraphicsPipeline); + } + else + { + // bind the pipeline for updating + cmdBuffer->BindPipeline(renderingPipelineData.pipeline); + } + if (emitter.isActive) { // bind the descriptor sets required for emitting particles diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h index a0675da6..2288a5bb 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h @@ -82,7 +82,14 @@ namespace SHADE //! Desc pool for particle component desc set allocation Handle descPool; + //! Renderpass the system draws its particles in + Handle renderpass; + + //! Subpass the system draws its particles in + Handle subpass; + std::unordered_map, CustomPipeline> customUpdatePipelineCache; + std::unordered_map, Handle>, CustomPipeline> customGraphicsPipelineCache; void InitializeComponent (SHParticleEmitterComponent& comp) noexcept; @@ -92,10 +99,11 @@ namespace SHADE void PreparePrePostUpdateBarriers (std::vector& preUpdateBarriers, std::vector& postUpdateBarriers, SHParticleEmitterComponent const& emitter, uint32_t const EMITTER_INDEX, uint32_t const FRAME_INDEX) noexcept; - Handle GetCustomUpdatePipeline (Handle customUpdateShader) noexcept; + Handle GetCustomUpdatePipeline(Handle customUpdateShader) noexcept; + Handle GetCustomGraphicsPipeline(Handle customVS, Handle customFS) noexcept; public: - void Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle subpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept; + void Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle compatibleSubpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept; void Run(Handle cmdBuffer, uint32_t frameIndex, Handle waitFence = {}) noexcept; void ResetInstanceCounts (Handle cmdBuffer, uint32_t frameIndex) noexcept; diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index a1c185aa..0df15b5b 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -518,6 +518,8 @@ namespace YAML static constexpr std::string_view ROTATION_SPEED_TAG = "Rotation Speed"; static constexpr std::string_view ROTATION_DECAY_TAG = "Rotation Decay"; static constexpr std::string_view TEXTURE_ASSET_ID_TAG = "Texture Asset ID"; + static constexpr std::string_view CUSTOM_VERTEX_SHADER_ASSET_ID_TAG = "Custom Vertex Shader Asset ID"; + static constexpr std::string_view CUSTOM_FRAGMENT_SHADER_ASSET_ID_TAG = "Custom Fragment Shader Asset ID"; static constexpr std::string_view CUSTOM_UPDATE_SHADER_ASSET_ID_TAG = "Custom Update Shader Asset ID"; static constexpr std::string_view COLOR_TINT_TAG = "Color Tint"; static constexpr std::string_view COLOR_TINT_RANGE_TAG = "Color Tint Range"; @@ -541,6 +543,8 @@ namespace YAML node[ROTATION_SPEED_TAG.data()] = rhs.GetRotationSpeed(); node[ROTATION_DECAY_TAG.data()] = rhs.GetRotationDecay(); node[TEXTURE_ASSET_ID_TAG.data()] = rhs.GetTextureAssetID(); + node[CUSTOM_VERTEX_SHADER_ASSET_ID_TAG.data()] = rhs.GetCustomVertexShaderAssetID(); + node[CUSTOM_FRAGMENT_SHADER_ASSET_ID_TAG.data()] = rhs.GetCustomFragmentShaderAssetID(); node[CUSTOM_UPDATE_SHADER_ASSET_ID_TAG.data()] = rhs.GetCustomUpdateShaderAssetID(); node[COLOR_TINT_TAG.data()] = rhs.GetColorTint(); node[COLOR_TINT_RANGE_TAG.data()] = rhs.GetColorTintRange(); @@ -634,6 +638,31 @@ namespace YAML rhs.SetCustomUpdateShader(shaderModule); rhs.SetCustomUpdateShaderAssetID(id); } + + if (node[CUSTOM_VERTEX_SHADER_ASSET_ID_TAG.data()].IsDefined()) + { + AssetID id = node[CUSTOM_VERTEX_SHADER_ASSET_ID_TAG.data()].as(); + + Handle shaderModule = SHResourceManager::LoadOrGet(id); + SHResourceManager::FinaliseChanges(); + //gfxSystem->BuildTextures(); + + rhs.SetCustomVertexShader(shaderModule); + rhs.SetCustomVertexShaderAssetID(id); + } + + if (node[CUSTOM_FRAGMENT_SHADER_ASSET_ID_TAG.data()].IsDefined()) + { + AssetID id = node[CUSTOM_FRAGMENT_SHADER_ASSET_ID_TAG.data()].as(); + + Handle shaderModule = SHResourceManager::LoadOrGet(id); + SHResourceManager::FinaliseChanges(); + //gfxSystem->BuildTextures(); + + rhs.SetCustomFragmentShader(shaderModule); + rhs.SetCustomFragmentShaderAssetID(id); + } + return true; }