ZibraLiquid.cs 189 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547
  1. using com.zibra.liquid.DataStructures;
  2. using com.zibra.liquid.Manipulators;
  3. using com.zibra.common.Utilities;
  4. using com.zibra.liquid.Bridge;
  5. #if UNITY_EDITOR
  6. using com.zibra.liquid.Analytics;
  7. using com.zibra.common.PresetAnalytics;
  8. #endif
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Collections.ObjectModel;
  12. using System.Runtime.InteropServices;
  13. using UnityEngine;
  14. using UnityEngine.Experimental.Rendering;
  15. using UnityEngine.Rendering;
  16. using UnityEngine.Serialization;
  17. using com.zibra.common.SDFObjects;
  18. using com.zibra.common.Solver;
  19. #if UNITY_EDITOR
  20. using com.zibra.common.Editor.SDFObjects;
  21. using com.zibra.common.Editor;
  22. #endif
  23. #if UNITY_PIPELINE_HDRP
  24. using UnityEngine.Rendering.HighDefinition;
  25. #endif // UNITY_PIPELINE_HDRP
  26. namespace com.zibra.liquid.Solver
  27. {
  28. /// <summary>
  29. /// Main ZibraLiquid component.
  30. /// </summary>
  31. /// <remarks>
  32. /// <para>
  33. /// Each ZibraLiquid component corresponds to one instance of simulation.
  34. /// Different instances of simulation can't interact with each other.
  35. /// </para>
  36. /// <para>
  37. /// Some parameters can't be changed after simulation has started and we created GPU buffers.
  38. /// Normally, simulation starts in playmode in OnEnable and stops in OnDisable.
  39. /// To change those parameters in runtime you want to have this component disabled,
  40. /// and after setting them, enable this component.
  41. /// </para>
  42. /// <para>
  43. /// Liquid may run in the edit mode, specifically when you use initial state baking.
  44. /// In that case, you can't modify some parameters in edit mode too.
  45. /// </para>
  46. /// <para>
  47. /// OnEnable will allocate GPU buffers, which may cause stuttering.
  48. /// Consider enabling liquid on level load, but with simulation/render paused,
  49. /// to not pay the cost of liquid initialization during gameplay.
  50. /// </para>
  51. /// <para>
  52. /// Disabling liquid will free GPU buffers.
  53. /// This means that liquid state will be lost.
  54. /// </para>
  55. /// <para>
  56. /// Various parameters of the liquid are spread throught multiple components.
  57. /// This is done so you can use Unity's Preset system to only change part of parameters.
  58. /// </para>
  59. /// </remarks>
  60. [AddComponentMenu("Zibra Effects - Liquid/Zibra Liquid")]
  61. [DisallowMultipleComponent]
  62. [RequireComponent(typeof(ZibraLiquidMaterialParameters))]
  63. [RequireComponent(typeof(ZibraLiquidSolverParameters))]
  64. [RequireComponent(typeof(ZibraLiquidAdvancedRenderParameters))]
  65. [RequireComponent(typeof(ZibraManipulatorManager))]
  66. [ExecuteInEditMode]
  67. public class ZibraLiquid : MonoBehaviour, StatReporter
  68. {
  69. #region Public Interface
  70. #region Properties
  71. /// <summary>
  72. /// A list of all enabled instances of this component.
  73. /// </summary>
  74. public static List<ZibraLiquid> AllFluids = new List<ZibraLiquid>();
  75. /// <summary>
  76. /// Header of initial state baked in the Paid version.
  77. /// </summary>
  78. /// <remarks>
  79. /// <para>
  80. /// Use <see cref="IsValidBakedLiquidHeader"/> instead,
  81. /// unless you need to check which version baked this state.
  82. /// </para>
  83. /// <para>
  84. /// You can compare this to first int in .bytes file,
  85. /// to check whether it is baked liquid state saved specifically by the Paid version.
  86. /// </para>
  87. /// <para>
  88. /// Baked states are compatible across versions,
  89. /// But state baked in the Pro version also contains data about particle species,
  90. /// So state from the Pro version has different format and a little bit larger.
  91. /// </para>
  92. /// </remarks>
  93. public const int BAKED_LIQUID_PAID_HEADER_VALUE = 0x071B9AA1;
  94. /// <summary>
  95. /// Header of initial state baked in the Pro version.
  96. /// </summary>
  97. /// <remarks>
  98. /// <para>
  99. /// Use <see cref="IsValidBakedLiquidHeader"/> instead,
  100. /// unless you need to check which version baked this state.
  101. /// </para>
  102. /// <para>
  103. /// You can compare this to first int in .bytes file,
  104. /// to check whether it is baked liquid state saved specifically by the Pro version.
  105. /// </para>
  106. /// <para>
  107. /// Baked states are compatible across versions,
  108. /// But state baked in the Pro version also contains data about particle species,
  109. /// So state from the Pro version has different format and a little bit larger.
  110. /// </para>
  111. /// </remarks>
  112. public const int BAKED_LIQUID_PRO_HEADER_VALUE = 0x171B9AA1;
  113. /// <summary>
  114. /// Default speed of liquid simulation.
  115. /// </summary>
  116. /// <remarks>
  117. /// The defualt value of speed of liquid simulation that defines
  118. /// relation between simulation time units and seconds.
  119. /// </remarks>
  120. public const float DEFAULT_SIMULATION_TIME_SCALE = 40.0f;
  121. /// <summary>
  122. /// Checks whether passed int is a valid header for baked liquid state.
  123. /// </summary>
  124. /// <remarks>
  125. /// To use it, read first int from the .bytes file and pass it to this function.
  126. /// </remarks>
  127. public bool IsValidBakedLiquidHeader(int header)
  128. {
  129. return header == BAKED_LIQUID_PAID_HEADER_VALUE || header == BAKED_LIQUID_PRO_HEADER_VALUE;
  130. }
  131. #if UNITY_EDITOR
  132. /// <summary>
  133. /// (Editor only) Event that is triggered when state of manipulator changes
  134. /// to trigger update of custom editor.
  135. /// </summary>
  136. /// <remarks>
  137. /// This is only intended to update custom editors,
  138. /// You can trigger it when you change some state to update custom editor.
  139. /// But using it for anything else is a bad idea.
  140. /// </remarks>
  141. public event Action OnChanged;
  142. /// <summary>
  143. /// (Editor only) Triggers custom editor update.
  144. /// </summary>
  145. /// <remarks>
  146. /// Just triggers <see cref="OnChanged"/>.
  147. /// </remarks>
  148. public void NotifyChange()
  149. {
  150. if (OnChanged != null)
  151. {
  152. OnChanged.Invoke();
  153. }
  154. }
  155. #endif
  156. /// <summary>
  157. /// Render target containing rendered mesh.
  158. /// </summary>
  159. /// <remarks>
  160. /// <para>
  161. /// This is RGBA float render target.
  162. /// Format during Mesh Render pass:
  163. /// * xyz - World position
  164. /// * w - Encoded surface normal
  165. ///
  166. /// Format during Visualse SDF pass:
  167. /// * xyz - Normal
  168. /// * w - Depth
  169. /// </para>
  170. /// <para>
  171. /// When Visualize SDF is enabled, it will execute after Mesh Render pass,
  172. /// and so it will overwrite rendered liquid.
  173. /// </para>
  174. /// <para>
  175. /// Only used in Mesh Render mode or Visualize SDF pass.
  176. /// </para>
  177. /// </remarks>
  178. [NonSerialized]
  179. public RenderTexture Color0;
  180. /// <summary>
  181. /// Render target containing raymarched data.
  182. /// </summary>
  183. /// <remarks>
  184. /// <para>
  185. /// This is RGBA float render target.
  186. /// Format:
  187. /// * x - Depth of first light bounce traveling inside liquid
  188. /// * y - Depth of first light bounce traveling outside liquid (if any)
  189. /// * z - Depth of second light bounce traveling inside liquid (if any)
  190. /// * w - 0
  191. ///
  192. /// calculation of yz components require RefractionBounces
  193. /// in ZibraLiquidAdvancedRenderParameters to be set to TwoBounces.
  194. /// </para>
  195. /// <para>
  196. /// Unused if DisableRaymarch in ZibraLiquidAdvancedRenderParameters is enabled.
  197. /// </para>
  198. /// <para>
  199. /// Only used in Mesh Render mode.
  200. /// </para>
  201. /// </remarks>
  202. [NonSerialized]
  203. public RenderTexture Color1;
  204. /// <summary>
  205. /// Render target containing raymarched data.
  206. /// </summary>
  207. /// <remarks>
  208. /// <para>
  209. /// This is RGBA float render target.
  210. /// Format:
  211. /// * xyz - Concentrations of Material1/2/3 respectively.
  212. /// * w - 0
  213. /// </para>
  214. /// <para>
  215. /// Unused if DisableRaymarch in ZibraLiquidAdvancedRenderParameters is enabled.
  216. /// </para>
  217. /// <para>
  218. /// Only used in Mesh Render mode.
  219. /// </para>
  220. /// <para>
  221. /// Texture exists in non Pro versions too for technical reasons,
  222. /// but has no functionality in non Pro versions.
  223. /// </para>
  224. /// </remarks>
  225. [NonSerialized]
  226. public RenderTexture Color2;
  227. /// <summary>
  228. /// Render target containing rendered liquid when using downscale.
  229. /// </summary>
  230. /// <remarks>
  231. /// <para>
  232. /// This is RGBA float render target.
  233. /// Format:
  234. /// * xyz - Rendered liquid
  235. /// * w - 1.0 in pixels with liquid, and 0 othewise
  236. /// </para>
  237. /// <para>
  238. /// Only used when <see cref="EnableDownscale"/> is enabled.
  239. /// </para>
  240. /// <para>
  241. /// Only used in Mesh Render mode.
  242. /// </para>
  243. /// </remarks>
  244. [NonSerialized]
  245. public RenderTexture UpscaleColor;
  246. /// <summary>
  247. /// Render target containing liquid depth when using downscale.
  248. /// </summary>
  249. /// <remarks>
  250. /// <para>
  251. /// Only used when <see cref="EnableDownscale"/> is enabled.
  252. /// </para>
  253. /// <para>
  254. /// Only used in Mesh Render mode.
  255. /// </para>
  256. /// </remarks>
  257. [NonSerialized]
  258. public RenderTexture UpscaleDepth;
  259. /// <summary>
  260. /// Depth buffer containing liquid depth.
  261. /// </summary>
  262. /// <remarks>
  263. /// <para>
  264. /// This is depth buffer.
  265. /// Format:
  266. /// * r - rendered liquid mesh depth.
  267. /// </para>
  268. /// <para>
  269. /// Only used in Mesh Render mode.
  270. /// </para>
  271. /// </remarks>
  272. [NonSerialized]
  273. public RenderTexture Depth;
  274. /// <summary>
  275. /// Render target containing rendered foam particles.
  276. /// </summary>
  277. /// <remarks>
  278. /// <para>
  279. /// Only used in Mesh Render mode.
  280. /// </para>
  281. /// <para>
  282. /// This is RGBA float render target.
  283. /// Format:
  284. /// * rgba - foam color.
  285. /// </para>
  286. /// <para>
  287. /// Current version only supports monochrome foam
  288. /// but in future update we'll use all 4 color components
  289. /// </para>
  290. /// </remarks>
  291. [NonSerialized]
  292. public RenderTexture ParticlesRT;
  293. /// <summary>
  294. /// Buffer containing generated mesh counters.
  295. /// </summary>
  296. /// <remarks>
  297. /// This is an int buffer.
  298. /// Counters[0] = Number of quads.
  299. /// Counters[1] = Number of vertices.
  300. /// </remarks>
  301. [NonSerialized]
  302. public ComputeBuffer Counters;
  303. /// <summary>
  304. /// Buffer containing indices of vertices corresponding to grid nodes.
  305. /// </summary>
  306. /// <remarks>
  307. /// This is an int buffer.
  308. /// VertexIDGrid[nodeID] = Index of vertex corresponding to grid node with id nodeID
  309. /// </remarks>
  310. [NonSerialized]
  311. public ComputeBuffer VertexIDGrid;
  312. /// <summary>
  313. /// Buffer containing indices of vertices corresponding to grid nodes.
  314. /// </summary>
  315. /// <remarks>
  316. /// This is an uint buffer.
  317. /// VertexIDGrid[3 * vertexID + 0/1/2] = X/Y/Z coordinate
  318. /// of vertex in simulation space encoded with <c>asuint</c>.
  319. /// </remarks>
  320. [NonSerialized]
  321. public GraphicsBuffer VertexBuffer0;
  322. /// <summary>
  323. /// Temporary buffer for internal calculations.
  324. /// </summary>
  325. /// <remarks>
  326. /// <para>
  327. /// Has same structure as <see cref="VertexBuffer0"/>,
  328. /// but only contains intermediate data.
  329. /// </para>
  330. /// <para>
  331. /// You can safely reuse it for your needs, to save VRAM,
  332. /// but it'll get overwritten during liquid mesh generation.
  333. /// </para>
  334. /// </remarks>
  335. [NonSerialized]
  336. public GraphicsBuffer VertexBuffer1;
  337. [NonSerialized]
  338. /// <summary>
  339. /// Buffer containing information about liquid mesh quads.
  340. /// </summary>
  341. /// <remarks>
  342. /// This is an uint buffer.
  343. /// Each element contains encoded data about single quad.
  344. /// Data encoded as follows:
  345. /// Leas significant 29 bits - ID of grid node corresponding to quad.
  346. /// Next 2 bits - ID of axis of quad
  347. /// Next 1 bit - direction of quad, 1 = positive direction, 0 = negative direction
  348. /// </remarks>
  349. public ComputeBuffer QuadBuffer;
  350. /// <summary>
  351. /// Temporary buffer for internal calculations.
  352. /// </summary>
  353. /// <remarks>
  354. /// Used as intermediate to write to buffers that cannot normally be written from GPU.
  355. /// </remarks>
  356. [NonSerialized]
  357. public ComputeBuffer TransferDataBuffer;
  358. /// <summary>
  359. /// Index buffer of liquid mesh.
  360. /// </summary>
  361. /// <remarks>
  362. /// Also, used as intermediate, to copy data to Unity's mesh.
  363. /// But not used exclusively in Unire Render mode.
  364. /// </remarks>
  365. [NonSerialized]
  366. public GraphicsBuffer MeshRenderIndexBuffer;
  367. /// <summary>
  368. /// Buffer containing vertex data of liquid mesh.
  369. /// </summary>
  370. /// <remarks>
  371. /// <para>
  372. /// Used as intermediate, to copy data to Unity's mesh.
  373. /// </para>
  374. /// <para>
  375. /// This is an uint buffer.
  376. /// Format:
  377. /// * VertexProperties[6 * VertexID + 0/1/2] = X/Y/Z coordinate in local space,
  378. /// encoded with <c>asuint</c>
  379. /// * VertexProperties[6 * VertexID + 3/4/5] = X/Y/Z normal encoded with <c>asuint</c>
  380. /// </para>
  381. /// <para>
  382. /// Only used in Unity Render mode.
  383. /// </para>
  384. /// </remarks>
  385. [NonSerialized]
  386. public GraphicsBuffer VertexProperties;
  387. /// <summary>
  388. /// Mesh used for rendering in case Unity Render mode is used.
  389. /// </summary>
  390. [NonSerialized]
  391. public Mesh LiquidMesh;
  392. /// <summary>
  393. /// 2D texture containing all heightmaps.
  394. /// </summary>
  395. /// <remarks>
  396. /// This is a float 2d texture. Each texel corresponds to a height value.
  397. /// Format:
  398. /// * x - Height
  399. /// </remarks>
  400. [NonSerialized]
  401. public RenderTexture HeightmapTexture;
  402. /// <summary>
  403. /// 3D texture containing liquid normals.
  404. /// </summary>
  405. /// <remarks>
  406. /// This is a float 3d texture. Each texel corresponds to grid node.
  407. /// Format:
  408. /// * xyz - Normal
  409. /// * w - Blurred liquid density
  410. /// </remarks>
  411. [NonSerialized]
  412. public RenderTexture GridNormalTexture;
  413. /// <summary>
  414. /// 3D texture containing liquid normals.
  415. /// </summary>
  416. /// <remarks>
  417. /// This is a float 3d texture. Each texel corresponds to grid node.
  418. /// Format:
  419. /// * xyz - Concentrations of liquid materials
  420. /// * w - Smooth liquid density
  421. /// </remarks>
  422. [NonSerialized]
  423. public RenderTexture DensityTexture;
  424. /// <summary>
  425. /// 3D texture containing liquid normals.
  426. /// </summary>
  427. /// <remarks>
  428. /// This is a float 3d texture. Each texel corresponds to grid node.
  429. /// Format:
  430. /// * xyz - Momentum of the liquid
  431. /// * w - Mass of the liquid
  432. /// </remarks>
  433. [NonSerialized]
  434. public RenderTexture VelocityTexture;
  435. /// <summary>
  436. /// Maximum number of particles simulation may have.
  437. /// </summary>
  438. /// <remarks>
  439. /// <para>
  440. /// Directly corresponds to maximum volume of liquid simulation may have.
  441. /// </para>
  442. /// <para>
  443. /// Has noticeable VRAM impact.
  444. /// </para>
  445. /// <para>
  446. /// Having more active particles in the simulation has noticeable performance impact.
  447. /// </para>
  448. /// <para>
  449. /// This parameter can not be changed when liquid has GPU resources initialized.
  450. /// (See <see cref="Initialized"/>)
  451. /// </para>
  452. /// <para>
  453. /// For UI limit of 10000000 particles is set,
  454. /// and that's maximum number which guaranteed to work (if you have enough VRAM).
  455. /// But if you want to, you can set it higher.
  456. /// </para>
  457. /// </remarks>
  458. [Range(1024, 10000000)]
  459. [Tooltip(
  460. "Maximum number of particles simulation may have. Directly corresponds to maximum volume of liquid simulation may have. Has noticeable VRAM impact.")]
  461. public int MaxNumParticles = 262144;
  462. /// <summary>
  463. /// Buffer containing positions and particle species information.
  464. /// </summary>
  465. /// <remarks>
  466. /// This is a float4 buffer. Each float4 corresponds to particle.
  467. /// Format:
  468. /// * PositionMass[i].xyz - Position of the particle in the simulation space
  469. /// * PositionMass[i].w - Particle species
  470. /// </remarks>
  471. public ComputeBuffer PositionMass { get; private set; }
  472. /// <summary>
  473. /// Buffers containing affine velocity matrices, velocities
  474. /// and foaming values for each particle.
  475. /// </summary>
  476. /// <remarks>
  477. /// <para>
  478. /// There are exactly 2 buffers, and the active one is flipped each simulation step.
  479. /// </para>
  480. /// <para>
  481. /// This is a float4 buffer. Each pack of 4 float4's corresponds to particle.
  482. /// Format:
  483. /// * Affine[particleID * 4 + 0].xyz - 1st row of affine velocity matrix
  484. /// * Affine[particleID * 4 + 0].w - 1st particle specific random number
  485. /// * Affine[particleID * 4 + 1].xyz - 2nd row of affine velocity matrix
  486. /// * Affine[particleID * 4 + 1].w - 2nd particle specific random number
  487. /// * Affine[particleID * 4 + 2].xyz - 3rd row of affine velocity matrix
  488. /// * Affine[particleID * 4 + 2].w - 3rd particle specific random number
  489. /// * Affine[particleID * 4 + 3].xyz - Velocity
  490. /// * Affine[particleID * 4 + 3].w - Foaming value
  491. /// </para>
  492. /// </remarks>
  493. public ComputeBuffer[] Affine { get; private set; }
  494. /// <summary>
  495. /// Buffer containing number of active particles, as well as some additional counters.
  496. /// </summary>
  497. /// <remarks>
  498. /// This is an int buffer.
  499. /// Format:
  500. /// * ParticleNumber[0] - Active particle count
  501. /// * ParticleNumber[1] - Particles emitted in the last simulation step
  502. /// * Other values are not useful outside of the simulation
  503. /// </remarks>
  504. public ComputeBuffer ParticleNumber { get; private set; }
  505. /// <summary>
  506. /// If enabled, makes liquid render in lower resolution.
  507. /// </summary>
  508. /// <remarks>
  509. /// <para>
  510. /// Enabling downscale can significantly improve performance on mobile,
  511. /// by having way less pixels calculate pixel shader for the liquid.
  512. /// </para>
  513. /// <para>
  514. /// Has no effect in Unity Render mode.
  515. /// </para>
  516. /// </remarks>
  517. [Tooltip("If enabled, makes liquid render in lower resolution")]
  518. public bool EnableDownscale = false;
  519. /// <summary>
  520. /// Factor of resolution downscale.
  521. /// </summary>
  522. /// <remarks>
  523. /// <para>
  524. /// Lower factor corresponds to better performance, but lower visual quality.
  525. /// </para>
  526. /// <para>
  527. /// If you set this value too high, you may get lower performance compared to downscale disabled.
  528. /// This is due to fact that we need to do additional pass to upscale liquid,
  529. /// so when resolution downscale is too high, performance win from lower shading resolution
  530. /// can potentially be less than performance loss due to cost of doing upscale pass.
  531. /// That's why value of 1.0 is not allowed and you have to disable downscale for full resolution.
  532. /// </para>
  533. /// <para>
  534. /// Has no effect in Unity Render mode or when <see cref="EnableDownscale"/> is disabled.
  535. /// </para>
  536. /// </remarks>
  537. [Range(0.2f, 0.99f)]
  538. [Tooltip(
  539. "Factor of resolution downscale. Lower factor corresponds to better performance, but lower visual quality.")]
  540. public float DownscaleFactor = 0.5f;
  541. /// <summary>
  542. /// See <see cref="InitialState"/>.
  543. /// </summary>
  544. public enum InitialStateType
  545. {
  546. NoParticles,
  547. BakedLiquidState
  548. }
  549. /// <summary>
  550. /// Baked initial state.
  551. /// </summary>
  552. [Serializable]
  553. public class BakedInitialState
  554. {
  555. /// <summary>
  556. /// Active particle count in baked state
  557. /// </summary>
  558. /// <remarks>
  559. /// If baked initial state will have more particles <see cref="MaxNumParticles"/> it'll trigger an
  560. /// error.
  561. /// </remarks>
  562. [SerializeField]
  563. public int ParticleCount;
  564. /// <summary>
  565. /// Particle data stored in same format as in buffer <see cref="PositionMass"/>.
  566. /// </summary>
  567. [SerializeField]
  568. public Vector4[] Positions;
  569. /// <summary>
  570. /// Particle data stored in same format as in buffers <see cref="Affine"/>.
  571. /// </summary>
  572. [SerializeField]
  573. public Vector2Int[] AffineVelocity;
  574. }
  575. /// <summary>
  576. /// Type of initial state of the liquid.
  577. /// </summary>
  578. /// <remarks>
  579. /// Default is - No Particles, which means that there won't be any liquid on startup.
  580. /// Alternative is - Baked Liquid State, which uses <see cref="BakedInitialStateAsset"/>
  581. /// to restore previously recorded liquid state.
  582. /// </remarks>
  583. [Tooltip("Type of initial state of the liquid")]
  584. public InitialStateType InitialState = InitialStateType.NoParticles;
  585. /// <summary>
  586. /// Asset containing baked initial state data.
  587. /// </summary>
  588. /// <remarks>
  589. /// <para>
  590. /// This state is too large to store in the scene file,
  591. /// So it's stored separately, which has sideeffect of having TextAsset type.
  592. /// Since any TextAsset can be assigned to it,
  593. /// we have check to make sure that any specific TextAsset is a baked liquid state.
  594. /// See <see cref="IsValidBakedLiquidHeader"/>.
  595. /// </para>
  596. /// <para>
  597. /// Has no effect in case <see cref="InitialState"/> is not set to BakedLiquidState.
  598. /// </para>
  599. /// </remarks>
  600. [Tooltip("Asset containing baked initial state data")]
  601. public TextAsset BakedInitialStateAsset;
  602. /// <summary>
  603. /// ID of running liquid instance.
  604. /// </summary>
  605. /// <remarks>
  606. /// <para>
  607. /// Only valid when liquid resources are initialized.
  608. /// </para>
  609. /// <para>
  610. /// Guaranteed to be unique among all currently initialized liquids.
  611. /// </para>
  612. /// </remarks>
  613. public int CurrentInstanceID { get; private set; }
  614. /// <summary>
  615. /// Timestep used in last simulation iteration.
  616. /// </summary>
  617. public float Timestep { get; private set; } = 0.0f;
  618. /// <summary>
  619. /// Simulation time passed (in simulation time units).
  620. /// </summary>
  621. public float SimulationInternalTime { get; private set; } = 0.0f;
  622. /// <summary>
  623. /// Number of simulation iterations done so far.
  624. /// </summary>
  625. public int SimulationInternalFrame { get; private set; } = 0;
  626. /// <summary>
  627. /// Total number of grid nodes.
  628. /// </summary>
  629. /// <remarks>
  630. /// Only valid when liquid resources are initialized.
  631. /// Or after call to <see cref="UpdateSimulationConstants"/>
  632. /// </remarks>
  633. public int GridNodeCount { get; private set; } = 0;
  634. /// <summary>
  635. /// See <see cref="CurrentRenderingMode"/>.
  636. /// </summary>
  637. public enum RenderingMode
  638. {
  639. [Obsolete("Particle Render is no longer support. Please switch to another render mode.",
  640. true)] ParticleRender = 0,
  641. MeshRender = 1,
  642. #if ZIBRA_EFFECTS_OTP_VERSION
  643. [Obsolete("Unity Render is not supported in OTP version.", true)]
  644. #endif
  645. UnityRender = 2
  646. }
  647. /// <summary>
  648. /// Rendering mode of the liquid.
  649. /// </summary>
  650. /// <remarks>
  651. /// <para>
  652. /// You can choose between:
  653. ///
  654. /// * Mesh Render mode - mode in which we:
  655. /// Generate mesh from the liquid.
  656. /// Render it with DrawIndirect in Native Plugin
  657. /// (optionally) Do raymarching pass to calculate light bounching inside the liquid in Native plugin.
  658. /// Shading inside Unity with customizeable shader.
  659. /// (optionally) Upscale pass to allow shading in lower resolution.
  660. ///
  661. /// * Unity Render mode - mode in which we:
  662. /// Generate mesh from the liquid.
  663. /// Copy it to Unity's Mesh Renderer.
  664. /// And Unity takes care of rendering that mesh.
  665. /// </para>
  666. /// <para>
  667. /// To use Unity Render mode you'll need your own shader for liquid to render with.
  668. /// </para>
  669. /// <para>
  670. /// In Unity Render mode you won't have raymarching results, so visual quality will be lower.
  671. /// </para>
  672. /// <para>
  673. /// Unity Render mode has slight performance penalty,
  674. /// as it currently can not draw variable number of indices.
  675. /// </para>
  676. /// <para>
  677. /// In Unity Render, material parameters set in liquid object have no effect.
  678. /// Since liquid can not control arbitrary material that may be set to render the liquid.
  679. /// </para>
  680. /// <para>
  681. /// Mesh Render mode doesn't support VR at the moment,
  682. /// so will have to switch to Unity Render mode in order for VR to work.
  683. /// </para>
  684. /// <para>
  685. /// Changing this parameter when liquid is initialized has no effect.
  686. /// During initialization we allocate different set of resources based on render mode.
  687. /// So changing render mode requires re-initialization.
  688. /// </para>
  689. /// <para>
  690. /// See User Guide for more details.
  691. /// </para>
  692. /// </remarks>
  693. [Tooltip("Rendering mode of the liquid. Please see documentation for more details.")]
  694. public RenderingMode CurrentRenderingMode = RenderingMode.MeshRender;
  695. /// <summary>
  696. /// Injection point where we will insert liquid rendering.
  697. /// </summary>
  698. /// <remarks>
  699. /// <para>
  700. /// Only used in case of Built-in Render Pipeline.
  701. /// </para>
  702. /// <para>
  703. /// Has no effect when using Unity Render mode.
  704. /// </para>
  705. /// </remarks>
  706. [Tooltip("Injection point where we will insert liquid rendering")]
  707. public CameraEvent CurrentInjectionPoint = CameraEvent.AfterSkybox;
  708. /// <summary>
  709. /// Size of the simulation grid.
  710. /// </summary>
  711. /// <remarks>
  712. /// <para>
  713. /// Only valid when liquid resources are initialized.
  714. /// Or after call to <see cref="UpdateSimulationConstants"/>
  715. /// </para>
  716. /// <para>
  717. /// Largest component is equal to <see cref="GridResolution"/>.
  718. /// Other components are scaled so aspect ratio of GridSize
  719. /// matches aspect ratio of <see cref="ContainerSize"/>.
  720. /// </para>
  721. /// </remarks>
  722. public Vector3Int GridSize { get; private set; }
  723. #if UNITY_PIPELINE_HDRP
  724. /// <summary>
  725. /// (HDRP Only) Reflection proble used for liquid reflections.
  726. /// </summary>
  727. /// <remarks>
  728. /// Must be set you are using HDRP and Mesh Render mode.
  729. /// Otherwise liquid won't inialize.
  730. /// </remarks>
  731. [FormerlySerializedAs("reflectionProbe")]
  732. [FormerlySerializedAs("reflectionProbeHDRP")]
  733. [Tooltip("Reflection proble used for liquid reflections")]
  734. public HDProbe ReflectionProbeHDRP;
  735. /// <summary>
  736. /// (HDRP Only) Light used for liquid shading.
  737. /// </summary>
  738. /// <remarks>
  739. /// Must be set you are using HDRP and Mesh Render mode.
  740. /// Otherwise liquid won't inialize.
  741. /// </remarks>
  742. [FormerlySerializedAs("customLightHDRP")]
  743. [Tooltip("Light used for liquid shading")]
  744. public Light CustomLightHDRP;
  745. #endif // UNITY_PIPELINE_HDRP
  746. /// <summary>
  747. /// (URP/Built-in RP Only) Reflection proble used for liquid reflections.
  748. /// </summary>
  749. /// <remarks>
  750. /// It's strongly recommended to set it if you are using URP/Built-in RP and Mesh Render mode.
  751. /// </remarks>
  752. #if !UNITY_PIPELINE_HDRP
  753. [FormerlySerializedAs("reflectionProbe")]
  754. #endif // !UNITY_PIPELINE_HDRP
  755. [FormerlySerializedAs("reflectionProbeSRP")]
  756. [Tooltip("Reflection proble used for liquid reflections")]
  757. public ReflectionProbe ReflectionProbeBRP;
  758. /// <summary>
  759. /// Maximum timestep that is allowed in single simulation iteration.
  760. /// </summary>
  761. /// <remarks>
  762. /// Higher values correspond to potentially less stable simulation.
  763. /// While lower values correspond to higher chance of liquid simulation slowing down during FPS drops.
  764. /// </remarks>
  765. [Range(0.0f, 1.0f)]
  766. [FormerlySerializedAs("timeStepMax")]
  767. [Tooltip("Maximum timestep that is allowed in single simulation iteration")]
  768. public float MaxAllowedTimestep = 1.00f;
  769. /// <summary>
  770. /// Maximum allowed number of frames queued to render.
  771. /// </summary>
  772. /// <remarks>
  773. /// <para>
  774. /// Only used when <c>QualitySettings.maxQueuedFrames</c> is not available or invalid.
  775. /// </para>
  776. /// <para>
  777. /// Defines number of frames we'll wait between submitting simulation workload
  778. /// and reading back simulation information back to the CPU.
  779. /// Higher values correspond to more delay for simulation info readback,
  780. /// while lower values can potentially decreasing framerate.
  781. /// </para>
  782. /// </remarks>
  783. [Range(2, 16)]
  784. [FormerlySerializedAs("maxFramesInFlight")]
  785. [Tooltip("Fallback maximum allowed number of frames queued to render")]
  786. public UInt32 MaxFramesInFlight = 3;
  787. /// <summary>
  788. /// Speed of liquid simulation.
  789. /// </summary>
  790. /// <remarks>
  791. /// <para>
  792. /// Defines relation between simulation time units and seconds.
  793. /// </para>
  794. /// <para>
  795. /// You can change the speed of liquid simulation with this parameter dynamically.
  796. /// </para>
  797. /// </remarks>
  798. [Range(0.0f, 100.0f)]
  799. [FormerlySerializedAs("simTimePerSec")]
  800. [Tooltip("Speed of liquid simulation")]
  801. public float SimulationTimeScale = DEFAULT_SIMULATION_TIME_SCALE;
  802. /// <summary>
  803. /// Current number of particles in the simulation.
  804. /// </summary>
  805. /// <remarks>
  806. /// <para>
  807. /// Values greater than 0 correspond to having any liquid in the simulation.
  808. /// </para>
  809. /// <para>
  810. /// This parameter is updated with delay, since we need to read that data from the GPU.
  811. /// </para>
  812. /// </remarks>
  813. public int CurrentParticleNumber { get; private set; } = 0;
  814. /// <summary>
  815. /// Number of simulation iterations to execute on each update.
  816. /// </summary>
  817. /// <remarks>
  818. /// <para>
  819. /// Update for purposes of this parameter is <c>Update()</c>
  820. /// in case <see cref="UseFixedTimestep"/> is disabled,
  821. /// and <c>FixedUpdate()</c> otherwise.
  822. /// </para>
  823. /// <para>
  824. /// It's strongly recommended to set it to 1 if you target mobile devices.
  825. /// </para>
  826. /// </remarks>
  827. [Range(1, 10)]
  828. [FormerlySerializedAs("iterationsPerFrame")]
  829. [Tooltip("Number of simulation iterations to execute on each update")]
  830. public int SimulationIterationsPerFrame = 1;
  831. /// <summary>
  832. /// Size of each grid node.
  833. /// </summary>
  834. /// <remarks>
  835. /// <para>
  836. /// Only valid when liquid resources are initialized.
  837. /// Or after call to <see cref="UpdateSimulationConstants"/>
  838. /// </para>
  839. /// <para>
  840. /// Grid nodes are all same size and all of them are cubes.
  841. /// This parameter is length of side of that cube.
  842. /// </para>
  843. /// </remarks>
  844. public float NodeSize { get; private set; }
  845. /// <summary>
  846. /// Resolution of the simulation grid.
  847. /// </summary>
  848. /// <remarks>
  849. /// <para>
  850. /// Has major impact on performance and quality.
  851. /// This is the first option you want to configure when tweaking performance.
  852. /// </para>
  853. /// <para>
  854. /// Changing resolution while liquid resources are intialized has no effect.
  855. /// </para>
  856. /// <para>
  857. /// This parameter defines number of nodes in largest dimension of grid node
  858. /// </para>
  859. /// </remarks>
  860. [Min(16)]
  861. [FormerlySerializedAs("gridResolution")]
  862. [Tooltip(
  863. "Resolution of the simulation grid. Has major impact on performance and quality. Please see documentation for details.")]
  864. public int GridResolution = 128;
  865. /// <summary>
  866. /// Whether to run simulation.
  867. /// </summary>
  868. /// <remarks>
  869. /// <para>
  870. /// Has no effect when liquid is not initialized.
  871. /// </para>
  872. /// <para>
  873. /// Disabling simulation will improve performance.
  874. /// </para>
  875. /// <para>
  876. /// Simulation will run for 2 frames after liquid initializations independently of this option,
  877. /// since liquid can't be rendered otherwise.
  878. /// </para>
  879. /// </remarks>
  880. [FormerlySerializedAs("runSimulation")]
  881. public bool RunSimulation = true;
  882. /// <summary>
  883. /// Whether to render liquid.
  884. /// </summary>
  885. /// <remarks>
  886. /// <para>
  887. /// Has no effect when liquid is not initialized.
  888. /// </para>
  889. /// <para>
  890. /// Disabling rendering will improve performance.
  891. /// </para>
  892. /// <para>
  893. /// Liquid may still be simulated,
  894. /// which mean that it may still push objects with force interaction,
  895. /// update data in detectors/emitters/voids,
  896. /// and сost performance due to simulation calculatons.
  897. /// </para>
  898. /// </remarks>
  899. [FormerlySerializedAs("runRendering")]
  900. [Tooltip("Whether to render liquid")]
  901. public bool RunRendering = true;
  902. /// <summary>
  903. /// When enabled, during container movement, liquid stays in place in world space.
  904. /// </summary>
  905. /// <remarks>
  906. /// If you want to move liquid container without disturbing simulation you can disable this.
  907. /// </remarks>
  908. [Tooltip("When enabled, during container movement, liquid stays in place in world space")]
  909. public bool EnableContainerMovementFeedback = true;
  910. /// <summary>
  911. /// Whether to render visualised SDFs.
  912. /// </summary>
  913. /// <remarks>
  914. /// <para>
  915. /// Has no effect when liquid is not initialized.
  916. /// </para>
  917. /// <para>
  918. /// This option is only meant for debugging purposes.
  919. /// It's strongly recommended to not enable it in final builds.
  920. /// </para>
  921. /// </remarks>
  922. [FormerlySerializedAs("visualizeSceneSDF")]
  923. [Tooltip("Whether to render visualized SDFs")]
  924. public bool VisualizeSceneSDF = false;
  925. /// <summary>
  926. /// Reference to <see cref="DataStructures::ZibraLiquidSolverParameters">ZibraLiquidSolverParameters</see>
  927. /// corresponding to this object.
  928. /// </summary>
  929. public ZibraLiquidSolverParameters SolverParameters
  930. {
  931. get {
  932. if (SolverParametersInternal == null)
  933. {
  934. SolverParametersInternal = gameObject.GetComponent<ZibraLiquidSolverParameters>();
  935. if (SolverParametersInternal == null)
  936. {
  937. SolverParametersInternal = gameObject.AddComponent<ZibraLiquidSolverParameters>();
  938. #if UNITY_EDITOR
  939. UnityEditor.EditorUtility.SetDirty(this);
  940. #endif
  941. }
  942. }
  943. return SolverParametersInternal;
  944. }
  945. }
  946. /// <summary>
  947. /// Reference to
  948. /// <see cref="DataStructures::ZibraLiquidMaterialParameters">ZibraLiquidMaterialParameters</see>
  949. /// corresponding to this object.
  950. /// </summary>
  951. public ZibraLiquidMaterialParameters MaterialParameters
  952. {
  953. get {
  954. if (MaterialParametersInternal == null)
  955. {
  956. MaterialParametersInternal = gameObject.GetComponent<ZibraLiquidMaterialParameters>();
  957. if (MaterialParametersInternal == null)
  958. {
  959. MaterialParametersInternal = gameObject.AddComponent<ZibraLiquidMaterialParameters>();
  960. #if UNITY_EDITOR
  961. UnityEditor.EditorUtility.SetDirty(this);
  962. #endif
  963. }
  964. }
  965. return MaterialParametersInternal;
  966. }
  967. }
  968. /// <summary>
  969. /// Reference to
  970. /// <see
  971. /// cref="DataStructures::ZibraLiquidAdvancedRenderParameters">ZibraLiquidAdvancedRenderParameters</see>
  972. /// corresponding to this object.
  973. /// </summary>
  974. public ZibraLiquidAdvancedRenderParameters AdvancedRenderParameters
  975. {
  976. get {
  977. if (AdvancedRenderParametersInternal == null)
  978. {
  979. AdvancedRenderParametersInternal = gameObject.GetComponent<ZibraLiquidAdvancedRenderParameters>();
  980. if (AdvancedRenderParametersInternal == null)
  981. {
  982. AdvancedRenderParametersInternal =
  983. gameObject.AddComponent<ZibraLiquidAdvancedRenderParameters>();
  984. #if UNITY_EDITOR
  985. UnityEditor.EditorUtility.SetDirty(this);
  986. #endif
  987. }
  988. }
  989. return AdvancedRenderParametersInternal;
  990. }
  991. }
  992. /// <summary>
  993. /// Liquid container size.
  994. /// </summary>
  995. /// <remarks>
  996. /// <para>
  997. /// Liquid container is always a axis aligned box, and this Vector3 is sides of the box.
  998. /// </para>
  999. /// <para>
  1000. /// This indirectly affects performance,
  1001. /// since aspect ratio of this box affects totan number of grid nodes.
  1002. /// See <see cref="GridNodeCount"/>.
  1003. /// </para>
  1004. /// <para>
  1005. /// Liquid can not leave this box.
  1006. /// You can, however, move this box.
  1007. /// If you do that, liquid will try to stay in place in world space,
  1008. /// unless <see cref="EnableContainerMovementFeedback"/> is disabled.
  1009. /// </para>
  1010. /// </remarks>
  1011. [FormerlySerializedAs("containerSize")]
  1012. public Vector3 ContainerSize = new Vector3(10, 10, 10);
  1013. /// <summary>
  1014. /// Whether liquid resources are initialized.
  1015. /// </summary>
  1016. /// <remarks>
  1017. /// <para>
  1018. /// Can be true in edit mode (e.g. during initial state baking).
  1019. /// Can be false in play mode (e.g. disabled liquid).
  1020. /// </para>
  1021. /// <para>
  1022. /// When liquid resources are initialized,
  1023. /// you won't be able to change a lot of liquid parameters.
  1024. /// This is due to fact, that some resources are initialized based on those parameters
  1025. /// and currently, can't be resized without re-initializing simulation.
  1026. /// </para>
  1027. /// </remarks>
  1028. public bool Initialized { get; private set; } = false;
  1029. /// <summary>
  1030. /// Selects whether to update simulation in Update or FixedUpdate.
  1031. /// </summary>
  1032. /// <remarks>
  1033. /// <para>
  1034. /// True corresponds on updating simulation in FixedUpdate.
  1035. /// </para>
  1036. /// <para>
  1037. /// When enabled, number of simulation iterations each frame
  1038. /// may be inconsistent between frames.
  1039. /// So use with care, as it may introduce stutter.
  1040. /// </para>
  1041. /// <para>
  1042. /// If you want to change fixed timestep interval,
  1043. /// change Fixed Timestep in Time section of Project settings.
  1044. /// </para>
  1045. /// </remarks>
  1046. [Tooltip("Selects whether to update simulation in Update or FixedUpdate")]
  1047. public bool UseFixedTimestep = false;
  1048. #endregion
  1049. #region Methods
  1050. /// <summary>
  1051. /// Simulation needs to do some loading before simulation can start.
  1052. /// Loading starts during initialization of engine.
  1053. /// If it takes too long and you start simulation too early
  1054. /// it can stall engine until loading finishes.
  1055. /// You can use this method to show loading screen to wait for loading to end
  1056. /// and prevent stalling.
  1057. /// </summary>
  1058. /// <returns>
  1059. /// true - if starting simulation won't trigger stall
  1060. /// false - if starting simulation will trigger stall
  1061. /// </returns>
  1062. public bool IsLoaded()
  1063. {
  1064. return LiquidBridge.ZibraLiquid_IsLoaded() != 0;
  1065. }
  1066. /// <summary>
  1067. /// Stalls engine until all loading is finished
  1068. /// See <see cref="IsLoaded"/>
  1069. /// </summary>
  1070. public void WaitLoad()
  1071. {
  1072. LiquidBridge.ZibraLiquid_WaitLoad();
  1073. }
  1074. /// <summary>
  1075. /// Updates values of some constants based on <see cref="ContainerSize"/> and
  1076. /// <see cref="GridResolution"/>.
  1077. /// </summary>
  1078. /// <remarks>
  1079. /// <para>
  1080. /// Update values of <see cref="NodeSize"/>, <see cref="GridSize"/>
  1081. /// and <see cref="GridNodeCount"/>.
  1082. /// </para>
  1083. /// <para>
  1084. /// Has no effect when liquid is initialized, since you can't modify
  1085. /// aforementioned parameters in this case.
  1086. /// </para>
  1087. /// </remarks>
  1088. public void UpdateSimulationConstants()
  1089. {
  1090. if (Initialized)
  1091. {
  1092. return;
  1093. }
  1094. NodeSize = Math.Max(ContainerSize.x, Math.Max(ContainerSize.y, ContainerSize.z)) / GridResolution;
  1095. GridSize = Vector3Int.CeilToInt(ContainerSize / NodeSize);
  1096. GridNodeCount = GridSize[0] * GridSize[1] * GridSize[2];
  1097. }
  1098. /// <summary>
  1099. /// Returns aproximate size each particle will have in case of resting liquid.
  1100. /// </summary>
  1101. public float GetParticleSize()
  1102. {
  1103. UpdateSimulationConstants();
  1104. return (float)(NodeSize / Math.Pow(SolverParameters.ParticleDensity, 1.0f / 3.0f));
  1105. }
  1106. /// <summary>
  1107. /// Checks if liquid has at least one emitter manipulator.
  1108. /// </summary>
  1109. /// <remarks>
  1110. /// Liquid component must have emitter or non empty initial state,
  1111. /// otherwise it won't be able to generate any particles
  1112. /// and will never generate any actual liquid.
  1113. /// </remarks>
  1114. public bool HasEmitter()
  1115. {
  1116. foreach (var manipulator in Manipulators)
  1117. {
  1118. if (manipulator.GetManipulatorType() == Manipulator.ManipulatorType.Emitter)
  1119. {
  1120. return true;
  1121. }
  1122. }
  1123. return false;
  1124. }
  1125. /// <summary>
  1126. /// Returns read-only list of colliders.
  1127. /// </summary>
  1128. public ReadOnlyCollection<ZibraLiquidCollider> GetColliderList()
  1129. {
  1130. return SDFColliders.AsReadOnly();
  1131. }
  1132. /// <summary>
  1133. /// Checks whether collider list has specified collider.
  1134. /// </summary>
  1135. public bool HasCollider(ZibraLiquidCollider collider)
  1136. {
  1137. return SDFColliders.Contains(collider);
  1138. }
  1139. /// <summary>
  1140. /// Adds collider to the liquid.
  1141. /// </summary>
  1142. /// <remarks>
  1143. /// Can only be used if liquid is not initialized yet,
  1144. /// e.g. when liquid is disabled.
  1145. /// </remarks>
  1146. public void AddCollider(ZibraLiquidCollider collider)
  1147. {
  1148. if (Initialized)
  1149. {
  1150. Debug.LogWarning(
  1151. "We don't yet support changing number of manipulators/colliders while liquid's resources are initialized.");
  1152. return;
  1153. }
  1154. if (!SDFColliders.Contains(collider))
  1155. {
  1156. SDFColliders.Add(collider);
  1157. SDFColliders.Sort(new SDFColliderCompare());
  1158. #if UNITY_EDITOR
  1159. UnityEditor.EditorUtility.SetDirty(this);
  1160. #endif
  1161. }
  1162. }
  1163. /// <summary>
  1164. /// Removes collider from the liquid.
  1165. /// </summary>
  1166. /// <remarks>
  1167. /// Can only be used if liquid is not initialized yet,
  1168. /// e.g. when liquid is disabled.
  1169. /// </remarks>
  1170. public void RemoveCollider(ZibraLiquidCollider collider)
  1171. {
  1172. if (Initialized)
  1173. {
  1174. Debug.LogWarning(
  1175. "We don't yet support changing number of manipulators/colliders while liquid's resources are initialized.");
  1176. return;
  1177. }
  1178. if (SDFColliders.Contains(collider))
  1179. {
  1180. SDFColliders.Remove(collider);
  1181. SDFColliders.Sort(new SDFColliderCompare());
  1182. #if UNITY_EDITOR
  1183. UnityEditor.EditorUtility.SetDirty(this);
  1184. #endif
  1185. }
  1186. }
  1187. /// <summary>
  1188. /// Returns read-only list of colliders.
  1189. /// </summary>
  1190. public ReadOnlyCollection<Manipulator> GetManipulatorList()
  1191. {
  1192. return Manipulators.AsReadOnly();
  1193. }
  1194. /// <summary>
  1195. /// Checks whether manipulator list has specified manipulator.
  1196. /// </summary>
  1197. public bool HasManipulator(Manipulator manipulator)
  1198. {
  1199. return Manipulators.Contains(manipulator);
  1200. }
  1201. /// <summary>
  1202. /// Adds manipulator to the liquid.
  1203. /// </summary>
  1204. /// <remarks>
  1205. /// Can only be used if liquid is not initialized yet,
  1206. /// e.g. when liquid is disabled.
  1207. /// </remarks>
  1208. public void AddManipulator(Manipulator manipulator)
  1209. {
  1210. if (Initialized)
  1211. {
  1212. Debug.LogWarning("We don't yet support changing number of manipulators/colliders at runtime.");
  1213. return;
  1214. }
  1215. if (!Manipulators.Contains(manipulator))
  1216. {
  1217. Manipulators.Add(manipulator);
  1218. Manipulators.Sort(new ManipulatorCompare());
  1219. #if UNITY_EDITOR
  1220. UnityEditor.EditorUtility.SetDirty(this);
  1221. #endif
  1222. }
  1223. }
  1224. /// <summary>
  1225. /// Removes manipulator from the liquid.
  1226. /// </summary>
  1227. /// <remarks>
  1228. /// Can only be used if liquid is not initialized yet,
  1229. /// e.g. when liquid is disabled.
  1230. /// </remarks>
  1231. public void RemoveManipulator(Manipulator manipulator)
  1232. {
  1233. if (Initialized)
  1234. {
  1235. Debug.LogWarning("We don't yet support changing number of manipulators/colliders at runtime.");
  1236. return;
  1237. }
  1238. if (Manipulators.Contains(manipulator))
  1239. {
  1240. Manipulators.Remove(manipulator);
  1241. Manipulators.Sort(new ManipulatorCompare());
  1242. #if UNITY_EDITOR
  1243. UnityEditor.EditorUtility.SetDirty(this);
  1244. #endif
  1245. }
  1246. }
  1247. /// <summary>
  1248. /// Returns approximate VRAM usage corresponding to <see cref="MaxNumParticles"/>.
  1249. /// </summary>
  1250. /// <returns>
  1251. /// Approximate VRAM usage in bytes.
  1252. /// </returns>
  1253. public ulong GetParticleCountFootprint()
  1254. {
  1255. ulong result = 0;
  1256. int particleCountRounded = GetParticleCountRounded();
  1257. result += (ulong)(MaxNumParticles * 4 * sizeof(float)); // PositionMass
  1258. result += (ulong)(2 * 4 * particleCountRounded * 2 * sizeof(int)); // Affine
  1259. result += (ulong)(particleCountRounded * 4 * sizeof(float)); // PositionMassCopy
  1260. result += (ulong)(particleCountRounded * 2 * sizeof(int)); // nodeParticlePairs
  1261. result += (ulong)(particleCountRounded * sizeof(uint)); // TmpSDFBuff
  1262. result += (ulong)(4 * MaxNumParticles * sizeof(int)); // NodeParticlePairs0 NodeParticlePairs1
  1263. int RadixWorkGroups1 = (int)Math.Ceiling((float)MaxNumParticles / (float)(2 * RADIX_THREADS));
  1264. int RadixWorkGroups2 = (int)Math.Ceiling((float)MaxNumParticles / (float)(RADIX_THREADS * RADIX_THREADS));
  1265. int RadixWorkGroups3 = (int)Math.Ceiling((float)RadixWorkGroups2 / (float)RADIX_THREADS);
  1266. result += (ulong)(RadixWorkGroups1 * HISTO_WIDTH * sizeof(int)); // RadixGroupData1
  1267. result += (ulong)(RadixWorkGroups2 * HISTO_WIDTH * sizeof(int)); // RadixGroupData2
  1268. result += (ulong)((RadixWorkGroups3 + 1) * HISTO_WIDTH * sizeof(int)); // RadixGroupData3
  1269. return result;
  1270. }
  1271. /// <summary>
  1272. /// Returns approximate VRAM usage corresponding to manipulators/colliders SDFs.
  1273. /// </summary>
  1274. /// <returns>
  1275. /// Approximate VRAM usage in bytes.
  1276. /// </returns>
  1277. public ulong GetSDFsFootprint()
  1278. {
  1279. ulong result = 0;
  1280. foreach (var collider in SDFColliders)
  1281. {
  1282. if (collider == null)
  1283. {
  1284. continue;
  1285. }
  1286. var sdf = collider.gameObject.GetComponent<SDFObject>();
  1287. if (sdf)
  1288. result += sdf.GetVRAMFootprint();
  1289. }
  1290. return result;
  1291. }
  1292. /// <summary>
  1293. /// Calculates approximate VRAM usage corresponding to <see cref="GridResolution"/>.
  1294. /// </summary>
  1295. /// <returns>
  1296. /// Approximate VRAM usage in bytes.
  1297. /// </returns>
  1298. public ulong GetGridFootprint()
  1299. {
  1300. ulong result = 0;
  1301. UpdateSimulationConstants();
  1302. result += (ulong)(GridNodeCount * 4 * sizeof(int)); // GridData
  1303. result += (ulong)(GridNodeCount * 4 * sizeof(float)); // GridNormal
  1304. result += (ulong)(GridNodeCount * sizeof(float)); // GridBlur0
  1305. result += (ulong)(GridNodeCount * sizeof(float)); // GridBlur1
  1306. result += (ulong)(GridNodeCount * sizeof(float)); // MassCopy
  1307. result += (ulong)(GridNodeCount * 2 * sizeof(int)); // IndexGrid
  1308. result += (ulong)(GridNodeCount * sizeof(int)); // VertexIDGrid
  1309. result += (ulong)(GridNodeCount * 4 * sizeof(float)); // VertexBuffer
  1310. result += (ulong)(GridNodeCount * sizeof(uint)); // QuadBuffer
  1311. result += (ulong)(GridNodeCount * (sizeof(uint) * 4)); // VertexProperties
  1312. result += (ulong)(GridNodeCount * 2 * sizeof(float)); // GridNormalTexture
  1313. result += (ulong)(GridNodeCount * sizeof(float) / 2); // DensityTexture
  1314. result += (ulong)(GridNodeCount * sizeof(float) / 2); // VelocityTexture
  1315. return result;
  1316. }
  1317. /// <summary>
  1318. /// Initializes liquid simulation resources.
  1319. /// </summary>
  1320. /// <remarks>
  1321. /// <para>
  1322. /// This is automatically called in <c>OnEnable()</c> if not in edit mode.
  1323. /// To run liquid simulation in edit mode, you need to call it manually.
  1324. /// </para>
  1325. /// <para>
  1326. /// On success, sets <see cref="Initialize"/> to true.
  1327. /// </para>
  1328. /// <para>
  1329. /// On fail, cleans up simulation resources and throws an <c>Exception</c>.
  1330. /// </para>
  1331. /// <para>
  1332. /// Initialization allocates GPU resources,
  1333. /// so calling this at runtime may cause stutter.
  1334. /// Prefer to initialize liquid on scene load.
  1335. /// </para>
  1336. /// <para>
  1337. /// Has no effect if liquid is already initialized.
  1338. /// </para>
  1339. /// </remarks>
  1340. public void InitializeSimulation()
  1341. {
  1342. if (Initialized)
  1343. {
  1344. return;
  1345. }
  1346. try
  1347. {
  1348. #if UNITY_IOS
  1349. if (SystemInfo.graphicsDeviceName == "Apple iOS simulator GPU")
  1350. {
  1351. throw new Exception("Zibra Liquid doesn't support iOS simulator. " + "Liquid was disabled.");
  1352. }
  1353. #endif
  1354. #if !ZIBRA_EFFECTS_NO_LICENSE_CHECK && UNITY_EDITOR
  1355. if (!ServerAuthManager.GetInstance().IsLicenseVerified(PluginManager.Effect.Liquid))
  1356. {
  1357. string errorMessage =
  1358. "License wasn't verified. " +
  1359. ServerAuthManager.GetInstance().GetErrorMessage(PluginManager.Effect.Liquid) +
  1360. " Liquid won't run in editor.";
  1361. throw new Exception(errorMessage);
  1362. }
  1363. #endif
  1364. // Copy Rendering Mode to internal variable to prevent user from modifying it during liquid lifetime
  1365. ActiveRenderingMode = CurrentRenderingMode;
  1366. #if UNITY_PIPELINE_HDRP
  1367. if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
  1368. {
  1369. bool missingRequiredParameter = false;
  1370. if (CustomLightHDRP == null
  1371. #if !ZIBRA_EFFECTS_OTP_VERSION
  1372. && ActiveRenderingMode != RenderingMode.UnityRender
  1373. #endif
  1374. )
  1375. {
  1376. Debug.LogError("No Custom Light set in Zibra Liquid.");
  1377. missingRequiredParameter = true;
  1378. }
  1379. if (ReflectionProbeHDRP == null
  1380. #if !ZIBRA_EFFECTS_OTP_VERSION
  1381. && ActiveRenderingMode != RenderingMode.UnityRender
  1382. #endif
  1383. )
  1384. {
  1385. Debug.LogError("No reflection probe added to Zibra Liquid.");
  1386. missingRequiredParameter = true;
  1387. }
  1388. if (missingRequiredParameter)
  1389. {
  1390. throw new Exception("Liquid creation failed due to missing parameter.");
  1391. }
  1392. }
  1393. #endif
  1394. ValidateColliders();
  1395. ValidateManipulators();
  1396. if (InitialState == ZibraLiquid.InitialStateType.NoParticles || BakedInitialStateAsset == null)
  1397. {
  1398. bool haveEmitter = false;
  1399. foreach (var manipulator in Manipulators)
  1400. {
  1401. if (manipulator.GetManipulatorType() == Manipulator.ManipulatorType.Emitter &&
  1402. manipulator.GetComponent<SDFObject>() != null)
  1403. {
  1404. haveEmitter = true;
  1405. break;
  1406. }
  1407. }
  1408. if (!haveEmitter)
  1409. {
  1410. throw new Exception(
  1411. "Liquid creation failed. Liquid have neither initial state nor emitters, or all emitters missing SDF component.");
  1412. }
  1413. }
  1414. Camera.onPreRender += RenderCallBackWrapper;
  1415. SolverCommandBuffer = new CommandBuffer { name = "ZibraLiquid.Solver" };
  1416. CurrentInstanceID = NextInstanceId++;
  1417. ForceCloseCommandEncoder(SolverCommandBuffer);
  1418. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  1419. LiquidBridge.EventID.CreateFluidInstance);
  1420. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  1421. SolverCommandBuffer.Clear();
  1422. InitializeParticles();
  1423. var initializeGPUReadbackParamsBridgeParams = new InitializeGPUReadbackParams();
  1424. UInt32 manipSize = (UInt32)ManipulatorManager.Elements * STATISTICS_PER_MANIPULATOR * sizeof(Int32);
  1425. initializeGPUReadbackParamsBridgeParams.readbackBufferSize = sizeof(Int32) + manipSize;
  1426. switch (SystemInfo.graphicsDeviceType)
  1427. {
  1428. case GraphicsDeviceType.Direct3D11:
  1429. case GraphicsDeviceType.XboxOne:
  1430. case GraphicsDeviceType.Switch:
  1431. case GraphicsDeviceType.Direct3D12:
  1432. case GraphicsDeviceType.XboxOneD3D12:
  1433. initializeGPUReadbackParamsBridgeParams.maxFramesInFlight = QualitySettings.maxQueuedFrames + 1;
  1434. break;
  1435. default:
  1436. initializeGPUReadbackParamsBridgeParams.maxFramesInFlight = (int)MaxFramesInFlight;
  1437. break;
  1438. }
  1439. IntPtr nativeCreateInstanceBridgeParams =
  1440. Marshal.AllocHGlobal(Marshal.SizeOf(initializeGPUReadbackParamsBridgeParams));
  1441. Marshal.StructureToPtr(initializeGPUReadbackParamsBridgeParams, nativeCreateInstanceBridgeParams, true);
  1442. SolverCommandBuffer.Clear();
  1443. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  1444. LiquidBridge.EventID.InitializeGpuReadback,
  1445. nativeCreateInstanceBridgeParams);
  1446. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  1447. ToFreeOnExit.Add(nativeCreateInstanceBridgeParams);
  1448. InitializeSolver();
  1449. Initialized = true;
  1450. #if UNITY_EDITOR
  1451. ZibraLiquidAnalytics.TrackSimulationInitialization(this);
  1452. ZibraEffectsPresetAnalytics.SendPresetAnalyticsData(new string[]
  1453. {
  1454. AdvancedRenderParameters.PresetName,
  1455. SolverParameters.PresetName,
  1456. MaterialParameters.PresetName,
  1457. });
  1458. #endif
  1459. }
  1460. catch (Exception)
  1461. {
  1462. ClearRendering();
  1463. ClearSolver();
  1464. throw;
  1465. }
  1466. }
  1467. /// <summary>
  1468. /// Releases liquid simulation resources.
  1469. /// </summary>
  1470. /// <remarks>
  1471. /// <para>
  1472. /// This is automatically called in <c>OnDisable()</c>.
  1473. /// When running liquid simulation in edit mode,
  1474. /// you may want to call it manually.
  1475. /// </para>
  1476. /// <para>
  1477. /// Sets <see cref="Initialize"/> to false.
  1478. /// </para>
  1479. /// <para>
  1480. /// Releases GPU resources and so frees up VRAM.
  1481. /// </para>
  1482. /// <para>
  1483. /// Has no effect if liquid is not initialized.
  1484. /// </para>
  1485. /// </remarks>
  1486. public void ReleaseSimulation()
  1487. {
  1488. if (!Initialized)
  1489. {
  1490. return;
  1491. }
  1492. ClearRendering();
  1493. ClearSolver();
  1494. Initialized = false;
  1495. // If ZibraLiquid object gets disabled/destroyed
  1496. // We still may need to do cleanup few frames later
  1497. // So we create new gameobject which allows us to run cleanup code
  1498. ZibraLiquidGPUGarbageCollector.CreateGarbageCollector();
  1499. }
  1500. /// <summary>
  1501. /// Runs liquid simulation.
  1502. /// </summary>
  1503. /// <remarks>
  1504. /// <para>
  1505. /// You don't need to call it manually, unless you want to run liquid in edit mode.
  1506. /// In play mode it's called automatically in <c>Update</c> or <c>FixedUpdate</c>
  1507. /// depending on <see cref="UseFixedTimestep"/>
  1508. /// </para>
  1509. /// <para>
  1510. /// Executes <see cref="SimulationIterationsPerFrame"/> number of liquid simulation iterations.
  1511. /// </para>
  1512. /// </remarks>
  1513. public void UpdateSimulation(float deltaTime)
  1514. {
  1515. UpdateUnityRender();
  1516. UpdateNativeRenderParams();
  1517. if (!IsSimulationEnabled())
  1518. {
  1519. return;
  1520. }
  1521. Timestep =
  1522. Math.Min(SimulationTimeScale * deltaTime / (float)SimulationIterationsPerFrame, MaxAllowedTimestep);
  1523. for (var i = 0; i < SimulationIterationsPerFrame; i++)
  1524. {
  1525. StepPhysics();
  1526. }
  1527. SolverCommandBuffer.Clear();
  1528. // copy grid data to 3d texture for rendering after physics steps
  1529. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  1530. #if UNITY_EDITOR
  1531. NotifyChange();
  1532. #endif
  1533. }
  1534. /// <summary>
  1535. /// Updates Mesh object used for Unity Render.
  1536. /// </summary>
  1537. /// <remarks>
  1538. /// <para>
  1539. /// In case <see cref="CurrentRenderingMode"/> is set to Unity Render mode,
  1540. /// creates or enabled mesh used for it.
  1541. /// Otherwise disabled that mesh (if it exists).
  1542. /// </para>
  1543. /// <para>
  1544. /// If you set <see cref="CurrentRenderingMode"/> to Unity Render mode via script,
  1545. /// you may want to call this method so make liquid create liquid mesh used for rendering,
  1546. /// so you can configure that newly created object.
  1547. /// </para>
  1548. /// <para>
  1549. /// Executes <see cref="SimulationIterationsPerFrame"/> number of liquid simulation iterations.
  1550. /// </para>
  1551. /// </remarks>
  1552. /// <returns>
  1553. /// GameObject used for Unity Render, or null if it doesn't exist.
  1554. /// In case <see cref="CurrentRenderingMode"/> is set to Unity Render mode,
  1555. /// valid GameObject is always returned.
  1556. /// Otherwise object may be returned if it was created previously.
  1557. /// </returns>
  1558. public GameObject UpdateUnityRender()
  1559. {
  1560. // This function can be called independently of whether liquid is initialized or not
  1561. // So need special care when querying rendering mode
  1562. RenderingMode effectiveRenderingMode = CurrentRenderingMode;
  1563. if (Initialized)
  1564. {
  1565. effectiveRenderingMode = ActiveRenderingMode;
  1566. }
  1567. #if !ZIBRA_EFFECTS_OTP_VERSION
  1568. if (effectiveRenderingMode == RenderingMode.UnityRender)
  1569. {
  1570. Transform meshTransform = transform.Find("ZibraLiquidMesh");
  1571. if (meshTransform == null)
  1572. {
  1573. GameObject obj = new GameObject();
  1574. obj.name = "ZibraLiquidMesh";
  1575. meshTransform = obj.transform;
  1576. meshTransform.SetParent(transform, false);
  1577. }
  1578. GameObject meshObject = meshTransform.gameObject;
  1579. // Add renderer components if not present
  1580. if (meshObject.GetComponent<MeshFilter>() == null)
  1581. {
  1582. meshObject.AddComponent(typeof(MeshFilter));
  1583. }
  1584. if (meshObject.GetComponent<MeshRenderer>() == null)
  1585. {
  1586. meshObject.AddComponent(typeof(MeshRenderer));
  1587. MeshRenderer meshRenderer = meshObject.GetComponent<MeshRenderer>();
  1588. meshRenderer.material = new Material(Shader.Find("Diffuse"));
  1589. meshRenderer.enabled = true;
  1590. }
  1591. else
  1592. {
  1593. MeshRenderer meshRenderer = meshObject.GetComponent<MeshRenderer>();
  1594. meshRenderer.enabled = true;
  1595. }
  1596. MeshFilter meshFilter = meshObject.GetComponent<MeshFilter>();
  1597. if (meshFilter.sharedMesh != LiquidMesh)
  1598. {
  1599. meshFilter.sharedMesh = LiquidMesh;
  1600. }
  1601. meshObject.SetActive(RunRendering);
  1602. return meshObject;
  1603. }
  1604. else
  1605. #endif
  1606. {
  1607. Transform meshTransform = transform.Find("ZibraLiquidMesh");
  1608. if (meshTransform == null)
  1609. return null;
  1610. GameObject meshObject = meshTransform.gameObject;
  1611. meshObject.SetActive(false);
  1612. return meshObject;
  1613. }
  1614. }
  1615. public List<string> GetStats()
  1616. {
  1617. float ResolutionScale = EnableDownscale ? DownscaleFactor : 1.0f;
  1618. float PixelCountScale = ResolutionScale * ResolutionScale;
  1619. return new List<string> {
  1620. "Liquid Simulation",
  1621. $"Instance: {name}",
  1622. $"Grid size: {GridSize}",
  1623. $"Render resolution: {ResolutionScale * 100.0f}%",
  1624. $"Render pixel count: {PixelCountScale * 100.0f}%",
  1625. $"Max particle count: {MaxNumParticles}",
  1626. $"Current particle count: {CurrentParticleNumber}"
  1627. };
  1628. }
  1629. #if UNITY_EDITOR
  1630. /// <summary>
  1631. /// (Editor only) Validates liquid parameters and fixes them as needed.
  1632. /// </summary>
  1633. public void OnValidate()
  1634. {
  1635. transform.rotation = Quaternion.identity;
  1636. transform.localScale = Vector3.one;
  1637. switch (CurrentRenderingMode)
  1638. {
  1639. case RenderingMode.MeshRender:
  1640. #if !ZIBRA_EFFECTS_OTP_VERSION
  1641. case RenderingMode.UnityRender:
  1642. #endif
  1643. break;
  1644. default:
  1645. CurrentRenderingMode = RenderingMode.MeshRender;
  1646. UnityEditor.EditorUtility.SetDirty(this);
  1647. break;
  1648. }
  1649. ContainerSize[0] = Math.Max(ContainerSize[0], 1e-3f);
  1650. ContainerSize[1] = Math.Max(ContainerSize[1], 1e-3f);
  1651. ContainerSize[2] = Math.Max(ContainerSize[2], 1e-3f);
  1652. UpdateSimulationConstants();
  1653. if (GetComponent<ZibraLiquidMaterialParameters>() == null)
  1654. {
  1655. gameObject.AddComponent<ZibraLiquidMaterialParameters>();
  1656. UnityEditor.EditorUtility.SetDirty(this);
  1657. }
  1658. if (GetComponent<ZibraLiquidSolverParameters>() == null)
  1659. {
  1660. gameObject.AddComponent<ZibraLiquidSolverParameters>();
  1661. UnityEditor.EditorUtility.SetDirty(this);
  1662. }
  1663. if (GetComponent<ZibraLiquidAdvancedRenderParameters>() == null)
  1664. {
  1665. gameObject.AddComponent<ZibraLiquidAdvancedRenderParameters>();
  1666. UnityEditor.EditorUtility.SetDirty(this);
  1667. }
  1668. if (GetComponent<ZibraManipulatorManager>() == null)
  1669. {
  1670. gameObject.AddComponent<ZibraManipulatorManager>();
  1671. UnityEditor.EditorUtility.SetDirty(this);
  1672. }
  1673. ValidateColliders();
  1674. ValidateManipulators();
  1675. if (BakedInitialStateAsset)
  1676. {
  1677. int bakedLiquidHeader = BitConverter.ToInt32(BakedInitialStateAsset.bytes, 0);
  1678. if (!IsValidBakedLiquidHeader(bakedLiquidHeader))
  1679. {
  1680. BakedInitialStateAsset = null;
  1681. UnityEditor.EditorUtility.SetDirty(this);
  1682. }
  1683. }
  1684. }
  1685. /// <summary>
  1686. /// (Editor only) Save current simulation state
  1687. /// </summary>
  1688. public BakedInitialState SerializeCurrentLiquidState()
  1689. {
  1690. int[] ParticleNumberArray = new int[1];
  1691. ParticleNumber.GetData(ParticleNumberArray, 0, 0, 1);
  1692. BakedInitialState initialStateData = new BakedInitialState();
  1693. initialStateData.ParticleCount = ParticleNumberArray[0];
  1694. int currentAffineIndex = 1 - LiquidBridge.ZibraLiquid_GetCurrentAffineBufferIndex(CurrentInstanceID);
  1695. InitialState = InitialStateType.BakedLiquidState;
  1696. Array.Resize(ref initialStateData.Positions, initialStateData.ParticleCount);
  1697. PositionMass.GetData(initialStateData.Positions);
  1698. Array.Resize(ref initialStateData.AffineVelocity, 4 * initialStateData.ParticleCount);
  1699. Affine[currentAffineIndex].GetData(initialStateData.AffineVelocity);
  1700. return initialStateData;
  1701. }
  1702. #endif
  1703. #endregion
  1704. #endregion
  1705. #region Deprecated
  1706. /// @cond SHOW_DEPRECATED
  1707. #region Properties
  1708. #pragma warning disable 0067
  1709. /// @deprecated
  1710. /// Only used for backwards compatibility
  1711. [Obsolete("onChanged is deprecated. Please use OnChanged.", true)]
  1712. public event Action onChanged;
  1713. #pragma warning restore 0067
  1714. /// @deprecated
  1715. /// Only used for backwards compatibility
  1716. [Obsolete("color0 is deprecated. Please use Color0.", true)]
  1717. [NonSerialized]
  1718. public RenderTexture color0;
  1719. [NonSerialized]
  1720. /// @deprecated
  1721. /// Only used for backwards compatibility
  1722. [Obsolete("color1 is deprecated. Please use Color1.", true)]
  1723. public RenderTexture color1;
  1724. /// @deprecated
  1725. /// Only used for backwards compatibility
  1726. [Obsolete("color2 is deprecated. Please use Color2.", true)]
  1727. [NonSerialized]
  1728. public RenderTexture color2;
  1729. [NonSerialized]
  1730. /// @deprecated
  1731. /// Only used for backwards compatibility
  1732. [Obsolete("upscaleColor is deprecated. Please use UpscaleColor.", true)]
  1733. public RenderTexture upscaleColor;
  1734. /// @deprecated
  1735. /// Only used for backwards compatibility
  1736. [Obsolete("depth is deprecated. Please use Depth.", true)]
  1737. [NonSerialized]
  1738. public RenderTexture depth;
  1739. /// @deprecated
  1740. /// Only used for backwards compatibility
  1741. [Obsolete("timestep is deprecated. Please use Timestep.", true)]
  1742. [NonSerialized]
  1743. public float timestep;
  1744. /// @deprecated
  1745. /// Only used for backwards compatibility
  1746. [Obsolete("simulationInternalTime is deprecated. Please use SimulationInternalTime.", true)]
  1747. [NonSerialized]
  1748. public float simulationInternalTime;
  1749. /// @deprecated
  1750. /// Only used for backwards compatibility
  1751. [Obsolete("simulationInternalFrame is deprecated. Please use SimulationInternalFrame.", true)]
  1752. [NonSerialized]
  1753. public int simulationInternalFrame;
  1754. /// @deprecated
  1755. /// Only used for backwards compatibility
  1756. [NonSerialized]
  1757. [Obsolete(
  1758. "reflectionProbe is deprecated. Use ReflectionProbeBRP or ReflectionProbeHDRP instead depending on your Rendering Pipeline (URP uses ReflectionProbeBRP).",
  1759. true)]
  1760. public ReflectionProbe reflectionProbe;
  1761. #if UNITY_PIPELINE_HDRP
  1762. /// @deprecated
  1763. /// Only used for backwards compatibility
  1764. [Obsolete("reflectionProbeHDRP is deprecated. Please use ReflectionProbeHDRP.", true)]
  1765. [NonSerialized]
  1766. public HDProbe reflectionProbeHDRP;
  1767. /// @deprecated
  1768. /// Only used for backwards compatibility
  1769. [Obsolete("customLightHDRP is deprecated. Please use CustomLightHDRP.", true)]
  1770. [NonSerialized]
  1771. public Light customLightHDRP;
  1772. #endif // UNITY_PIPELINE_HDRP
  1773. /// @deprecated
  1774. /// Only used for backwards compatibility
  1775. [Obsolete("reflectionProbeSRP is deprecated. Please use ReflectionProbeBRP.", true)]
  1776. [NonSerialized]
  1777. public ReflectionProbe reflectionProbeSRP;
  1778. /// @deprecated
  1779. /// Only used for backwards compatibility
  1780. [Obsolete("timeStepMax is deprecated. Please use MaxAllowedTimestep.", true)]
  1781. [NonSerialized]
  1782. public float timeStepMax;
  1783. /// @deprecated
  1784. /// Only used for backwards compatibility
  1785. [Obsolete("maxFramesInFlight is deprecated. Please use MaxFramesInFlight.", true)]
  1786. [NonSerialized]
  1787. public UInt32 maxFramesInFlight;
  1788. /// @deprecated
  1789. /// Only used for backwards compatibility
  1790. [Obsolete("simTimePerSec is deprecated. Please use SimulationTimeScale.", true)]
  1791. [NonSerialized]
  1792. public float simTimePerSec;
  1793. /// @deprecated
  1794. /// Only used for backwards compatibility
  1795. [Obsolete("activeParticleNumber is deprecated. Please use CurrentParticleNumber.", true)]
  1796. [NonSerialized]
  1797. public int activeParticleNumber;
  1798. /// @deprecated
  1799. /// Only used for backwards compatibility
  1800. [Obsolete("iterationsPerFrame is deprecated. Please use SimulationIterationsPerFrame.", true)]
  1801. [NonSerialized]
  1802. public int iterationsPerFrame;
  1803. /// @deprecated
  1804. /// Only used for backwards compatibility
  1805. [Obsolete("CellSize is deprecated. Please use NodeSize.", true)]
  1806. [NonSerialized]
  1807. public float CellSize;
  1808. /// @deprecated
  1809. /// Only used for backwards compatibility
  1810. [Obsolete("gridResolution is deprecated. Please use GridResolution.", true)]
  1811. [NonSerialized]
  1812. public int gridResolution;
  1813. /// @deprecated
  1814. /// Only used for backwards compatibility
  1815. [Obsolete("runSimulation is deprecated. Please use RunSimulation.", true)]
  1816. [NonSerialized]
  1817. public bool runSimulation;
  1818. /// @deprecated
  1819. /// Only used for backwards compatibility
  1820. [Obsolete("runRendering is deprecated. Please use RunRendering.", true)]
  1821. [NonSerialized]
  1822. public bool runRendering;
  1823. /// @deprecated
  1824. /// Only used for backwards compatibility
  1825. [Obsolete("visualizeSceneSDF is deprecated. Please use VisualizeSceneSDF.", true)]
  1826. [NonSerialized]
  1827. public bool visualizeSceneSDF;
  1828. /// @deprecated
  1829. /// Only used for backwards compatibility
  1830. [Obsolete("solverParameters is deprecated. Please use SolverParameters.", true)]
  1831. [NonSerialized]
  1832. public ZibraLiquidSolverParameters solverParameters;
  1833. /// @deprecated
  1834. /// Only used for backwards compatibility
  1835. [Obsolete("materialParameters is deprecated. Please use MaterialParameters.", true)]
  1836. [NonSerialized]
  1837. public ZibraLiquidSolverParameters materialParameters;
  1838. /// @deprecated
  1839. /// Only used for backwards compatibility
  1840. [Obsolete("renderingParameters is deprecated. Please use AdvancedRenderParameters.", true)]
  1841. [NonSerialized]
  1842. public ZibraLiquidAdvancedRenderParameters renderingParameters;
  1843. /// @deprecated
  1844. /// Only used for backwards compatibility
  1845. [Obsolete("containerSize is deprecated. Please use ContainerSize.", true)]
  1846. [NonSerialized]
  1847. public Vector3 containerSize;
  1848. /// @deprecated
  1849. /// Only used for backwards compatibility
  1850. [Obsolete("initialized is deprecated. Please use Initialized.", true)]
  1851. [NonSerialized]
  1852. public bool initialized;
  1853. /// @deprecated
  1854. /// Only used for backwards compatibility
  1855. [Obsolete("useFixedTimestep is deprecated. Please use UseFixedTimestep.", true)]
  1856. [NonSerialized]
  1857. public bool useFixedTimestep = false;
  1858. #endregion
  1859. #region Methods
  1860. /// @deprecated
  1861. /// Only used for backwards compatibility
  1862. [Obsolete("Init is deprecated. Please use InitializeSimulation.", true)]
  1863. public void Init()
  1864. {
  1865. }
  1866. /// @deprecated
  1867. /// Only used for backwards compatibility
  1868. [Obsolete("StopSolver is deprecated. Please use ReleaseSimulation.", true)]
  1869. public void StopSolver()
  1870. {
  1871. }
  1872. #endregion
  1873. /// @endcond
  1874. #endregion
  1875. #region Implementation details
  1876. #region Interop structures
  1877. [StructLayout(LayoutKind.Sequential)]
  1878. private class UnityTextureBridge
  1879. {
  1880. public IntPtr texture;
  1881. public LiquidBridge.TextureFormat format;
  1882. }
  1883. [StructLayout(LayoutKind.Sequential)]
  1884. private class RegisterParticlesBuffersBridgeParams
  1885. {
  1886. public IntPtr PositionMass;
  1887. public IntPtr AffineVelocity0;
  1888. public IntPtr AffineVelocity1;
  1889. public IntPtr ParticleNumber;
  1890. }
  1891. [StructLayout(LayoutKind.Sequential)]
  1892. private class InitializeGPUReadbackParams
  1893. {
  1894. public UInt32 readbackBufferSize;
  1895. public Int32 maxFramesInFlight;
  1896. }
  1897. [StructLayout(LayoutKind.Sequential)]
  1898. private struct TextureUploadData
  1899. {
  1900. public IntPtr data;
  1901. public Int32 dataSize;
  1902. public Int32 rowPitch;
  1903. public Int32 dimensionX;
  1904. public Int32 dimensionY;
  1905. public Int32 dimensionZ;
  1906. };
  1907. [StructLayout(LayoutKind.Sequential)]
  1908. private class RegisterManipulatorsBridgeParams
  1909. {
  1910. public Int32 ManipulatorNum;
  1911. public IntPtr ManipulatorBufferDynamic;
  1912. public IntPtr SDFObjectBuffer;
  1913. public IntPtr ManipulatorBufferStatistics;
  1914. public IntPtr ManipulatorParams;
  1915. public Int32 SDFObjectCount;
  1916. public IntPtr SDFObjectData;
  1917. public IntPtr ManipIndices;
  1918. public UnityTextureBridge EmbeddingsTexture;
  1919. public UnityTextureBridge SDFGridTexture;
  1920. public UnityTextureBridge HeightmapTexture;
  1921. public TextureUploadData EmbeddigsData;
  1922. public TextureUploadData SDFGridData;
  1923. }
  1924. [StructLayout(LayoutKind.Sequential)]
  1925. private class RegisterSolverBuffersBridgeParams
  1926. {
  1927. public IntPtr SimulationParams;
  1928. public IntPtr PositionMassCopy;
  1929. public IntPtr GridData;
  1930. public IntPtr IndexGrid;
  1931. public IntPtr GridBlur0;
  1932. public IntPtr GridBlur1;
  1933. public IntPtr MassCopy;
  1934. public IntPtr TmpSDFBuff;
  1935. public IntPtr GridNormal;
  1936. public IntPtr NodeParticlePairs0;
  1937. public IntPtr NodeParticlePairs1;
  1938. public IntPtr RadixGroupData1;
  1939. public IntPtr RadixGroupData2;
  1940. public IntPtr RadixGroupData3;
  1941. public IntPtr Counters;
  1942. public IntPtr VertexIDGrid;
  1943. public IntPtr VertexBuffer0;
  1944. public IntPtr VertexBuffer1;
  1945. public IntPtr QuadBuffer;
  1946. public IntPtr TransferDataBuffer;
  1947. public IntPtr MeshRenderIndexBuffer;
  1948. public IntPtr ParticleSpeciesData;
  1949. public Int32 ParticleSpeciesCount;
  1950. public IntPtr UnityMeshVertexBuffer;
  1951. public IntPtr UnityMeshIndexBuffer;
  1952. public IntPtr VertexData;
  1953. public UnityTextureBridge GridNormals;
  1954. public UnityTextureBridge GridDensity;
  1955. public UnityTextureBridge GridVelocity;
  1956. public IntPtr EffectParticleData0;
  1957. public IntPtr EffectParticleData1;
  1958. }
  1959. [StructLayout(LayoutKind.Sequential)]
  1960. private class RegisterRenderResourcesBridgeParams
  1961. {
  1962. public UnityTextureBridge Depth;
  1963. public UnityTextureBridge Color0;
  1964. public UnityTextureBridge Color1;
  1965. public UnityTextureBridge Color2;
  1966. public UnityTextureBridge SceneDepth;
  1967. public UnityTextureBridge ParticlesRT;
  1968. }
  1969. [StructLayout(LayoutKind.Sequential)]
  1970. private class CameraParams
  1971. {
  1972. public Matrix4x4 View;
  1973. public Matrix4x4 Projection;
  1974. public Matrix4x4 ProjectionInverse;
  1975. public Matrix4x4 ViewProjection;
  1976. public Matrix4x4 ViewProjectionInverse;
  1977. public Matrix4x4 EyeRayCameraCoeficients;
  1978. public Vector3 WorldSpaceCameraPos;
  1979. public Int32 CameraID;
  1980. public Vector4 ZBufferParams;
  1981. public Vector2 CameraResolution;
  1982. public Single CameraDownscaleFactor;
  1983. private Single CameraParamsPadding1;
  1984. }
  1985. [StructLayout(LayoutKind.Sequential)]
  1986. private class MeshRenderGlobalParams
  1987. {
  1988. public Vector2 RenderingParameterPadding1;
  1989. public Int32 DisableRaymarch;
  1990. public Single LiquidIOR;
  1991. public Single RayMarchIsoSurface;
  1992. public Int32 UnderwaterRender;
  1993. public Single RayMarchStepSize;
  1994. public Single RayMarchStepFactor;
  1995. public Int32 RayMarchMaxSteps;
  1996. public Int32 TwoBouncesEnabled;
  1997. public Vector2Int RayMarchResolution;
  1998. public Single FoamingIntensity;
  1999. public Single FoamingDecay;
  2000. public Single FoamingThreshold;
  2001. public Single FoamBrightness;
  2002. public Vector4 Absorption;
  2003. public Single FoamMotionBlur;
  2004. public Single FoamSize;
  2005. public Single FoamDiffusion;
  2006. public Single FoamSpawning;
  2007. public Single FoamingDecaySmoothness;
  2008. public Single FoamingOcclusionDistance;
  2009. public Single SimulationParamPadding2;
  2010. public Single SimulationParamPadding3;
  2011. };
  2012. [StructLayout(LayoutKind.Sequential)]
  2013. private class RenderParams
  2014. {
  2015. public Single BlurRadius;
  2016. public Single RenderParamsPadding1;
  2017. public Single NeuralSamplingDistance;
  2018. public Single SDFDebug;
  2019. public Int32 RenderingMode;
  2020. public Int32 VertexOptimizationIterations;
  2021. public Int32 MeshOptimizationIterations;
  2022. public Single DualContourIsoValue;
  2023. public Single MeshOptimizationStep;
  2024. public Single CameraDensity;
  2025. public Int32 MaxVertexBufferSize;
  2026. public Int32 MaxIndexBufferSize;
  2027. public Vector3 RenderParamsContainerPos;
  2028. public float RenderParams_space0;
  2029. }
  2030. [StructLayout(LayoutKind.Sequential)]
  2031. private class SimulationParams
  2032. {
  2033. public Vector3 GridSize;
  2034. public Int32 ParticleCount;
  2035. public Vector3 ContainerScale;
  2036. public Int32 NodeCount;
  2037. public Vector3 SimulationParamsContainerPos;
  2038. public Single TimeStep;
  2039. public Int32 SimulationFrame;
  2040. public Single DensityBlurRadius;
  2041. public Single LiquidIsosurfaceThreshold;
  2042. public Single VertexOptimizationStep;
  2043. public Vector3 ParticleTranslation;
  2044. public Single GlobalVelocityLimit;
  2045. public Single MinimumVelocity;
  2046. public Single BlurNormalizationConstant;
  2047. public Int32 MaxParticleCount;
  2048. public Int32 VisualizeSDF;
  2049. public Single SimulationTime;
  2050. public Single FoamBuoyancy;
  2051. public Int32 ParticleSpeciesCount;
  2052. public Single SimulationParameterPadding;
  2053. public Int32 MaxEffectParticleCount;
  2054. public Int32 FoamParticleLifetime;
  2055. public Single padding0;
  2056. public Int32 EnableContainerMovementFeedback;
  2057. public Int32 EnableFoam;
  2058. public Single SimulationParamPadding1;
  2059. public Single SimulationParamPadding2;
  2060. public Single SimulationParamPadding3;
  2061. }
  2062. [StructLayout(LayoutKind.Sequential)]
  2063. private class ParticleSpeciesParameters
  2064. {
  2065. public Vector3 Gravity;
  2066. public Single AffineAmmount;
  2067. public Single LiquidStiffness;
  2068. public Single RestDensity;
  2069. public Single SurfaceTension;
  2070. public Single AffineDivergenceDecay;
  2071. public Vector3 Material;
  2072. public Single VelocityLimit;
  2073. }
  2074. #endregion
  2075. private RenderTexture DepthTexture;
  2076. internal const int MPM_THREADS = 256;
  2077. internal const int STATISTICS_PER_MANIPULATOR = 8;
  2078. private const int RADIX_THREADS = 128;
  2079. private const int HISTO_WIDTH = 32;
  2080. private const int DEPTH_COPY_WORKGROUP = 16;
  2081. private const int ADDITIONAL_VERTICES = 3000;
  2082. private static int NextInstanceId = 0;
  2083. private int CopyDepthID;
  2084. #if ZIBRA_EFFECTS_PROFILING_ENABLED
  2085. [NonSerialized]
  2086. internal LiquidBridge.DebugTimestampItem[] DebugTimestampsItems = new LiquidBridge.DebugTimestampItem[100];
  2087. #endif
  2088. internal struct MaterialPair
  2089. {
  2090. public Material CurrentMaterial;
  2091. public Material SharedMaterial;
  2092. // Returns true if dirty
  2093. public bool SetMaterial(Material mat)
  2094. {
  2095. if (SharedMaterial != mat)
  2096. {
  2097. CurrentMaterial = (mat != null ? Material.Instantiate(mat) : null);
  2098. SharedMaterial = mat;
  2099. return true;
  2100. }
  2101. return false;
  2102. }
  2103. }
  2104. internal class CameraResources
  2105. {
  2106. public RenderTexture Background;
  2107. public MaterialPair LiquidMaterial;
  2108. public MaterialPair UpscaleMaterial;
  2109. public MaterialPair SDFRenderMaterial;
  2110. public bool IsDirty = true;
  2111. }
  2112. private enum GraphicsBufferType
  2113. {
  2114. Vertex,
  2115. Index
  2116. }
  2117. private GraphicsBuffer CreateGraphicsBuffer(GraphicsBufferType type, int count, int stride)
  2118. {
  2119. return new GraphicsBuffer(type == GraphicsBufferType.Vertex
  2120. ? GraphicsBuffer.Target.Raw | GraphicsBuffer.Target.Vertex
  2121. : GraphicsBuffer.Target.Raw | GraphicsBuffer.Target.Index,
  2122. count, stride);
  2123. }
  2124. // We need to keep MaxFoamParticlesCount constant during runtime so we cache it on solver init and null on stop
  2125. private int MaxFoamParticles = 0;
  2126. private ZibraLiquidSolverParameters SolverParametersInternal;
  2127. private ZibraLiquidMaterialParameters MaterialParametersInternal;
  2128. private ZibraLiquidAdvancedRenderParameters AdvancedRenderParametersInternal;
  2129. private ZibraManipulatorManager ManipulatorManagerInternal;
  2130. internal ZibraManipulatorManager ManipulatorManager
  2131. {
  2132. get {
  2133. if (ManipulatorManagerInternal == null)
  2134. {
  2135. ManipulatorManagerInternal = gameObject.GetComponent<ZibraManipulatorManager>();
  2136. if (ManipulatorManagerInternal == null)
  2137. {
  2138. ManipulatorManagerInternal = gameObject.AddComponent<ZibraManipulatorManager>();
  2139. #if UNITY_EDITOR
  2140. UnityEditor.EditorUtility.SetDirty(this);
  2141. #endif
  2142. }
  2143. }
  2144. return ManipulatorManagerInternal;
  2145. }
  2146. }
  2147. [NonSerialized]
  2148. private Vector2Int CurrentTextureResolution = new Vector2Int(0, 0);
  2149. // List of all cameras we have added a command buffer to
  2150. private readonly Dictionary<Camera, CommandBuffer> CameraCBs = new Dictionary<Camera, CommandBuffer>();
  2151. // Each camera needs its own resources
  2152. private List<Camera> Cameras = new List<Camera>();
  2153. internal Dictionary<Camera, IntPtr> CamNativeParams = new Dictionary<Camera, IntPtr>();
  2154. private Dictionary<Camera, IntPtr> CamMeshRenderParams = new Dictionary<Camera, IntPtr>();
  2155. private Dictionary<Camera, Vector2Int> CamRenderResolutions = new Dictionary<Camera, Vector2Int>();
  2156. private Dictionary<Camera, Vector2Int> CamNativeResolutions = new Dictionary<Camera, Vector2Int>();
  2157. internal Dictionary<Camera, CameraResources> CameraResourcesMap = new Dictionary<Camera, CameraResources>();
  2158. private CameraParams CameraRenderParams;
  2159. private MeshRenderGlobalParams MeshRenderGlobalParamsContainer;
  2160. private RenderParams RenderParamsContainer;
  2161. #if ZIBRA_EFFECTS_PROFILING_ENABLED
  2162. [NonSerialized]
  2163. public uint DebugTimestampsItemsCount = 0;
  2164. #endif
  2165. private SimulationParams LiquidParameters;
  2166. private ComputeBuffer GridData;
  2167. private ComputeBuffer IndexGrid;
  2168. private ComputeBuffer GridNormal;
  2169. private Texture3D SDFGridTexture;
  2170. private Texture3D EmbeddingsTexture;
  2171. private ComputeBuffer PositionMassCopy;
  2172. private ComputeBuffer GridBlur0;
  2173. private ComputeBuffer GridBlur1;
  2174. private ComputeBuffer MassCopy;
  2175. private ComputeBuffer TmpSDFBuff;
  2176. private ComputeBuffer NodeParticlePairs0;
  2177. private ComputeBuffer NodeParticlePairs1;
  2178. private ComputeBuffer EffectParticleData0;
  2179. private ComputeBuffer EffectParticleData1;
  2180. private ComputeBuffer RadixGroupData1;
  2181. private ComputeBuffer RadixGroupData2;
  2182. private ComputeBuffer RadixGroupData3;
  2183. private ComputeBuffer DynamicManipulatorData;
  2184. private ComputeBuffer SDFObjectData;
  2185. private ComputeBuffer ManipulatorStatistics;
  2186. private ComputeBuffer ParticleSpeciesData;
  2187. private CommandBuffer SolverCommandBuffer;
  2188. private List<IntPtr> ToFreeOnExit = new List<IntPtr>();
  2189. private RenderingMode ActiveRenderingMode = RenderingMode.MeshRender;
  2190. private CameraEvent ActiveInjectionPoint = CameraEvent.AfterSkybox;
  2191. private IntPtr NativeManipData;
  2192. private IntPtr NativeSDFData;
  2193. private IntPtr NativeFluidData;
  2194. private IntPtr NativeSolverData;
  2195. [SerializeField]
  2196. [FormerlySerializedAs("sdfColliders")]
  2197. private List<ZibraLiquidCollider> SDFColliders = new List<ZibraLiquidCollider>();
  2198. [SerializeField]
  2199. [FormerlySerializedAs("manipulators")]
  2200. private List<Manipulator> Manipulators = new List<Manipulator>();
  2201. #if UNITY_PIPELINE_HDRP
  2202. private LiquidHDRPRenderComponent HDRPRenderer;
  2203. #endif // UNITY_PIPELINE_HDRP
  2204. private IntPtr GetNativePtr(ComputeBuffer buffer)
  2205. {
  2206. return buffer == null ? IntPtr.Zero : buffer.GetNativeBufferPtr();
  2207. }
  2208. private IntPtr GetNativePtr(GraphicsBuffer buffer)
  2209. {
  2210. return buffer == null ? IntPtr.Zero : buffer.GetNativeBufferPtr();
  2211. }
  2212. private IntPtr GetNativePtr(RenderTexture texture)
  2213. {
  2214. return texture == null ? IntPtr.Zero : texture.GetNativeTexturePtr();
  2215. }
  2216. private IntPtr GetNativePtr(Texture3D texture)
  2217. {
  2218. return texture == null ? IntPtr.Zero : texture.GetNativeTexturePtr();
  2219. }
  2220. internal bool IsRenderingEnabled()
  2221. {
  2222. // We need at least 2 simulation frames before we can start rendering
  2223. return Initialized && RunRendering && (SimulationInternalFrame > 1)
  2224. #if !ZIBRA_EFFECTS_OTP_VERSION
  2225. && (ActiveRenderingMode != RenderingMode.UnityRender || VisualizeSceneSDF)
  2226. #endif
  2227. ;
  2228. }
  2229. private bool IsSimulationEnabled()
  2230. {
  2231. // We need at least 2 simulation frames before we can start rendering
  2232. // So we need to always simulate first 2 frames
  2233. return Initialized && (RunSimulation || (SimulationInternalFrame <= 2));
  2234. }
  2235. private void SetupScriptableRenderComponent()
  2236. {
  2237. #if UNITY_PIPELINE_HDRP
  2238. #if UNITY_EDITOR
  2239. if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
  2240. {
  2241. HDRPRenderer = gameObject.GetComponent<LiquidHDRPRenderComponent>();
  2242. if (HDRPRenderer != null && HDRPRenderer.customPasses.Count == 0)
  2243. {
  2244. DestroyImmediate(HDRPRenderer);
  2245. HDRPRenderer = null;
  2246. }
  2247. if (HDRPRenderer == null)
  2248. {
  2249. HDRPRenderer = gameObject.AddComponent<LiquidHDRPRenderComponent>();
  2250. HDRPRenderer.injectionPoint = CustomPassInjectionPoint.BeforePreRefraction;
  2251. HDRPRenderer.AddPassOfType(typeof(LiquidHDRPRenderComponent.FluidHDRPRender));
  2252. LiquidHDRPRenderComponent.FluidHDRPRender renderer =
  2253. HDRPRenderer.customPasses[0] as LiquidHDRPRenderComponent.FluidHDRPRender;
  2254. renderer.name = "ZibraLiquidRenderer";
  2255. renderer.liquid = this;
  2256. }
  2257. }
  2258. #endif
  2259. #endif // UNITY_PIPELINE_HDRP
  2260. }
  2261. private void ForceCloseCommandEncoder(CommandBuffer cmdList)
  2262. {
  2263. #if UNITY_EDITOR_OSX || (!UNITY_EDITOR && UNITY_STANDALONE_OSX) || (!UNITY_EDITOR && UNITY_IOS)
  2264. // Unity bug workaround
  2265. // For whatever reason, Unity sometimes doesn't close command encoder when we request it from native plugin
  2266. // So when we try to start our command encoder with active encoder already present it leads to crash
  2267. // This happens when scene have Terrain (I still have no idea why)
  2268. // So we force change command encoder like that, and this one closes gracefully
  2269. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal)
  2270. {
  2271. cmdList.DispatchCompute(MaterialParameters.NoOpCompute, 0, 1, 1, 1);
  2272. }
  2273. #endif
  2274. }
  2275. private UnityTextureBridge MakeTextureNativeBridge(RenderTexture texture)
  2276. {
  2277. var unityTextureBridge = new UnityTextureBridge();
  2278. if (texture != null)
  2279. {
  2280. unityTextureBridge.texture = GetNativePtr(texture);
  2281. unityTextureBridge.format = LiquidBridge.ToBridgeTextureFormat(texture.graphicsFormat);
  2282. }
  2283. else
  2284. {
  2285. unityTextureBridge.texture = IntPtr.Zero;
  2286. unityTextureBridge.format = LiquidBridge.TextureFormat.None;
  2287. }
  2288. return unityTextureBridge;
  2289. }
  2290. private UnityTextureBridge MakeTextureNativeBridge(Texture3D texture)
  2291. {
  2292. var unityTextureBridge = new UnityTextureBridge();
  2293. unityTextureBridge.texture = GetNativePtr(texture);
  2294. unityTextureBridge.format = LiquidBridge.ToBridgeTextureFormat(texture.graphicsFormat);
  2295. return unityTextureBridge;
  2296. }
  2297. void OnDrawGizmosInternal(bool isSelected)
  2298. {
  2299. if (!enabled)
  2300. {
  2301. return;
  2302. }
  2303. Gizmos.color = Color.yellow;
  2304. if (!isSelected)
  2305. {
  2306. Gizmos.color = new Color(Gizmos.color.r, Gizmos.color.g, Gizmos.color.b, Gizmos.color.a * 0.5f);
  2307. }
  2308. Gizmos.DrawWireCube(transform.position, ContainerSize);
  2309. Gizmos.color = new Color(0.2f, 0.8f, 0.8f);
  2310. if (!isSelected)
  2311. {
  2312. Gizmos.color = new Color(Gizmos.color.r, Gizmos.color.g, Gizmos.color.b, Gizmos.color.a * 0.5f);
  2313. }
  2314. Vector3 voxelSize =
  2315. new Vector3(ContainerSize.x / GridSize.x, ContainerSize.y / GridSize.y, ContainerSize.z / GridSize.z);
  2316. const int GizmosVoxelCubeSize = 2;
  2317. for (int i = -GizmosVoxelCubeSize; i <= GizmosVoxelCubeSize; i++)
  2318. for (int j = -GizmosVoxelCubeSize; j <= GizmosVoxelCubeSize; j++)
  2319. for (int k = -GizmosVoxelCubeSize; k <= GizmosVoxelCubeSize; k++)
  2320. Gizmos.DrawWireCube(transform.position +
  2321. new Vector3(i * voxelSize.x, j * voxelSize.y, k * voxelSize.z),
  2322. voxelSize);
  2323. }
  2324. private void OnDrawGizmosSelected()
  2325. {
  2326. OnDrawGizmosInternal(true);
  2327. }
  2328. private void OnDrawGizmos()
  2329. {
  2330. OnDrawGizmosInternal(false);
  2331. }
  2332. private void Awake()
  2333. {
  2334. SetupScriptableRenderComponent();
  2335. }
  2336. private void OnEnable()
  2337. {
  2338. #if UNITY_EDITOR
  2339. foreach (var manipulator in Manipulators)
  2340. {
  2341. if (manipulator is ZibraLiquidEmitter)
  2342. {
  2343. ZibraLiquidEmitter emitter = manipulator as ZibraLiquidEmitter;
  2344. if (emitter.InitialVelocity.magnitude > SolverParameters.MaximumVelocity)
  2345. {
  2346. Debug.LogWarning("Too high velocity magnitude " + emitter.InitialVelocity.magnitude +
  2347. " on emitter '" + emitter.name + "'. Liquid instance '" + this.name +
  2348. "' MaximumVelocity is " + SolverParameters.MaximumVelocity);
  2349. }
  2350. }
  2351. }
  2352. #endif
  2353. SetupScriptableRenderComponent();
  2354. AllFluids?.Add(this);
  2355. UpdateUnityRender();
  2356. #if UNITY_EDITOR
  2357. if (!UnityEditor.EditorApplication.isPlaying)
  2358. {
  2359. return;
  2360. }
  2361. #endif
  2362. AddToStatReporter();
  2363. InitializeSimulation();
  2364. }
  2365. private void InitializeParticles()
  2366. {
  2367. UpdateSimulationConstants();
  2368. LiquidParameters = new SimulationParams();
  2369. NativeFluidData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SimulationParams)));
  2370. NativeSolverData = Marshal.AllocHGlobal((SolverParameters.AdditionalParticleSpecies.Count +
  2371. ZibraLiquidSolverParameters.MAX_RUNTIME_ADDED_SPECIES) *
  2372. Marshal.SizeOf(typeof(ParticleSpeciesParameters)));
  2373. var numParticlesRounded =
  2374. (int)Math.Ceiling((double)MaxNumParticles / MPM_THREADS) * MPM_THREADS; // round to workgroup size
  2375. PositionMass = new ComputeBuffer(MaxNumParticles, 4 * sizeof(float));
  2376. Affine = new ComputeBuffer[2];
  2377. Affine[0] = new ComputeBuffer(4 * numParticlesRounded, 2 * sizeof(int));
  2378. Affine[1] = new ComputeBuffer(4 * numParticlesRounded, 2 * sizeof(int));
  2379. ParticleNumber = new ComputeBuffer(128, sizeof(int));
  2380. int[] particleNumberInitialData = new int[128];
  2381. ParticleNumber.SetData(particleNumberInitialData);
  2382. #if ZIBRA_EFFECTS_DEBUG
  2383. PositionMass.name = "PositionMass";
  2384. Affine[0].name = "Affine0";
  2385. Affine[1].name = "Affine1";
  2386. ParticleNumber.name = "ParticleNumber";
  2387. #endif
  2388. // We mush apply state before we send buffers to native plugin
  2389. // SetData seems to recreate buffers, at least on Metal
  2390. ApplyInitialState();
  2391. int[] Pnums = new int[128];
  2392. for (int i = 0; i < 128; i++)
  2393. {
  2394. Pnums[i] = 0;
  2395. }
  2396. ParticleNumber.SetData(Pnums);
  2397. ManipulatorManager.UpdateConst(Manipulators, SDFColliders);
  2398. ManipulatorManager.HeightmapCountSqrt = (int)Mathf.Ceil(Mathf.Sqrt(ManipulatorManager.HeightmapCount));
  2399. ManipulatorManager.HeightmapSize = Vector2Int.one * Mathf.Max(1, ManipulatorManager.HeightmapCountSqrt *
  2400. SolverParameters.HeightmapResolution);
  2401. CreateTexture(ref HeightmapTexture, ManipulatorManager.HeightmapSize, FilterMode.Point, 0,
  2402. RenderTextureFormat.RHalf, false);
  2403. ManipulatorManager.UpdateDynamic(SolverCommandBuffer, this);
  2404. if (ManipulatorManager.TextureCount > 0)
  2405. {
  2406. EmbeddingsTexture = new Texture3D(
  2407. ManipulatorManager.EmbeddingTextureDimension, ManipulatorManager.EmbeddingTextureDimension,
  2408. ManipulatorManager.EmbeddingTextureDimension, TextureFormat.RGBA32, false);
  2409. SDFGridTexture =
  2410. new Texture3D(ManipulatorManager.SDFTextureDimension, ManipulatorManager.SDFTextureDimension,
  2411. ManipulatorManager.SDFTextureDimension, TextureFormat.RHalf, false);
  2412. EmbeddingsTexture.filterMode = FilterMode.Trilinear;
  2413. SDFGridTexture.filterMode = FilterMode.Trilinear;
  2414. }
  2415. else
  2416. {
  2417. EmbeddingsTexture = new Texture3D(1, 1, 1, TextureFormat.RGBA32, 0);
  2418. SDFGridTexture = new Texture3D(1, 1, 1, TextureFormat.RHalf, 0);
  2419. EmbeddingsTexture.filterMode = FilterMode.Trilinear;
  2420. SDFGridTexture.filterMode = FilterMode.Trilinear;
  2421. }
  2422. int ManipSize = Marshal.SizeOf(typeof(ZibraManipulatorManager.ManipulatorParam));
  2423. int SDFSize = Marshal.SizeOf(typeof(ZibraManipulatorManager.SDFObjectParams));
  2424. // Need to create at least some buffer to bind to shaders
  2425. NativeManipData = Marshal.AllocHGlobal(ManipulatorManager.Elements * ManipSize);
  2426. NativeSDFData = Marshal.AllocHGlobal(ManipulatorManager.SDFObjectList.Count * SDFSize);
  2427. DynamicManipulatorData = new ComputeBuffer(Math.Max(ManipulatorManager.Elements, 1), ManipSize);
  2428. SDFObjectData = new ComputeBuffer(Math.Max(ManipulatorManager.SDFObjectList.Count, 1),
  2429. Marshal.SizeOf(typeof(ZibraManipulatorManager.SDFObjectParams)));
  2430. int ManipulatorStatisticsSize = Math.Max(STATISTICS_PER_MANIPULATOR * ManipulatorManager.Elements, 1);
  2431. // flag ComputeBufferType.IndirectArguments is needed to make R32_UINT buffer on d3d11
  2432. ManipulatorStatistics =
  2433. new ComputeBuffer(ManipulatorStatisticsSize, sizeof(int), ComputeBufferType.IndirectArguments);
  2434. int[] manipulatorStatisticsSizeInitialData = new int[ManipulatorStatisticsSize];
  2435. ManipulatorStatistics.SetData(manipulatorStatisticsSizeInitialData);
  2436. #if ZIBRA_EFFECTS_DEBUG
  2437. DynamicManipulatorData.name = "DynamicManipulatorData";
  2438. SDFObjectData.name = "SDFObjectData";
  2439. ManipulatorStatistics.name = "ManipulatorStatistics";
  2440. #endif
  2441. var gcparamBuffer2 = GCHandle.Alloc(ManipulatorManager.Indices, GCHandleType.Pinned);
  2442. UpdateInteropBuffers();
  2443. var registerManipulatorsBridgeParams = new RegisterManipulatorsBridgeParams();
  2444. registerManipulatorsBridgeParams.ManipulatorNum = ManipulatorManager.Elements;
  2445. registerManipulatorsBridgeParams.ManipulatorBufferDynamic = GetNativePtr(DynamicManipulatorData);
  2446. registerManipulatorsBridgeParams.SDFObjectBuffer = GetNativePtr(SDFObjectData);
  2447. registerManipulatorsBridgeParams.ManipulatorBufferStatistics = ManipulatorStatistics.GetNativeBufferPtr();
  2448. registerManipulatorsBridgeParams.ManipulatorParams = NativeManipData;
  2449. registerManipulatorsBridgeParams.SDFObjectCount = ManipulatorManager.SDFObjectList.Count;
  2450. registerManipulatorsBridgeParams.SDFObjectData = NativeSDFData;
  2451. registerManipulatorsBridgeParams.ManipIndices = gcparamBuffer2.AddrOfPinnedObject();
  2452. registerManipulatorsBridgeParams.EmbeddingsTexture = MakeTextureNativeBridge(EmbeddingsTexture);
  2453. registerManipulatorsBridgeParams.SDFGridTexture = MakeTextureNativeBridge(SDFGridTexture);
  2454. registerManipulatorsBridgeParams.HeightmapTexture = MakeTextureNativeBridge(HeightmapTexture);
  2455. GCHandle embeddingDataHandle = default(GCHandle);
  2456. if (ManipulatorManager.Embeddings.Length > 0)
  2457. {
  2458. embeddingDataHandle = GCHandle.Alloc(ManipulatorManager.Embeddings, GCHandleType.Pinned);
  2459. registerManipulatorsBridgeParams.EmbeddigsData.dataSize =
  2460. Marshal.SizeOf(new Color32()) * ManipulatorManager.Embeddings.Length;
  2461. registerManipulatorsBridgeParams.EmbeddigsData.data = embeddingDataHandle.AddrOfPinnedObject();
  2462. registerManipulatorsBridgeParams.EmbeddigsData.rowPitch =
  2463. Marshal.SizeOf(new Color32()) * EmbeddingsTexture.width;
  2464. registerManipulatorsBridgeParams.EmbeddigsData.dimensionX = EmbeddingsTexture.width;
  2465. registerManipulatorsBridgeParams.EmbeddigsData.dimensionY = EmbeddingsTexture.height;
  2466. registerManipulatorsBridgeParams.EmbeddigsData.dimensionZ = EmbeddingsTexture.depth;
  2467. }
  2468. GCHandle sdfGridHandle = default(GCHandle);
  2469. if (ManipulatorManager.SDFGrid.Length > 0)
  2470. {
  2471. sdfGridHandle = GCHandle.Alloc(ManipulatorManager.SDFGrid, GCHandleType.Pinned);
  2472. registerManipulatorsBridgeParams.SDFGridData.dataSize =
  2473. Marshal.SizeOf(new byte()) * ManipulatorManager.SDFGrid.Length;
  2474. registerManipulatorsBridgeParams.SDFGridData.data = sdfGridHandle.AddrOfPinnedObject();
  2475. registerManipulatorsBridgeParams.SDFGridData.rowPitch =
  2476. Marshal.SizeOf(new byte()) * 2 * SDFGridTexture.width;
  2477. registerManipulatorsBridgeParams.SDFGridData.dimensionX = SDFGridTexture.width;
  2478. registerManipulatorsBridgeParams.SDFGridData.dimensionY = SDFGridTexture.height;
  2479. registerManipulatorsBridgeParams.SDFGridData.dimensionZ = SDFGridTexture.depth;
  2480. }
  2481. IntPtr nativeRegisterManipulatorsBridgeParams =
  2482. Marshal.AllocHGlobal(Marshal.SizeOf(registerManipulatorsBridgeParams));
  2483. Marshal.StructureToPtr(registerManipulatorsBridgeParams, nativeRegisterManipulatorsBridgeParams, true);
  2484. SolverCommandBuffer.Clear();
  2485. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  2486. LiquidBridge.EventID.RegisterManipulators,
  2487. nativeRegisterManipulatorsBridgeParams);
  2488. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  2489. gcparamBuffer2.Free();
  2490. CameraRenderParams = new CameraParams();
  2491. RenderParamsContainer = new RenderParams();
  2492. MeshRenderGlobalParamsContainer = new MeshRenderGlobalParams();
  2493. var registerParticlesBuffersParams = new RegisterParticlesBuffersBridgeParams();
  2494. registerParticlesBuffersParams.PositionMass = GetNativePtr(PositionMass);
  2495. registerParticlesBuffersParams.AffineVelocity0 = GetNativePtr(Affine[0]);
  2496. registerParticlesBuffersParams.AffineVelocity1 = GetNativePtr(Affine[1]);
  2497. registerParticlesBuffersParams.ParticleNumber = GetNativePtr(ParticleNumber);
  2498. IntPtr nativeRegisterParticlesBuffersParams =
  2499. Marshal.AllocHGlobal(Marshal.SizeOf(registerParticlesBuffersParams));
  2500. Marshal.StructureToPtr(registerParticlesBuffersParams, nativeRegisterParticlesBuffersParams, true);
  2501. SolverCommandBuffer.Clear();
  2502. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  2503. LiquidBridge.EventID.RegisterParticlesBuffers,
  2504. nativeRegisterParticlesBuffersParams);
  2505. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  2506. ToFreeOnExit.Add(nativeRegisterParticlesBuffersParams);
  2507. }
  2508. private int GetParticleCountRounded()
  2509. {
  2510. return (int)Math.Ceiling((double)MaxNumParticles / MPM_THREADS) * MPM_THREADS; // round to workgroup size;
  2511. }
  2512. private void InitVolumeTexture(ref RenderTexture volume, GraphicsFormat format)
  2513. {
  2514. if (volume)
  2515. return;
  2516. volume = new RenderTexture(GridSize.x, GridSize.y, 0, format);
  2517. volume.volumeDepth = GridSize.z;
  2518. volume.dimension = UnityEngine.Rendering.TextureDimension.Tex3D;
  2519. volume.enableRandomWrite = true;
  2520. volume.filterMode = FilterMode.Trilinear;
  2521. volume.Create();
  2522. if (!volume.IsCreated())
  2523. {
  2524. volume = null;
  2525. throw new NotSupportedException("Failed to create 3D texture.");
  2526. }
  2527. }
  2528. private void InitializeSolver()
  2529. {
  2530. SimulationInternalTime = 0.0f;
  2531. SimulationInternalFrame = 0;
  2532. MaxFoamParticles = MaterialParameters.MaxFoamParticles;
  2533. GridNodeCount = GridSize[0] * GridSize[1] * GridSize[2];
  2534. GridData = new ComputeBuffer(GridNodeCount * 4, sizeof(uint));
  2535. GridNormal = new ComputeBuffer(GridNodeCount, 4 * sizeof(float));
  2536. GridBlur0 = new ComputeBuffer(GridNodeCount, sizeof(float));
  2537. GridBlur1 = new ComputeBuffer(GridNodeCount, sizeof(float));
  2538. MassCopy = new ComputeBuffer(GridNodeCount, sizeof(float));
  2539. ParticleSpeciesData = new ComputeBuffer(SolverParameters.AdditionalParticleSpecies.Count +
  2540. ZibraLiquidSolverParameters.MAX_RUNTIME_ADDED_SPECIES,
  2541. Marshal.SizeOf(typeof(ParticleSpeciesParameters)));
  2542. Counters = new ComputeBuffer(8, sizeof(uint));
  2543. VertexIDGrid = new ComputeBuffer(GridNodeCount, sizeof(int));
  2544. VertexBuffer0 = CreateGraphicsBuffer(GraphicsBufferType.Vertex, 6 * GridNodeCount, sizeof(uint));
  2545. VertexBuffer1 = CreateGraphicsBuffer(GraphicsBufferType.Vertex, 4 * GridNodeCount, sizeof(uint));
  2546. TransferDataBuffer = new ComputeBuffer(1, sizeof(uint));
  2547. MeshRenderIndexBuffer = CreateGraphicsBuffer(GraphicsBufferType.Index, 3 * GridNodeCount, sizeof(uint));
  2548. #if !ZIBRA_EFFECTS_OTP_VERSION
  2549. if (ActiveRenderingMode == RenderingMode.UnityRender)
  2550. {
  2551. LiquidMesh = new Mesh();
  2552. var layout = new[] {
  2553. new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
  2554. new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3),
  2555. };
  2556. int maxVertexCount = GridNodeCount;
  2557. int maxTriangleCount =
  2558. (int)(maxVertexCount * AdvancedRenderParameters.MaxLiquidMeshSize / 3.0f + ADDITIONAL_VERTICES);
  2559. int indexBufferSize = maxTriangleCount * 3;
  2560. int vertexBufferSize = maxTriangleCount * 2;
  2561. LiquidMesh.SetVertexBufferParams(indexBufferSize, layout);
  2562. LiquidMesh.SetIndexBufferParams(vertexBufferSize, IndexFormat.UInt32);
  2563. LiquidMesh.MarkDynamic();
  2564. LiquidMesh.SetVertices(new Vector3[vertexBufferSize], 0, vertexBufferSize);
  2565. LiquidMesh.SetIndices(new int[indexBufferSize], MeshTopology.Triangles, 0);
  2566. LiquidMesh.bounds = new Bounds(Vector3.zero, ContainerSize);
  2567. LiquidMesh.vertexBufferTarget |= GraphicsBuffer.Target.CopyDestination;
  2568. LiquidMesh.indexBufferTarget |= GraphicsBuffer.Target.CopyDestination;
  2569. }
  2570. #endif
  2571. QuadBuffer = new ComputeBuffer(GridNodeCount, sizeof(int));
  2572. VertexProperties = CreateGraphicsBuffer(GraphicsBufferType.Vertex, GridNodeCount, 6 * sizeof(uint));
  2573. IndexGrid = new ComputeBuffer(GridNodeCount, 2 * sizeof(int));
  2574. InitVolumeTexture(ref GridNormalTexture,
  2575. SystemInfo.IsFormatSupported(GraphicsFormat.R16G16B16A16_SFloat, FormatUsage.LoadStore)
  2576. ? GraphicsFormat.R16G16B16A16_SFloat
  2577. : GraphicsFormat.R32G32B32A32_SFloat);
  2578. GridNormalTexture.name = "GridNormalTexture";
  2579. InitVolumeTexture(ref DensityTexture,
  2580. SystemInfo.IsFormatSupported(GraphicsFormat.R16G16B16A16_SFloat, FormatUsage.LoadStore)
  2581. ? GraphicsFormat.R16G16B16A16_SFloat
  2582. : GraphicsFormat.R32G32B32A32_SFloat);
  2583. DensityTexture.name = "DensityTexture";
  2584. InitVolumeTexture(ref VelocityTexture,
  2585. SystemInfo.IsFormatSupported(GraphicsFormat.R16G16B16A16_SFloat, FormatUsage.LoadStore)
  2586. ? GraphicsFormat.R16G16B16A16_SFloat
  2587. : GraphicsFormat.R32G32B32A32_SFloat);
  2588. VelocityTexture.name = "VelocityTexture";
  2589. int NumParticlesRounded = GetParticleCountRounded();
  2590. PositionMassCopy = new ComputeBuffer(NumParticlesRounded, 4 * sizeof(float));
  2591. TmpSDFBuff = new ComputeBuffer(NumParticlesRounded, sizeof(uint));
  2592. NodeParticlePairs0 = new ComputeBuffer(2 * NumParticlesRounded, sizeof(int));
  2593. NodeParticlePairs1 = new ComputeBuffer(2 * NumParticlesRounded, sizeof(int));
  2594. EffectParticleData0 = new ComputeBuffer(4 * Math.Max(MaxFoamParticles, 1), sizeof(uint));
  2595. EffectParticleData1 = new ComputeBuffer(4 * Math.Max(MaxFoamParticles, 1), sizeof(uint));
  2596. int RadixWorkGroups1 = (int)Math.Ceiling((float)MaxNumParticles / (float)(2 * RADIX_THREADS));
  2597. int RadixWorkGroups2 = (int)Math.Ceiling((float)MaxNumParticles / (float)(RADIX_THREADS * RADIX_THREADS));
  2598. int RadixWorkGroups3 = (int)Math.Ceiling((float)RadixWorkGroups2 / (float)RADIX_THREADS);
  2599. RadixGroupData1 = new ComputeBuffer(RadixWorkGroups1 * HISTO_WIDTH, sizeof(uint));
  2600. RadixGroupData2 = new ComputeBuffer(RadixWorkGroups2 * HISTO_WIDTH, sizeof(uint));
  2601. RadixGroupData3 = new ComputeBuffer((RadixWorkGroups3 + 1) * HISTO_WIDTH, sizeof(uint));
  2602. #if ZIBRA_EFFECTS_DEBUG
  2603. GridData.name = "GridData";
  2604. GridNormal.name = "GridNormal";
  2605. GridBlur0.name = "GridBlur0";
  2606. GridBlur1.name = "GridBlur1";
  2607. MassCopy.name = "MassCopy";
  2608. TmpSDFBuff.name = "TmpSDFBuff";
  2609. IndexGrid.name = "IndexGrid";
  2610. PositionMassCopy.name = "PositionMassCopy";
  2611. NodeParticlePairs0.name = "NodeParticlePairs0";
  2612. NodeParticlePairs1.name = "NodeParticlePairs1";
  2613. RadixGroupData1.name = "RadixGroupData1";
  2614. RadixGroupData2.name = "RadixGroupData2";
  2615. RadixGroupData3.name = "RadixGroupData3";
  2616. ParticleSpeciesData.name = "ParticleSpeciesData";
  2617. #endif
  2618. SetFluidParameters();
  2619. var gcparamBuffer = GCHandle.Alloc(LiquidParameters, GCHandleType.Pinned);
  2620. var registerSolverBuffersBridgeParams = new RegisterSolverBuffersBridgeParams();
  2621. registerSolverBuffersBridgeParams.SimulationParams = gcparamBuffer.AddrOfPinnedObject();
  2622. registerSolverBuffersBridgeParams.ParticleSpeciesCount =
  2623. SolverParameters.AdditionalParticleSpecies.Count + 1;
  2624. registerSolverBuffersBridgeParams.PositionMassCopy = GetNativePtr(PositionMassCopy);
  2625. registerSolverBuffersBridgeParams.GridData = GetNativePtr(GridData);
  2626. registerSolverBuffersBridgeParams.IndexGrid = GetNativePtr(IndexGrid);
  2627. registerSolverBuffersBridgeParams.GridBlur0 = GetNativePtr(GridBlur0);
  2628. registerSolverBuffersBridgeParams.GridBlur1 = GetNativePtr(GridBlur1);
  2629. registerSolverBuffersBridgeParams.MassCopy = GetNativePtr(MassCopy);
  2630. registerSolverBuffersBridgeParams.TmpSDFBuff = GetNativePtr(TmpSDFBuff);
  2631. registerSolverBuffersBridgeParams.GridNormal = GetNativePtr(GridNormal);
  2632. registerSolverBuffersBridgeParams.NodeParticlePairs0 = GetNativePtr(NodeParticlePairs0);
  2633. registerSolverBuffersBridgeParams.NodeParticlePairs1 = GetNativePtr(NodeParticlePairs1);
  2634. registerSolverBuffersBridgeParams.EffectParticleData0 = GetNativePtr(EffectParticleData0);
  2635. registerSolverBuffersBridgeParams.EffectParticleData1 = GetNativePtr(EffectParticleData1);
  2636. registerSolverBuffersBridgeParams.RadixGroupData1 = GetNativePtr(RadixGroupData1);
  2637. registerSolverBuffersBridgeParams.RadixGroupData2 = GetNativePtr(RadixGroupData2);
  2638. registerSolverBuffersBridgeParams.RadixGroupData3 = GetNativePtr(RadixGroupData3);
  2639. registerSolverBuffersBridgeParams.Counters = GetNativePtr(Counters);
  2640. registerSolverBuffersBridgeParams.VertexIDGrid = GetNativePtr(VertexIDGrid);
  2641. registerSolverBuffersBridgeParams.VertexBuffer0 = GetNativePtr(VertexBuffer0);
  2642. registerSolverBuffersBridgeParams.VertexBuffer1 = GetNativePtr(VertexBuffer1);
  2643. registerSolverBuffersBridgeParams.QuadBuffer = GetNativePtr(QuadBuffer);
  2644. registerSolverBuffersBridgeParams.GridDensity = MakeTextureNativeBridge(DensityTexture);
  2645. registerSolverBuffersBridgeParams.GridVelocity = MakeTextureNativeBridge(VelocityTexture);
  2646. registerSolverBuffersBridgeParams.GridNormals = MakeTextureNativeBridge(GridNormalTexture);
  2647. #if !ZIBRA_EFFECTS_OTP_VERSION
  2648. if (ActiveRenderingMode == RenderingMode.UnityRender)
  2649. {
  2650. registerSolverBuffersBridgeParams.UnityMeshVertexBuffer = LiquidMesh.GetNativeVertexBufferPtr(0);
  2651. registerSolverBuffersBridgeParams.UnityMeshIndexBuffer = LiquidMesh.GetNativeIndexBufferPtr();
  2652. }
  2653. else
  2654. #endif
  2655. {
  2656. registerSolverBuffersBridgeParams.UnityMeshVertexBuffer = IntPtr.Zero;
  2657. registerSolverBuffersBridgeParams.UnityMeshIndexBuffer = IntPtr.Zero;
  2658. }
  2659. registerSolverBuffersBridgeParams.TransferDataBuffer = GetNativePtr(TransferDataBuffer);
  2660. registerSolverBuffersBridgeParams.MeshRenderIndexBuffer = GetNativePtr(MeshRenderIndexBuffer);
  2661. registerSolverBuffersBridgeParams.VertexData = GetNativePtr(VertexProperties);
  2662. registerSolverBuffersBridgeParams.ParticleSpeciesData = GetNativePtr(ParticleSpeciesData);
  2663. IntPtr nativeRegisterSolverBuffersBridgeParams =
  2664. Marshal.AllocHGlobal(Marshal.SizeOf(registerSolverBuffersBridgeParams));
  2665. Marshal.StructureToPtr(registerSolverBuffersBridgeParams, nativeRegisterSolverBuffersBridgeParams, true);
  2666. SolverCommandBuffer.Clear();
  2667. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  2668. LiquidBridge.EventID.RegisterSolverBuffers,
  2669. nativeRegisterSolverBuffersBridgeParams);
  2670. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  2671. gcparamBuffer.Free();
  2672. SolverCommandBuffer.Clear();
  2673. CopyDepthID = MaterialParameters.RendererCompute.FindKernel("CS_CopyDepth");
  2674. ToFreeOnExit.Add(nativeRegisterSolverBuffersBridgeParams);
  2675. }
  2676. private void Update()
  2677. {
  2678. if (!Initialized)
  2679. {
  2680. return;
  2681. }
  2682. ZibraLiquidGPUGarbageCollector.GCUpdateWrapper();
  2683. #if UNITY_EDITOR
  2684. if (!UnityEditor.EditorApplication.isPlaying)
  2685. {
  2686. return;
  2687. }
  2688. #endif
  2689. if (!UseFixedTimestep)
  2690. UpdateSimulation(Time.smoothDeltaTime);
  2691. UpdateReadback();
  2692. #if ZIBRA_EFFECTS_PROFILING_ENABLED
  2693. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan)
  2694. {
  2695. UpdateDebugTimestamps();
  2696. }
  2697. #endif
  2698. }
  2699. private void FixedUpdate()
  2700. {
  2701. #if UNITY_EDITOR
  2702. if (!UnityEditor.EditorApplication.isPlaying)
  2703. {
  2704. return;
  2705. }
  2706. #endif
  2707. if (UseFixedTimestep)
  2708. UpdateSimulation(Time.fixedDeltaTime);
  2709. }
  2710. #if ZIBRA_EFFECTS_PROFILING_ENABLED
  2711. public void UpdateDebugTimestamps()
  2712. {
  2713. if (!IsSimulationEnabled())
  2714. {
  2715. return;
  2716. }
  2717. DebugTimestampsItemsCount =
  2718. LiquidBridge.ZibraLiquid_GetDebugTimestamps(CurrentInstanceID, DebugTimestampsItems);
  2719. }
  2720. #endif
  2721. private void UpdateReadback()
  2722. {
  2723. if (!IsSimulationEnabled())
  2724. {
  2725. return;
  2726. }
  2727. SolverCommandBuffer.Clear();
  2728. // This must be called at most ONCE PER FRAME
  2729. // Otherwise you'll get deadlock
  2730. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  2731. LiquidBridge.EventID.UpdateReadback);
  2732. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  2733. /// ParticleNumber GPUReadback
  2734. UInt32 size = sizeof(UInt32);
  2735. IntPtr readbackData = LiquidBridge.ZibraLiquid_GPUReadbackGetData(CurrentInstanceID, size);
  2736. if (readbackData != IntPtr.Zero)
  2737. {
  2738. CurrentParticleNumber = Marshal.ReadInt32(readbackData);
  2739. }
  2740. UpdateManipulatorStatistics();
  2741. }
  2742. /// <summary>
  2743. /// Update the material parameters
  2744. /// </summary>
  2745. private bool SetMaterialParams(Camera cam)
  2746. {
  2747. bool isDirty = false;
  2748. CameraResources camRes = CameraResourcesMap[cam];
  2749. Material usedUpscaleMaterial = EnableDownscale ? MaterialParameters.UpscaleMaterial : null;
  2750. isDirty = camRes.UpscaleMaterial.SetMaterial(usedUpscaleMaterial) || isDirty;
  2751. bool usingMainMaterial = ActiveRenderingMode == RenderingMode.MeshRender;
  2752. Material CurrentSharedMaterial = usingMainMaterial ? MaterialParameters.FluidMeshMaterial : null;
  2753. isDirty = camRes.LiquidMaterial.SetMaterial(CurrentSharedMaterial) || isDirty;
  2754. Material CurrentMaterial = camRes.LiquidMaterial.CurrentMaterial;
  2755. if (usingMainMaterial)
  2756. {
  2757. if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
  2758. {
  2759. #if UNITY_PIPELINE_HDRP
  2760. if (CustomLightHDRP == null)
  2761. Debug.LogError("No Custom Light set in Zibra Liquid.");
  2762. else
  2763. CurrentMaterial.SetVector("WorldSpaceLightPos", CustomLightHDRP.transform.position);
  2764. if (ReflectionProbeHDRP == null)
  2765. Debug.LogError("No reflection probe added to Zibra Liquid.");
  2766. #endif // UNITY_PIPELINE_HDRP
  2767. }
  2768. else
  2769. {
  2770. CurrentMaterial.SetKeyword(new LocalKeyword(CurrentMaterial.shader, "USE_CUBEMAP_REFRACTION"),
  2771. MaterialParameters.UseCubemapRefraction);
  2772. if (ReflectionProbeBRP != null) // custom reflection probe
  2773. {
  2774. CurrentMaterial.EnableKeyword("CUSTOM_REFLECTION_PROBE");
  2775. CurrentMaterial.SetTexture("ReflectionProbe", ReflectionProbeBRP.texture);
  2776. CurrentMaterial.SetVector("ReflectionProbe_HDR", ReflectionProbeBRP.textureHDRDecodeValues);
  2777. CurrentMaterial.SetVector("ReflectionProbe_BoxMax", ReflectionProbeBRP.bounds.max);
  2778. CurrentMaterial.SetVector("ReflectionProbe_BoxMin", ReflectionProbeBRP.bounds.min);
  2779. CurrentMaterial.SetVector("ReflectionProbe_ProbePosition",
  2780. ReflectionProbeBRP.transform.position);
  2781. }
  2782. else
  2783. {
  2784. CurrentMaterial.DisableKeyword("CUSTOM_REFLECTION_PROBE");
  2785. }
  2786. }
  2787. CurrentMaterial.SetFloat("AbsorptionAmount", MaterialParameters.AbsorptionAmount);
  2788. CurrentMaterial.SetFloat("ScatteringAmount", MaterialParameters.ScatteringAmount);
  2789. CurrentMaterial.SetFloat("Metalness", MaterialParameters.Metalness);
  2790. CurrentMaterial.SetFloat("FresnelStrength", MaterialParameters.FresnelStrength);
  2791. CurrentMaterial.SetFloat("RefractionDistortion", MaterialParameters.IndexOfRefraction - 1.0f);
  2792. CurrentMaterial.SetFloat("LiquidIOR", MaterialParameters.IndexOfRefraction);
  2793. CurrentMaterial.SetFloat("Roughness", MaterialParameters.Roughness);
  2794. CurrentMaterial.SetVector("RefractionColor", MaterialParameters.Color);
  2795. CurrentMaterial.SetVector("ReflectionColor", MaterialParameters.ReflectionColor);
  2796. CurrentMaterial.SetVector("EmissiveColor", MaterialParameters.EmissiveColor);
  2797. CurrentMaterial.SetVector("Material1Color", MaterialParameters.Material1.Color);
  2798. CurrentMaterial.SetVector("Material2Color", MaterialParameters.Material2.Color);
  2799. CurrentMaterial.SetVector("Material3Color", MaterialParameters.Material3.Color);
  2800. CurrentMaterial.SetVector("Material1Emission", MaterialParameters.Material1.EmissiveColor);
  2801. CurrentMaterial.SetVector("Material2Emission", MaterialParameters.Material2.EmissiveColor);
  2802. CurrentMaterial.SetVector("Material3Emission", MaterialParameters.Material3.EmissiveColor);
  2803. CurrentMaterial.SetVector("MatMetalness", new Vector3(MaterialParameters.Material1.Metalness,
  2804. MaterialParameters.Material2.Metalness,
  2805. MaterialParameters.Material3.Metalness));
  2806. CurrentMaterial.SetVector("MatAbsorption", new Vector3(MaterialParameters.Material1.AbsorptionAmount,
  2807. MaterialParameters.Material2.AbsorptionAmount,
  2808. MaterialParameters.Material3.AbsorptionAmount));
  2809. CurrentMaterial.SetVector("MatScattering", new Vector3(MaterialParameters.Material1.ScatteringAmount,
  2810. MaterialParameters.Material2.ScatteringAmount,
  2811. MaterialParameters.Material3.ScatteringAmount));
  2812. CurrentMaterial.SetVector("MatRoughness", new Vector3(MaterialParameters.Material1.Roughness,
  2813. MaterialParameters.Material2.Roughness,
  2814. MaterialParameters.Material3.Roughness));
  2815. #if UNITY_PIPELINE_HDRP
  2816. CurrentMaterial.SetVector("LightColor",
  2817. CustomLightHDRP.color * Mathf.Log(CustomLightHDRP.intensity) / 8.0f);
  2818. CurrentMaterial.SetVector("LightDirection", CustomLightHDRP.transform.rotation * new Vector3(0, 0, -1));
  2819. #endif
  2820. CurrentMaterial.SetVector("ContainerScale", ContainerSize);
  2821. CurrentMaterial.SetVector("ContainerPosition", transform.position);
  2822. CurrentMaterial.SetVector("GridSize", (Vector3)GridSize);
  2823. CurrentMaterial.SetFloat("RayMarchResolutionDownscale",
  2824. AdvancedRenderParameters.RayMarchingResolutionDownscale);
  2825. CurrentMaterial.SetFloat("RefractionMinimumDepth", 1e-4f);
  2826. CurrentMaterial.SetFloat("RefractionDepthBias", 1.25f);
  2827. CurrentMaterial.SetTexture("GridNormals", GridNormalTexture);
  2828. CurrentMaterial.SetTexture("MeshRenderData", Color0);
  2829. CurrentMaterial.SetTexture("MeshDepth", Depth, RenderTextureSubElement.Depth);
  2830. CurrentMaterial.SetTexture("GridDensity", DensityTexture);
  2831. if (AdvancedRenderParameters.RefractionBounces ==
  2832. ZibraLiquidAdvancedRenderParameters.RayMarchingBounces.TwoBounces)
  2833. {
  2834. if (MeshRenderGlobalParamsContainer.TwoBouncesEnabled == 0)
  2835. isDirty = true;
  2836. MeshRenderGlobalParamsContainer.TwoBouncesEnabled = 1;
  2837. }
  2838. else
  2839. {
  2840. if (MeshRenderGlobalParamsContainer.TwoBouncesEnabled == 1)
  2841. isDirty = true;
  2842. MeshRenderGlobalParamsContainer.TwoBouncesEnabled = 0;
  2843. }
  2844. #if UNITY_IOS && !UNITY_EDITOR
  2845. if (!EnableDownscale)
  2846. {
  2847. CurrentMaterial.DisableKeyword("FLIP_BACKGROUND_TEXTURE");
  2848. CurrentMaterial.EnableKeyword("FLIP_NATIVE_TEXTURES");
  2849. CurrentMaterial.EnableKeyword("FLIP_PARTICLES_TEXTURE");
  2850. }
  2851. else
  2852. {
  2853. CurrentMaterial.DisableKeyword("FLIP_NATIVE_TEXTURES");
  2854. CurrentMaterial.EnableKeyword("FLIP_BACKGROUND_TEXTURE");
  2855. CurrentMaterial.DisableKeyword("FLIP_PARTICLES_TEXTURE");
  2856. }
  2857. #endif
  2858. #if UNITY_ANDROID && !UNITY_EDITOR
  2859. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan && !EnableDownscale)
  2860. {
  2861. if (!EnableDownscale)
  2862. {
  2863. CurrentMaterial.DisableKeyword("FLIP_BACKGROUND_TEXTURE");
  2864. CurrentMaterial.EnableKeyword("FLIP_NATIVE_TEXTURES");
  2865. }
  2866. else
  2867. {
  2868. CurrentMaterial.DisableKeyword("FLIP_NATIVE_TEXTURES");
  2869. CurrentMaterial.EnableKeyword("FLIP_BACKGROUND_TEXTURE");
  2870. }
  2871. }
  2872. #endif
  2873. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3)
  2874. {
  2875. CurrentMaterial.EnableKeyword("FLIP_PARTICLES_TEXTURE");
  2876. }
  2877. CurrentMaterial.SetTexture("Background", GetBackgroundToBind(cam));
  2878. CurrentMaterial.SetTexture("FluidColor", Color0);
  2879. if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
  2880. {
  2881. #if UNITY_PIPELINE_HDRP
  2882. CurrentMaterial.SetTexture("ReflectionProbe", ReflectionProbeHDRP.texture);
  2883. CurrentMaterial.SetVector("ReflectionProbe_HDR", new Vector4(0.01f, 1.0f));
  2884. CurrentMaterial.SetVector("ReflectionProbe_BoxMax", ReflectionProbeHDRP.bounds.max);
  2885. CurrentMaterial.SetVector("ReflectionProbe_BoxMin", ReflectionProbeHDRP.bounds.min);
  2886. CurrentMaterial.SetVector("ReflectionProbe_ProbePosition", ReflectionProbeHDRP.transform.position);
  2887. CurrentMaterial.EnableKeyword("HDRP");
  2888. #endif
  2889. }
  2890. }
  2891. Material usedSDFRenderMaterial = VisualizeSceneSDF ? MaterialParameters.SDFRenderMaterial : null;
  2892. isDirty = camRes.SDFRenderMaterial.SetMaterial(usedSDFRenderMaterial) || isDirty;
  2893. if (VisualizeSceneSDF)
  2894. {
  2895. Material CurrentSDFRenderMaterial = camRes.SDFRenderMaterial.CurrentMaterial;
  2896. CurrentSDFRenderMaterial.SetTexture("SDFRender", Color0);
  2897. if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
  2898. {
  2899. #if UNITY_PIPELINE_HDRP
  2900. CurrentSDFRenderMaterial.SetVector("LightColor", CustomLightHDRP.color *
  2901. Mathf.Log(CustomLightHDRP.intensity) / 8.0f);
  2902. CurrentSDFRenderMaterial.SetVector("LightDirection",
  2903. CustomLightHDRP.transform.rotation * new Vector3(0, 0, -1));
  2904. CurrentSDFRenderMaterial.EnableKeyword("HDRP");
  2905. #endif
  2906. }
  2907. }
  2908. return isDirty;
  2909. }
  2910. internal Vector2Int ApplyDownscaleFactor(Vector2Int val)
  2911. {
  2912. if (!EnableDownscale)
  2913. return val;
  2914. return new Vector2Int((int)(val.x * DownscaleFactor), (int)(val.y * DownscaleFactor));
  2915. }
  2916. private Vector2Int ApplyRenderPipelineRenderScale(Vector2Int val, float renderPipelineRenderScale)
  2917. {
  2918. return new Vector2Int((int)(val.x * renderPipelineRenderScale), (int)(val.y * renderPipelineRenderScale));
  2919. }
  2920. private bool CreateTexture(ref RenderTexture texture, Vector2Int resolution, FilterMode filterMode, int depth,
  2921. RenderTextureFormat format, bool enableRandomWrite = false)
  2922. {
  2923. if (texture == null || texture.width != resolution.x || texture.height != resolution.y)
  2924. {
  2925. ZibraLiquidGPUGarbageCollector.SafeRelease(texture);
  2926. texture = null;
  2927. texture = new RenderTexture(resolution.x, resolution.y, depth, format);
  2928. texture.enableRandomWrite = enableRandomWrite;
  2929. texture.filterMode = filterMode;
  2930. texture.Create();
  2931. return true;
  2932. }
  2933. return false;
  2934. }
  2935. private bool CreateRenderBuffer(ref ComputeBuffer buffer, Vector2Int resolution)
  2936. {
  2937. if (buffer == null || buffer.count != resolution.x * resolution.y)
  2938. {
  2939. ZibraLiquidGPUGarbageCollector.SafeRelease(buffer);
  2940. buffer = new ComputeBuffer(resolution.x * resolution.y * 3, sizeof(uint));
  2941. return true;
  2942. }
  2943. return false;
  2944. }
  2945. // Returns resolution that is enough for all cameras
  2946. private Vector2Int GetRequiredTextureResolution()
  2947. {
  2948. if (CamRenderResolutions.Count == 0)
  2949. Debug.Log("camRenderResolutions dictionary was empty when GetRequiredTextureResolution was called.");
  2950. Vector2Int result = new Vector2Int(0, 0);
  2951. foreach (var item in CamRenderResolutions)
  2952. {
  2953. result = Vector2Int.Max(result, item.Value);
  2954. }
  2955. return result;
  2956. }
  2957. internal bool IsBackgroundCopyNeeded(Camera cam)
  2958. {
  2959. return !EnableDownscale || (cam.activeTexture == null);
  2960. }
  2961. private RenderTexture GetBackgroundToBind(Camera cam)
  2962. {
  2963. if (!IsBackgroundCopyNeeded(cam))
  2964. return cam.activeTexture;
  2965. return CameraResourcesMap[cam].Background;
  2966. }
  2967. /// <summary>
  2968. /// Removes disabled/inactive cameras from cameraResources
  2969. /// </summary>
  2970. private void UpdateCameraList()
  2971. {
  2972. List<Camera> toRemove = new List<Camera>();
  2973. foreach (var camResource in CameraResourcesMap)
  2974. {
  2975. if (camResource.Key == null ||
  2976. (!camResource.Key.isActiveAndEnabled && camResource.Key.cameraType != CameraType.SceneView))
  2977. {
  2978. toRemove.Add(camResource.Key);
  2979. continue;
  2980. }
  2981. }
  2982. foreach (var cam in toRemove)
  2983. {
  2984. if (CameraResourcesMap[cam].Background)
  2985. {
  2986. CameraResourcesMap[cam].Background.Release();
  2987. CameraResourcesMap[cam].Background = null;
  2988. }
  2989. CameraResourcesMap.Remove(cam);
  2990. }
  2991. }
  2992. private void UpdateCameraResolution(Camera cam, float renderPipelineRenderScale)
  2993. {
  2994. Vector2Int cameraResolution = new Vector2Int(cam.pixelWidth, cam.pixelHeight);
  2995. cameraResolution = ApplyRenderPipelineRenderScale(cameraResolution, renderPipelineRenderScale);
  2996. CamNativeResolutions[cam] = cameraResolution;
  2997. Vector2Int cameraResolutionDownscaled = ApplyDownscaleFactor(cameraResolution);
  2998. CamRenderResolutions[cam] = cameraResolutionDownscaled;
  2999. }
  3000. /// <summary>
  3001. /// Update Native textures for a given camera
  3002. /// </summary>
  3003. private bool UpdateNativeTextures(Camera cam, float renderPipelineRenderScale)
  3004. {
  3005. UpdateCameraList();
  3006. Vector2Int cameraResolution = new Vector2Int(cam.pixelWidth, cam.pixelHeight);
  3007. cameraResolution = ApplyRenderPipelineRenderScale(cameraResolution, renderPipelineRenderScale);
  3008. Vector2Int textureResolution = GetRequiredTextureResolution();
  3009. int pixelCount = textureResolution.x * textureResolution.y;
  3010. if (!Cameras.Contains(cam))
  3011. {
  3012. Cameras.Add(cam);
  3013. }
  3014. int CameraID = Cameras.IndexOf(cam);
  3015. bool isGlobalTexturesDirty = false;
  3016. bool isCameraDirty = CameraResourcesMap[cam].IsDirty;
  3017. FilterMode defaultFilter = EnableDownscale ? FilterMode.Bilinear : FilterMode.Point;
  3018. if (IsBackgroundCopyNeeded(cam))
  3019. {
  3020. if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
  3021. {
  3022. #if UNITY_PIPELINE_HDRP
  3023. isCameraDirty = CreateTexture(ref CameraResourcesMap[cam].Background, cameraResolution,
  3024. FilterMode.Point, 0, RenderTextureFormat.ARGBHalf) ||
  3025. isCameraDirty;
  3026. #endif
  3027. }
  3028. else
  3029. {
  3030. var format =
  3031. SystemInfo.IsFormatSupported(GraphicsFormat.B10G11R11_UFloatPack32, FormatUsage.LoadStore)
  3032. ? RenderTextureFormat.RGB111110Float
  3033. : RenderTextureFormat.ARGB32; // 8 bits per component
  3034. isCameraDirty = CreateTexture(ref CameraResourcesMap[cam].Background, cameraResolution,
  3035. FilterMode.Point, 0, format) ||
  3036. isCameraDirty;
  3037. }
  3038. }
  3039. else
  3040. {
  3041. if (CameraResourcesMap[cam].Background != null)
  3042. {
  3043. isCameraDirty = true;
  3044. CameraResourcesMap[cam].Background.Release();
  3045. CameraResourcesMap[cam].Background = null;
  3046. }
  3047. }
  3048. isGlobalTexturesDirty = CreateTexture(ref DepthTexture, cameraResolution, defaultFilter, 32,
  3049. RenderTextureFormat.RFloat, true) ||
  3050. isGlobalTexturesDirty;
  3051. isGlobalTexturesDirty =
  3052. CreateTexture(ref Depth, textureResolution, defaultFilter, 32, RenderTextureFormat.Depth) ||
  3053. isGlobalTexturesDirty;
  3054. isGlobalTexturesDirty = CreateTexture(ref Color0, textureResolution, FilterMode.Point, 0,
  3055. RenderTextureFormat.ARGBFloat, true) ||
  3056. isGlobalTexturesDirty;
  3057. isGlobalTexturesDirty = CreateTexture(ref Color1, textureResolution, FilterMode.Point, 0,
  3058. RenderTextureFormat.ARGBFloat, true) ||
  3059. isGlobalTexturesDirty;
  3060. isGlobalTexturesDirty = CreateTexture(ref Color2, textureResolution, FilterMode.Point, 0,
  3061. RenderTextureFormat.ARGBFloat, true) ||
  3062. isGlobalTexturesDirty;
  3063. isGlobalTexturesDirty = CreateTexture(ref UpscaleColor, textureResolution, FilterMode.Point, 0,
  3064. RenderTextureFormat.ARGBHalf, false) ||
  3065. isGlobalTexturesDirty;
  3066. isGlobalTexturesDirty = CreateTexture(ref UpscaleDepth, textureResolution, FilterMode.Point, 32,
  3067. RenderTextureFormat.Depth, false) ||
  3068. isGlobalTexturesDirty;
  3069. isGlobalTexturesDirty = CreateTexture(ref ParticlesRT, textureResolution, FilterMode.Point, 0,
  3070. RenderTextureFormat.ARGBFloat, true) ||
  3071. isGlobalTexturesDirty;
  3072. if (isGlobalTexturesDirty || isCameraDirty)
  3073. {
  3074. if (isGlobalTexturesDirty)
  3075. {
  3076. foreach (var camera in CameraResourcesMap)
  3077. {
  3078. camera.Value.IsDirty = true;
  3079. }
  3080. CurrentTextureResolution = textureResolution;
  3081. }
  3082. CameraResourcesMap[cam].IsDirty = false;
  3083. var registerRenderResourcesBridgeParams = new RegisterRenderResourcesBridgeParams();
  3084. registerRenderResourcesBridgeParams.Depth = MakeTextureNativeBridge(Depth);
  3085. registerRenderResourcesBridgeParams.Color0 = MakeTextureNativeBridge(Color0);
  3086. registerRenderResourcesBridgeParams.Color1 = MakeTextureNativeBridge(Color1);
  3087. registerRenderResourcesBridgeParams.Color2 = MakeTextureNativeBridge(Color2);
  3088. registerRenderResourcesBridgeParams.SceneDepth = MakeTextureNativeBridge(DepthTexture);
  3089. registerRenderResourcesBridgeParams.ParticlesRT = MakeTextureNativeBridge(ParticlesRT);
  3090. IntPtr nativeRegisterRenderResourcesBridgeParams =
  3091. Marshal.AllocHGlobal(Marshal.SizeOf(registerRenderResourcesBridgeParams));
  3092. Marshal.StructureToPtr(registerRenderResourcesBridgeParams, nativeRegisterRenderResourcesBridgeParams,
  3093. true);
  3094. SolverCommandBuffer.Clear();
  3095. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  3096. LiquidBridge.EventID.RegisterRenderResources,
  3097. nativeRegisterRenderResourcesBridgeParams);
  3098. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  3099. LiquidBridge.EventID.InitializeGraphicsPipeline);
  3100. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  3101. ToFreeOnExit.Add(nativeRegisterRenderResourcesBridgeParams);
  3102. }
  3103. return isGlobalTexturesDirty || isCameraDirty;
  3104. }
  3105. private int IntDivCeil(int a, int b)
  3106. {
  3107. return (a + b - 1) / b;
  3108. }
  3109. /// <summary>
  3110. /// Render the liquid from the native plugin
  3111. /// </summary>
  3112. /// <param name="cmdBuffer">Command Buffer to add the rendering commands to</param>
  3113. internal void RenderLiquidNative(CommandBuffer cmdBuffer, Camera cam, Rect? viewport = null)
  3114. {
  3115. var renderEffectParticles = MaterialParametersInternal.EnableFoam && MaxFoamParticles > 0;
  3116. ForceCloseCommandEncoder(cmdBuffer);
  3117. if (renderEffectParticles)
  3118. {
  3119. cmdBuffer.SetComputeVectorParam(MaterialParameters.RendererCompute, "Resolution",
  3120. new Vector2(cam.pixelWidth, cam.pixelHeight));
  3121. cmdBuffer.SetComputeTextureParam(MaterialParameters.RendererCompute, CopyDepthID, "_DepthOUT", DepthTexture);
  3122. cmdBuffer.DispatchCompute(MaterialParameters.RendererCompute, CopyDepthID, IntDivCeil(cam.pixelWidth, DEPTH_COPY_WORKGROUP),
  3123. IntDivCeil(cam.pixelHeight, DEPTH_COPY_WORKGROUP), 1);
  3124. }
  3125. LiquidBridge.SubmitInstanceEvent(cmdBuffer, CurrentInstanceID, LiquidBridge.EventID.SetCameraParams,
  3126. CamNativeParams[cam]);
  3127. LiquidBridge.SubmitInstanceEvent(cmdBuffer, CurrentInstanceID,
  3128. LiquidBridge.EventID.UpdateMeshRenderGlobalParameters,
  3129. CamMeshRenderParams[cam]);
  3130. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan)
  3131. {
  3132. cmdBuffer.SetRenderTarget(Color0, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, Depth,
  3133. RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
  3134. cmdBuffer.ClearRenderTarget(true, true, Color.clear);
  3135. }
  3136. LiquidBridge.SubmitInstanceEvent(cmdBuffer, CurrentInstanceID, LiquidBridge.EventID.DrawLiquid);
  3137. if (renderEffectParticles)
  3138. {
  3139. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan)
  3140. {
  3141. cmdBuffer.SetRenderTarget(ParticlesRT);
  3142. cmdBuffer.ClearRenderTarget(false, true, Color.clear);
  3143. }
  3144. LiquidBridge.SubmitInstanceEvent(cmdBuffer, CurrentInstanceID,
  3145. LiquidBridge.EventID.DrawEffectParticles);
  3146. }
  3147. }
  3148. internal void RenderLiquidMain(CommandBuffer cmdBuffer, Camera cam, Rect? viewport = null)
  3149. {
  3150. switch (ActiveRenderingMode)
  3151. {
  3152. case RenderingMode.MeshRender:
  3153. RenderLiquidMesh(cmdBuffer, cam, viewport);
  3154. break;
  3155. #if !ZIBRA_EFFECTS_OTP_VERSION
  3156. case RenderingMode.UnityRender:
  3157. break;
  3158. #endif
  3159. default:
  3160. Debug.LogError("Unknown Rendering mode");
  3161. break;
  3162. }
  3163. }
  3164. /// <summary>
  3165. /// Upscale the liquid surface to currently bound render target
  3166. /// Used for URP where we can't change render targets
  3167. /// Used for URP where we can't change render targets
  3168. /// </summary>
  3169. internal void UpscaleLiquidDirect(CommandBuffer cmdBuffer, Camera cam,
  3170. RenderTargetIdentifier? sourceColorTexture = null,
  3171. RenderTargetIdentifier? sourceDepthTexture = null, Rect? viewport = null)
  3172. {
  3173. Material CurrentUpscaleMaterial = CameraResourcesMap[cam].UpscaleMaterial.CurrentMaterial;
  3174. Vector2Int cameraNativeResolution = CamNativeResolutions[cam];
  3175. cmdBuffer.SetViewport(new Rect(0, 0, cameraNativeResolution.x, cameraNativeResolution.y));
  3176. if (sourceColorTexture == null)
  3177. {
  3178. cmdBuffer.SetGlobalTexture("ShadedLiquid", UpscaleColor);
  3179. cmdBuffer.SetGlobalTexture("ShadedLiquidDepth", UpscaleDepth);
  3180. }
  3181. else
  3182. {
  3183. cmdBuffer.SetGlobalTexture("ShadedLiquid", sourceColorTexture.Value);
  3184. cmdBuffer.SetGlobalTexture("ShadedLiquidDepth", sourceDepthTexture.Value);
  3185. }
  3186. cmdBuffer.DrawProcedural(transform.localToWorldMatrix, CurrentUpscaleMaterial, 0, MeshTopology.Triangles,
  3187. 6);
  3188. }
  3189. /// <summary>
  3190. /// Render the liquid surface
  3191. /// Camera's targetTexture must be copied to cameraResources[cam].background
  3192. /// using corresponding Render Pipeline before calling this method
  3193. /// </summary>
  3194. /// <param name="cmdBuffer">Command Buffer to add the rendering commands to</param>
  3195. internal void RenderFluid(CommandBuffer cmdBuffer, Camera cam, RenderTargetIdentifier? renderTargetParam = null,
  3196. RenderTargetIdentifier? depthTargetParam = null, Rect? viewport = null)
  3197. {
  3198. RenderTargetIdentifier renderTarget =
  3199. renderTargetParam ?? new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget);
  3200. RenderTargetIdentifier depthTarget =
  3201. depthTargetParam ?? new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget);
  3202. // Render fluid to temporary RenderTexture if downscale enabled
  3203. // Otherwise render straight to final RenderTexture
  3204. if (EnableDownscale)
  3205. {
  3206. cmdBuffer.SetRenderTarget(UpscaleColor, UpscaleDepth);
  3207. cmdBuffer.ClearRenderTarget(true, true, Color.clear);
  3208. }
  3209. else
  3210. {
  3211. cmdBuffer.SetRenderTarget(renderTarget, depthTarget);
  3212. }
  3213. RenderLiquidMain(cmdBuffer, cam, viewport);
  3214. if (VisualizeSceneSDF)
  3215. {
  3216. LiquidBridge.SubmitInstanceEvent(cmdBuffer, CurrentInstanceID, LiquidBridge.EventID.RenderSDF);
  3217. if (EnableDownscale)
  3218. {
  3219. cmdBuffer.SetRenderTarget(UpscaleColor, UpscaleDepth);
  3220. }
  3221. else
  3222. {
  3223. cmdBuffer.SetRenderTarget(renderTarget, depthTarget);
  3224. }
  3225. RenderSDFVisualization(cmdBuffer, cam, viewport);
  3226. }
  3227. // If downscale enabled then we need to blend it on top of final RenderTexture
  3228. if (EnableDownscale)
  3229. {
  3230. cmdBuffer.SetRenderTarget(renderTarget, depthTarget);
  3231. UpscaleLiquidDirect(cmdBuffer, cam, null, null, viewport);
  3232. }
  3233. }
  3234. /// <summary>
  3235. /// Render the liquid surface
  3236. /// Camera's targetTexture must be copied to cameraResources[cam].background
  3237. /// using corresponding Render Pipeline before calling this method
  3238. /// </summary>
  3239. /// <param name="cmdBuffer">Command Buffer to add the rendering commands to</param>
  3240. private void RenderLiquidMesh(CommandBuffer cmdBuffer, Camera cam, Rect? viewport = null)
  3241. {
  3242. Vector2Int cameraRenderResolution = CamRenderResolutions[cam];
  3243. Material CurrentMaterial = CameraResourcesMap[cam].LiquidMaterial.CurrentMaterial;
  3244. // Render fluid to temporary RenderTexture if downscale enabled
  3245. // Otherwise render straight to final RenderTexture
  3246. if (EnableDownscale)
  3247. {
  3248. cmdBuffer.SetViewport(new Rect(0, 0, cameraRenderResolution.x, cameraRenderResolution.y));
  3249. }
  3250. else
  3251. {
  3252. if (viewport != null)
  3253. {
  3254. cmdBuffer.SetViewport(viewport.Value);
  3255. }
  3256. }
  3257. cmdBuffer.SetGlobalTexture("Background", GetBackgroundToBind(cam));
  3258. if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
  3259. {
  3260. #if UNITY_PIPELINE_HDRP
  3261. cmdBuffer.SetGlobalTexture("ReflectionProbe", ReflectionProbeHDRP.texture);
  3262. cmdBuffer.SetGlobalVector("ReflectionProbe_HDR", new Vector4(0.01f, 1.0f));
  3263. cmdBuffer.SetGlobalVector("ReflectionProbe_BoxMax", ReflectionProbeHDRP.bounds.max);
  3264. cmdBuffer.SetGlobalVector("ReflectionProbe_BoxMin", ReflectionProbeHDRP.bounds.min);
  3265. cmdBuffer.SetGlobalVector("ReflectionProbe_ProbePosition", ReflectionProbeHDRP.transform.position);
  3266. CurrentMaterial.EnableKeyword("HDRP");
  3267. #endif
  3268. }
  3269. cmdBuffer.DrawProcedural(transform.localToWorldMatrix, CurrentMaterial, 0, MeshTopology.Triangles, 6);
  3270. }
  3271. internal void RenderSDFVisualization(CommandBuffer cmdBuffer, Camera cam, Rect? viewport = null)
  3272. {
  3273. Vector2Int cameraRenderResolution = CamRenderResolutions[cam];
  3274. Material CurrentMaterial = CameraResourcesMap[cam].SDFRenderMaterial.CurrentMaterial;
  3275. // Render fluid to temporary RenderTexture if downscale enabled
  3276. // Otherwise render straight to final RenderTexture
  3277. if (EnableDownscale)
  3278. {
  3279. cmdBuffer.SetViewport(new Rect(0, 0, cameraRenderResolution.x, cameraRenderResolution.y));
  3280. }
  3281. else
  3282. {
  3283. if (viewport != null)
  3284. {
  3285. cmdBuffer.SetViewport(viewport.Value);
  3286. }
  3287. }
  3288. cmdBuffer.DrawProcedural(transform.localToWorldMatrix, CurrentMaterial, 0, MeshTopology.Triangles, 6);
  3289. }
  3290. /// <summary>
  3291. /// Update the camera parameters for the particle renderer
  3292. /// </summary>
  3293. private void UpdateCamera(Camera cam)
  3294. {
  3295. Vector2Int resolution = CamRenderResolutions[cam];
  3296. Material CurrentMaterial = CameraResourcesMap[cam].LiquidMaterial.CurrentMaterial;
  3297. Material CurrentUpscaleMaterial = CameraResourcesMap[cam].UpscaleMaterial.CurrentMaterial;
  3298. Material CurrentSDFRenderMaterial = CameraResourcesMap[cam].SDFRenderMaterial.CurrentMaterial;
  3299. Matrix4x4 Projection = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true);
  3300. Matrix4x4 ProjectionInverse = Projection.inverse;
  3301. Matrix4x4 View = cam.worldToCameraMatrix;
  3302. Matrix4x4 ViewProjection = Projection * View;
  3303. Matrix4x4 ViewProjectionInverse = ViewProjection.inverse;
  3304. CurrentMaterial.SetVector("Resolution", CameraRenderParams.CameraResolution);
  3305. CameraRenderParams.View = cam.worldToCameraMatrix;
  3306. CameraRenderParams.Projection = Projection;
  3307. CameraRenderParams.ProjectionInverse = ProjectionInverse;
  3308. CameraRenderParams.ViewProjection = ViewProjection;
  3309. CameraRenderParams.ViewProjectionInverse = ViewProjectionInverse;
  3310. CameraRenderParams.EyeRayCameraCoeficients = CalculateEyeRayCameraCoeficients(cam);
  3311. CameraRenderParams.WorldSpaceCameraPos = cam.transform.position;
  3312. CameraRenderParams.CameraResolution = new Vector2(resolution.x, resolution.y);
  3313. CameraRenderParams.CameraID = Cameras.IndexOf(cam);
  3314. CameraRenderParams.CameraDownscaleFactor = EnableDownscale ? DownscaleFactor : 1f;
  3315. { // Same as Unity's built-in _ZBufferParams
  3316. float y = cam.farClipPlane / cam.nearClipPlane;
  3317. float x = 1 - y;
  3318. CameraRenderParams.ZBufferParams = new Vector4(x, y, x / cam.farClipPlane, y / cam.farClipPlane);
  3319. }
  3320. MeshRenderGlobalParamsContainer.LiquidIOR = MaterialParameters.IndexOfRefraction;
  3321. MeshRenderGlobalParamsContainer.RayMarchIsoSurface = AdvancedRenderParameters.RayMarchIsoSurface;
  3322. MeshRenderGlobalParamsContainer.DisableRaymarch = AdvancedRenderParameters.DisableRaymarch ? 1 : 0;
  3323. MeshRenderGlobalParamsContainer.UnderwaterRender = AdvancedRenderParameters.UnderwaterRender ? 1 : 0;
  3324. MeshRenderGlobalParamsContainer.RayMarchMaxSteps = AdvancedRenderParameters.RayMarchMaxSteps;
  3325. MeshRenderGlobalParamsContainer.RayMarchStepSize = AdvancedRenderParameters.RayMarchStepSize;
  3326. MeshRenderGlobalParamsContainer.RayMarchStepFactor = AdvancedRenderParameters.RayMarchStepFactor;
  3327. Vector2 renderingResolution = resolution;
  3328. Vector2 rayMarchResolution = renderingResolution * AdvancedRenderParameters.RayMarchingResolutionDownscale;
  3329. MeshRenderGlobalParamsContainer.RayMarchResolution =
  3330. new Vector2Int((int)rayMarchResolution.x, (int)rayMarchResolution.y);
  3331. MeshRenderGlobalParamsContainer.FoamingIntensity = MaterialParameters.FoamIntensity;
  3332. MeshRenderGlobalParamsContainer.FoamingDecay = MaterialParameters.FoamDecay;
  3333. MeshRenderGlobalParamsContainer.FoamingDecaySmoothness = MaterialParameters.FoamDecaySmoothness;
  3334. MeshRenderGlobalParamsContainer.FoamingOcclusionDistance = MaterialParameters.FoamingOcclusionDistance;
  3335. MeshRenderGlobalParamsContainer.FoamingThreshold = MaterialParameters.FoamingThreshold;
  3336. MeshRenderGlobalParamsContainer.FoamBrightness = MaterialParameters.FoamBrightness;
  3337. MeshRenderGlobalParamsContainer.FoamMotionBlur = MaterialParameters.FoamMotionBlur;
  3338. MeshRenderGlobalParamsContainer.FoamSize = MaterialParameters.FoamSize;
  3339. MeshRenderGlobalParamsContainer.FoamDiffusion = MaterialParameters.FoamDiffusion;
  3340. MeshRenderGlobalParamsContainer.FoamSpawning = MaterialParameters.FoamSpawning;
  3341. MeshRenderGlobalParamsContainer.Absorption = new Vector4(
  3342. MaterialParameters.Material1.ScatteringAmount, MaterialParameters.Material2.ScatteringAmount,
  3343. MaterialParameters.Material3.ScatteringAmount, MaterialParameters.ScatteringAmount);
  3344. Marshal.StructureToPtr(MeshRenderGlobalParamsContainer, CamMeshRenderParams[cam], true);
  3345. Vector2 textureScale = new Vector2(resolution.x, resolution.y) / GetRequiredTextureResolution();
  3346. // update the data at the pointer
  3347. Marshal.StructureToPtr(CameraRenderParams, CamNativeParams[cam], true);
  3348. if (ActiveRenderingMode == RenderingMode.MeshRender)
  3349. {
  3350. CurrentMaterial.SetMatrix("ProjectionInverse", CameraRenderParams.ProjectionInverse);
  3351. CurrentMaterial.SetMatrix("ViewProjectionInverse", CameraRenderParams.ViewProjectionInverse);
  3352. CurrentMaterial.SetMatrix("EyeRayCameraCoeficients", CameraRenderParams.EyeRayCameraCoeficients);
  3353. CurrentMaterial.SetVector("TextureScale", textureScale);
  3354. if (AdvancedRenderParameters.UnderwaterRender)
  3355. {
  3356. CurrentMaterial.EnableKeyword("UNDERWATER_RENDER");
  3357. }
  3358. else
  3359. {
  3360. CurrentMaterial.DisableKeyword("UNDERWATER_RENDER");
  3361. }
  3362. if (AdvancedRenderParameters.DisableRaymarch)
  3363. {
  3364. CurrentMaterial.EnableKeyword("RAYMARCH_DISABLED");
  3365. }
  3366. else
  3367. {
  3368. CurrentMaterial.DisableKeyword("RAYMARCH_DISABLED");
  3369. CurrentMaterial.SetTexture("RayMarchData", Color1);
  3370. CurrentMaterial.SetTexture("MaterialData", Color2);
  3371. }
  3372. #if !UNITY_ANDROID
  3373. if (MaxFoamParticles > 0 && MaterialParameters.EnableFoam)
  3374. {
  3375. CurrentMaterial.DisableKeyword("FOAM_DISABLED");
  3376. CurrentMaterial.SetTexture("ParticlesTex", ParticlesRT);
  3377. }
  3378. else
  3379. #endif
  3380. {
  3381. CurrentMaterial.EnableKeyword("FOAM_DISABLED");
  3382. }
  3383. }
  3384. if (EnableDownscale)
  3385. {
  3386. CurrentUpscaleMaterial.SetVector("TextureScale", textureScale);
  3387. }
  3388. if (VisualizeSceneSDF)
  3389. {
  3390. CurrentSDFRenderMaterial.SetVector("TextureScale", textureScale);
  3391. CurrentSDFRenderMaterial.SetMatrix("EyeRayCameraCoeficients",
  3392. CameraRenderParams.EyeRayCameraCoeficients);
  3393. }
  3394. }
  3395. /// <summary>
  3396. /// Update render parameters for a given camera
  3397. /// </summary>
  3398. private void InitializeNativeCameraParams(Camera cam)
  3399. {
  3400. if (!CamNativeParams.ContainsKey(cam))
  3401. {
  3402. // allocate memory for camera parameters
  3403. CamNativeParams[cam] = Marshal.AllocHGlobal(Marshal.SizeOf(CameraRenderParams));
  3404. }
  3405. if (!CamMeshRenderParams.ContainsKey(cam))
  3406. {
  3407. // allocate memory for mesh render parameters
  3408. CamMeshRenderParams[cam] = Marshal.AllocHGlobal(Marshal.SizeOf(MeshRenderGlobalParamsContainer));
  3409. }
  3410. }
  3411. private void UpdateNativeRenderParams()
  3412. {
  3413. #if ZIBRA_EFFECTS_DEBUG
  3414. RenderParamsContainer.NeuralSamplingDistance = MaterialParameters.NeuralSamplingDistance;
  3415. RenderParamsContainer.SDFDebug = MaterialParameters.SDFDebug;
  3416. #endif
  3417. RenderParamsContainer.RenderingMode = (int)ActiveRenderingMode;
  3418. RenderParamsContainer.VertexOptimizationIterations = AdvancedRenderParameters.VertexOptimizationIterations;
  3419. RenderParamsContainer.MeshOptimizationIterations = AdvancedRenderParameters.MeshOptimizationIterations;
  3420. RenderParamsContainer.DualContourIsoValue = AdvancedRenderParameters.DualContourIsoSurfaceLevel;
  3421. RenderParamsContainer.MeshOptimizationStep = AdvancedRenderParameters.MeshOptimizationStep;
  3422. int maxVertexCount = GridNodeCount;
  3423. int maxTriangleCount =
  3424. (int)(maxVertexCount * AdvancedRenderParameters.MaxLiquidMeshSize / 3.0f + ADDITIONAL_VERTICES);
  3425. RenderParamsContainer.MaxVertexBufferSize = maxTriangleCount * 6;
  3426. RenderParamsContainer.MaxIndexBufferSize = maxTriangleCount * 3;
  3427. RenderParamsContainer.RenderParamsContainerPos = transform.position;
  3428. GCHandle gcparamBuffer = GCHandle.Alloc(RenderParamsContainer, GCHandleType.Pinned);
  3429. SolverCommandBuffer.Clear();
  3430. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  3431. LiquidBridge.EventID.SetRenderParameters,
  3432. gcparamBuffer.AddrOfPinnedObject());
  3433. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  3434. gcparamBuffer.Free();
  3435. }
  3436. private void ClearCameraCommandBuffers()
  3437. {
  3438. // clear all rendering command buffers if not rendering
  3439. foreach (KeyValuePair<Camera, CommandBuffer> entry in CameraCBs)
  3440. {
  3441. if (entry.Key != null)
  3442. {
  3443. entry.Key.RemoveCommandBuffer(ActiveInjectionPoint, entry.Value);
  3444. }
  3445. }
  3446. CameraCBs.Clear();
  3447. Cameras.Clear();
  3448. }
  3449. /// <summary>
  3450. /// Rendering callback which is called by every camera in the scene
  3451. /// </summary>
  3452. internal void RenderCallBack(Camera cam, float renderPipelineRenderScale = 1.0f)
  3453. {
  3454. if (cam.cameraType == CameraType.Preview || cam.cameraType == CameraType.Reflection ||
  3455. cam.cameraType == CameraType.VR)
  3456. {
  3457. ClearCameraCommandBuffers();
  3458. return;
  3459. }
  3460. if (!cam.isActiveAndEnabled && cam.cameraType != CameraType.SceneView)
  3461. {
  3462. return;
  3463. }
  3464. UpdateCameraResolution(cam, renderPipelineRenderScale);
  3465. // Need at least 2 simulation frames to start rendering
  3466. if (!IsRenderingEnabled())
  3467. {
  3468. return;
  3469. }
  3470. if (!CameraResourcesMap.ContainsKey(cam))
  3471. {
  3472. CameraResourcesMap[cam] = new CameraResources();
  3473. }
  3474. // Re-add command buffers to cameras with new injection points
  3475. if (CurrentInjectionPoint != ActiveInjectionPoint)
  3476. {
  3477. foreach (KeyValuePair<Camera, CommandBuffer> entry in CameraCBs)
  3478. {
  3479. entry.Key.RemoveCommandBuffer(ActiveInjectionPoint, entry.Value);
  3480. entry.Key.AddCommandBuffer(CurrentInjectionPoint, entry.Value);
  3481. }
  3482. ActiveInjectionPoint = CurrentInjectionPoint;
  3483. }
  3484. bool visibleInCamera =
  3485. (RenderPipelineDetector.GetRenderPipelineType() != RenderPipelineDetector.RenderPipeline.BuiltInRP) ||
  3486. ((cam.cullingMask & (1 << this.gameObject.layer)) != 0);
  3487. if (!visibleInCamera || MaterialParameters.FluidMeshMaterial == null ||
  3488. (EnableDownscale && MaterialParameters.UpscaleMaterial == null) ||
  3489. (VisualizeSceneSDF && MaterialParameters.SDFRenderMaterial == null))
  3490. {
  3491. if (CameraCBs.ContainsKey(cam))
  3492. {
  3493. cam.RemoveCommandBuffer(ActiveInjectionPoint, CameraCBs[cam]);
  3494. CameraCBs[cam].Clear();
  3495. CameraCBs.Remove(cam);
  3496. }
  3497. return;
  3498. }
  3499. bool isDirty = SetMaterialParams(cam);
  3500. isDirty = UpdateNativeTextures(cam, renderPipelineRenderScale) || isDirty;
  3501. isDirty = !CameraCBs.ContainsKey(cam) || isDirty;
  3502. InitializeNativeCameraParams(cam);
  3503. UpdateCamera(cam);
  3504. if (RenderPipelineDetector.GetRenderPipelineType() != RenderPipelineDetector.RenderPipeline.BuiltInRP)
  3505. {
  3506. #if UNITY_PIPELINE_HDRP || UNITY_PIPELINE_URP
  3507. // upload camera parameters
  3508. SolverCommandBuffer.Clear();
  3509. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  3510. LiquidBridge.EventID.SetCameraParameters, CamNativeParams[cam]);
  3511. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  3512. #endif
  3513. }
  3514. else
  3515. {
  3516. if (!CameraCBs.ContainsKey(cam) || isDirty)
  3517. {
  3518. CommandBuffer renderCommandBuffer;
  3519. if (isDirty && CameraCBs.ContainsKey(cam))
  3520. {
  3521. renderCommandBuffer = CameraCBs[cam];
  3522. renderCommandBuffer.Clear();
  3523. }
  3524. else
  3525. {
  3526. // Create render command buffer
  3527. renderCommandBuffer = new CommandBuffer { name = "ZibraLiquid.Render" };
  3528. // add command buffer to camera
  3529. cam.AddCommandBuffer(ActiveInjectionPoint, renderCommandBuffer);
  3530. // add camera to the list
  3531. CameraCBs[cam] = renderCommandBuffer;
  3532. }
  3533. // enable depth texture
  3534. cam.depthTextureMode = DepthTextureMode.Depth;
  3535. // update native camera parameters
  3536. if (IsBackgroundCopyNeeded(cam))
  3537. {
  3538. renderCommandBuffer.Blit(BuiltinRenderTextureType.CurrentActive,
  3539. CameraResourcesMap[cam].Background);
  3540. }
  3541. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan)
  3542. {
  3543. renderCommandBuffer.SetRenderTarget(
  3544. Color0, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, Depth,
  3545. RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
  3546. renderCommandBuffer.ClearRenderTarget(true, true, Color.clear);
  3547. }
  3548. RenderLiquidNative(renderCommandBuffer, cam);
  3549. RenderFluid(renderCommandBuffer, cam);
  3550. }
  3551. }
  3552. }
  3553. private ParticleSpeciesParameters GetSpeciesParametersDefault()
  3554. {
  3555. ParticleSpeciesParameters speciesParameters = new ParticleSpeciesParameters();
  3556. speciesParameters.Gravity = SolverParameters.Gravity / 100.0f;
  3557. speciesParameters.AffineAmmount = 4.0f * (1.0f - SolverParameters.Viscosity);
  3558. speciesParameters.LiquidStiffness = SolverParameters.FluidStiffness;
  3559. speciesParameters.RestDensity = SolverParameters.ParticleDensity;
  3560. speciesParameters.SurfaceTension = SolverParameters.SurfaceTension;
  3561. speciesParameters.AffineDivergenceDecay = 1.0f;
  3562. speciesParameters.Material =
  3563. new Vector3(SolverParameters.Material1, SolverParameters.Material2, SolverParameters.Material3);
  3564. speciesParameters.VelocityLimit = SolverParameters.MaximumVelocity;
  3565. return speciesParameters;
  3566. }
  3567. private ParticleSpeciesParameters GetSpeciesParameters(
  3568. ZibraLiquidSolverParameters.SolverSettings thisSolverParameters)
  3569. {
  3570. ParticleSpeciesParameters speciesParameters = new ParticleSpeciesParameters();
  3571. speciesParameters.Gravity = thisSolverParameters.Gravity / 100.0f;
  3572. speciesParameters.AffineAmmount = 4.0f * (1.0f - thisSolverParameters.Viscosity);
  3573. speciesParameters.LiquidStiffness = thisSolverParameters.FluidStiffness;
  3574. speciesParameters.RestDensity = thisSolverParameters.ParticleDensity;
  3575. speciesParameters.SurfaceTension = thisSolverParameters.SurfaceTension;
  3576. speciesParameters.AffineDivergenceDecay = 1.0f;
  3577. speciesParameters.Material = new Vector3(thisSolverParameters.Material1, thisSolverParameters.Material2,
  3578. thisSolverParameters.Material3);
  3579. speciesParameters.VelocityLimit = thisSolverParameters.MaximumVelocity;
  3580. return speciesParameters;
  3581. }
  3582. private void SetInteropBuffer<T>(IntPtr NativeBuffer, List<T> list)
  3583. {
  3584. long LongPtr = NativeBuffer.ToInt64();
  3585. for (int I = 0; I < list.Count; I++)
  3586. {
  3587. IntPtr Ptr = new IntPtr(LongPtr);
  3588. Marshal.StructureToPtr(list[I], Ptr, true);
  3589. LongPtr += Marshal.SizeOf(typeof(T));
  3590. }
  3591. }
  3592. private void UpdateInteropBuffers()
  3593. {
  3594. Marshal.StructureToPtr(LiquidParameters, NativeFluidData, true);
  3595. if (ManipulatorManager.Elements > 0)
  3596. {
  3597. SetInteropBuffer(NativeManipData, ManipulatorManager.ManipulatorParams);
  3598. }
  3599. if (ManipulatorManager.SDFObjectList.Count > 0)
  3600. {
  3601. SetInteropBuffer(NativeSDFData, ManipulatorManager.SDFObjectList);
  3602. }
  3603. List<ParticleSpeciesParameters> SpeciesList = new List<ParticleSpeciesParameters>();
  3604. SpeciesList.Add(GetSpeciesParametersDefault());
  3605. foreach (var species in SolverParameters.AdditionalParticleSpecies)
  3606. {
  3607. SpeciesList.Add(GetSpeciesParameters(species));
  3608. }
  3609. SetInteropBuffer(NativeSolverData, SpeciesList);
  3610. }
  3611. private void UpdateSolverParameters()
  3612. {
  3613. // Update fluid parameters
  3614. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  3615. LiquidBridge.EventID.UpdateLiquidParameters, NativeFluidData);
  3616. if (ManipulatorManager.Elements > 0)
  3617. {
  3618. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  3619. LiquidBridge.EventID.UpdateManipulatorParameters, NativeManipData);
  3620. }
  3621. if (ManipulatorManager.SDFObjectList.Count > 0)
  3622. {
  3623. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  3624. LiquidBridge.EventID.UpdateSDFObjects, NativeSDFData);
  3625. }
  3626. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  3627. LiquidBridge.EventID.UpdateSolverParameters, NativeSolverData);
  3628. }
  3629. private void RenderCallBackWrapper(Camera cam)
  3630. {
  3631. try
  3632. {
  3633. RenderCallBack(cam);
  3634. }
  3635. catch (Exception e)
  3636. {
  3637. Debug.LogException(e);
  3638. }
  3639. }
  3640. private void StepPhysics()
  3641. {
  3642. SolverCommandBuffer.Clear();
  3643. ForceCloseCommandEncoder(SolverCommandBuffer);
  3644. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  3645. LiquidBridge.EventID.ClearSDFAndID);
  3646. SetFluidParameters();
  3647. ManipulatorManager.UpdateDynamic(SolverCommandBuffer, this, Timestep);
  3648. UpdateInteropBuffers();
  3649. UpdateSolverParameters();
  3650. // execute simulation
  3651. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID, LiquidBridge.EventID.StepPhysics);
  3652. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  3653. // update internal time
  3654. SimulationInternalTime += Timestep;
  3655. SimulationInternalFrame++;
  3656. }
  3657. private void UpdateManipulatorStatistics()
  3658. {
  3659. /// ManipulatorStatistics GPUReadback
  3660. if (!IsSimulationEnabled() || ManipulatorManager.Elements == 0)
  3661. {
  3662. return;
  3663. }
  3664. UInt32 size = (UInt32)ManipulatorManager.Elements * STATISTICS_PER_MANIPULATOR;
  3665. IntPtr readbackData = LiquidBridge.ZibraLiquid_GPUReadbackGetData(CurrentInstanceID, size * sizeof(Int32));
  3666. if (readbackData != IntPtr.Zero)
  3667. {
  3668. Int32[] Stats = new Int32[size];
  3669. Marshal.Copy(readbackData, Stats, 0, (Int32)size);
  3670. ManipulatorManager.UpdateStatistics(this, Stats, Manipulators, SolverParameters, SDFColliders);
  3671. }
  3672. }
  3673. private void SetFluidParameters()
  3674. {
  3675. SolverParameters.ValidateParameters();
  3676. LiquidParameters.GridSize = GridSize;
  3677. LiquidParameters.ContainerScale = ContainerSize;
  3678. LiquidParameters.NodeCount = GridNodeCount;
  3679. LiquidParameters.SimulationParamsContainerPos = transform.position;
  3680. LiquidParameters.TimeStep = Timestep;
  3681. LiquidParameters.SimulationFrame = SimulationInternalFrame;
  3682. LiquidParameters.DensityBlurRadius = MaterialParameters.FluidSurfaceBlur;
  3683. LiquidParameters.LiquidIsosurfaceThreshold = AdvancedRenderParameters.IsoSurfaceLevel;
  3684. LiquidParameters.VertexOptimizationStep = AdvancedRenderParameters.VertexOptimizationStep;
  3685. LiquidParameters.EnableContainerMovementFeedback = EnableContainerMovementFeedback ? 1 : 0;
  3686. // ParticleTranslation is set by native plugin
  3687. #if UNITY_ANDROID
  3688. var FoamParticlesEnabled = 0;
  3689. var MaxFoamParticles = 0;
  3690. #else
  3691. var FoamParticlesEnabled = MaterialParameters.EnableFoam ? 1 : 0;
  3692. var MaxFoamParticles = this.MaxFoamParticles;
  3693. #endif
  3694. float MaxVelocityLimit = SolverParameters.MaximumVelocity;
  3695. for (int i = 0; i < SolverParameters.AdditionalParticleSpecies.Count; i++)
  3696. {
  3697. MaxVelocityLimit =
  3698. Mathf.Max(MaxVelocityLimit, SolverParameters.AdditionalParticleSpecies[i].MaximumVelocity);
  3699. }
  3700. LiquidParameters.GlobalVelocityLimit = MaxVelocityLimit;
  3701. LiquidParameters.MinimumVelocity = SolverParameters.MinimumVelocity;
  3702. // BlurNormalizationConstant set by native plugin
  3703. LiquidParameters.MaxParticleCount = MaxNumParticles;
  3704. LiquidParameters.VisualizeSDF = VisualizeSceneSDF ? 1 : 0;
  3705. LiquidParameters.SimulationTime = SimulationInternalTime;
  3706. LiquidParameters.FoamParticleLifetime = MaterialParameters.FoamParticleLifetime;
  3707. LiquidParameters.MaxEffectParticleCount = MaxFoamParticles;
  3708. LiquidParameters.FoamBuoyancy = SolverParameters.FoamBuoyancy;
  3709. LiquidParameters.ParticleSpeciesCount = SolverParameters.AdditionalParticleSpecies.Count + 1;
  3710. LiquidParameters.EnableFoam = FoamParticlesEnabled;
  3711. }
  3712. private void ClearRendering()
  3713. {
  3714. Camera.onPreRender -= RenderCallBackWrapper;
  3715. ClearCameraCommandBuffers();
  3716. // free allocated memory
  3717. foreach (var data in CamNativeParams)
  3718. {
  3719. Marshal.FreeHGlobal(data.Value);
  3720. }
  3721. foreach (var resource in CameraResourcesMap)
  3722. {
  3723. if (resource.Value.Background != null)
  3724. {
  3725. resource.Value.Background.Release();
  3726. resource.Value.Background = null;
  3727. }
  3728. }
  3729. CameraResourcesMap.Clear();
  3730. ZibraLiquidGPUGarbageCollector.SafeRelease(Color0);
  3731. Color0 = null;
  3732. ZibraLiquidGPUGarbageCollector.SafeRelease(Color1);
  3733. Color1 = null;
  3734. ZibraLiquidGPUGarbageCollector.SafeRelease(Color2);
  3735. Color2 = null;
  3736. ZibraLiquidGPUGarbageCollector.SafeRelease(UpscaleColor);
  3737. UpscaleColor = null;
  3738. ZibraLiquidGPUGarbageCollector.SafeRelease(VertexIDGrid);
  3739. VertexIDGrid = null;
  3740. ZibraLiquidGPUGarbageCollector.SafeRelease(VertexBuffer0);
  3741. VertexBuffer0 = null;
  3742. ZibraLiquidGPUGarbageCollector.SafeRelease(VertexBuffer1);
  3743. VertexBuffer1 = null;
  3744. ZibraLiquidGPUGarbageCollector.SafeRelease(TransferDataBuffer);
  3745. TransferDataBuffer = null;
  3746. ZibraLiquidGPUGarbageCollector.SafeRelease(MeshRenderIndexBuffer);
  3747. MeshRenderIndexBuffer = null;
  3748. ZibraLiquidGPUGarbageCollector.SafeRelease(QuadBuffer);
  3749. QuadBuffer = null;
  3750. ZibraLiquidGPUGarbageCollector.SafeRelease(VertexProperties);
  3751. VertexProperties = null;
  3752. ZibraLiquidGPUGarbageCollector.SafeRelease(GridNormalTexture);
  3753. GridNormalTexture = null;
  3754. ZibraLiquidGPUGarbageCollector.SafeRelease(DensityTexture);
  3755. DensityTexture = null;
  3756. ZibraLiquidGPUGarbageCollector.SafeRelease(VelocityTexture);
  3757. VelocityTexture = null;
  3758. ZibraLiquidGPUGarbageCollector.SafeRelease(SDFGridTexture);
  3759. SDFGridTexture = null;
  3760. ZibraLiquidGPUGarbageCollector.SafeRelease(EmbeddingsTexture);
  3761. EmbeddingsTexture = null;
  3762. ZibraLiquidGPUGarbageCollector.SafeRelease(HeightmapTexture);
  3763. HeightmapTexture = null;
  3764. CamNativeParams.Clear();
  3765. MaxFoamParticles = 0;
  3766. }
  3767. private void ClearSolver()
  3768. {
  3769. if (SolverCommandBuffer != null)
  3770. {
  3771. LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
  3772. LiquidBridge.EventID.ReleaseResources);
  3773. Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
  3774. }
  3775. if (SolverCommandBuffer != null)
  3776. {
  3777. SolverCommandBuffer.Release();
  3778. SolverCommandBuffer = null;
  3779. }
  3780. ZibraLiquidGPUGarbageCollector.SafeRelease(PositionMass);
  3781. PositionMass = null;
  3782. if (Affine != null)
  3783. {
  3784. ZibraLiquidGPUGarbageCollector.SafeRelease(Affine[0]);
  3785. Affine[0] = null;
  3786. ZibraLiquidGPUGarbageCollector.SafeRelease(Affine[1]);
  3787. Affine[1] = null;
  3788. }
  3789. ZibraLiquidGPUGarbageCollector.SafeRelease(GridData);
  3790. GridData = null;
  3791. ZibraLiquidGPUGarbageCollector.SafeRelease(IndexGrid);
  3792. IndexGrid = null;
  3793. ZibraLiquidGPUGarbageCollector.SafeRelease(NodeParticlePairs0);
  3794. NodeParticlePairs0 = null;
  3795. ZibraLiquidGPUGarbageCollector.SafeRelease(NodeParticlePairs1);
  3796. NodeParticlePairs1 = null;
  3797. ZibraLiquidGPUGarbageCollector.SafeRelease(EffectParticleData0);
  3798. EffectParticleData0 = null;
  3799. ZibraLiquidGPUGarbageCollector.SafeRelease(EffectParticleData1);
  3800. EffectParticleData1 = null;
  3801. ZibraLiquidGPUGarbageCollector.SafeRelease(RadixGroupData1);
  3802. RadixGroupData1 = null;
  3803. ZibraLiquidGPUGarbageCollector.SafeRelease(RadixGroupData2);
  3804. RadixGroupData2 = null;
  3805. ZibraLiquidGPUGarbageCollector.SafeRelease(RadixGroupData3);
  3806. RadixGroupData3 = null;
  3807. ZibraLiquidGPUGarbageCollector.SafeRelease(PositionMassCopy);
  3808. PositionMassCopy = null;
  3809. ZibraLiquidGPUGarbageCollector.SafeRelease(GridNormal);
  3810. GridNormal = null;
  3811. ZibraLiquidGPUGarbageCollector.SafeRelease(GridBlur0);
  3812. GridBlur0 = null;
  3813. ZibraLiquidGPUGarbageCollector.SafeRelease(GridBlur1);
  3814. GridBlur1 = null;
  3815. ZibraLiquidGPUGarbageCollector.SafeRelease(MassCopy);
  3816. MassCopy = null;
  3817. ZibraLiquidGPUGarbageCollector.SafeRelease(TmpSDFBuff);
  3818. TmpSDFBuff = null;
  3819. ZibraLiquidGPUGarbageCollector.SafeRelease(ParticleNumber);
  3820. ParticleNumber = null;
  3821. ZibraLiquidGPUGarbageCollector.SafeRelease(DynamicManipulatorData);
  3822. DynamicManipulatorData = null;
  3823. ZibraLiquidGPUGarbageCollector.SafeRelease(ParticleSpeciesData);
  3824. ParticleSpeciesData = null;
  3825. ZibraLiquidGPUGarbageCollector.SafeRelease(SDFObjectData);
  3826. SDFObjectData = null;
  3827. ZibraLiquidGPUGarbageCollector.SafeRelease(ManipulatorStatistics);
  3828. ManipulatorStatistics = null;
  3829. ZibraLiquidGPUGarbageCollector.SafeRelease(Counters);
  3830. Counters = null;
  3831. if (!Application.isEditor)
  3832. {
  3833. Destroy(LiquidMesh);
  3834. }
  3835. else
  3836. {
  3837. DestroyImmediate(LiquidMesh);
  3838. }
  3839. Marshal.FreeHGlobal(NativeManipData);
  3840. NativeManipData = IntPtr.Zero;
  3841. Marshal.FreeHGlobal(NativeFluidData);
  3842. NativeFluidData = IntPtr.Zero;
  3843. CurrentTextureResolution = new Vector2Int(0, 0);
  3844. GridSize = new Vector3Int(0, 0, 0);
  3845. CurrentParticleNumber = 0;
  3846. GridNodeCount = 0;
  3847. SimulationInternalFrame = 0;
  3848. SimulationInternalTime = 0.0f;
  3849. Timestep = 0.0f;
  3850. CamRenderResolutions.Clear();
  3851. CamNativeResolutions.Clear();
  3852. // DO NOT USE AllFluids.Remove(this)
  3853. // This will not result in equivalent code
  3854. // ZibraLiquid::Equals is overriden and don't have correct implementation
  3855. if (AllFluids != null)
  3856. {
  3857. for (int i = 0; i < AllFluids.Count; i++)
  3858. {
  3859. var fluid = AllFluids[i];
  3860. if (ReferenceEquals(fluid, this))
  3861. {
  3862. AllFluids.RemoveAt(i);
  3863. break;
  3864. }
  3865. }
  3866. }
  3867. }
  3868. private void OnApplicationQuit()
  3869. {
  3870. // On quit we need to destroy liquid before destroying any colliders/manipulators
  3871. OnDisable();
  3872. }
  3873. // dispose the objects
  3874. private void OnDisable()
  3875. {
  3876. RemoveFromStatReporter();
  3877. ReleaseSimulation();
  3878. }
  3879. private float ByteArrayToSingle(byte[] array, ref int startIndex)
  3880. {
  3881. float value = BitConverter.ToSingle(array, startIndex);
  3882. startIndex += sizeof(float);
  3883. return value;
  3884. }
  3885. private int ByteArrayToInt(byte[] array, ref int startIndex)
  3886. {
  3887. int value = BitConverter.ToInt32(array, startIndex);
  3888. startIndex += sizeof(int);
  3889. return value;
  3890. }
  3891. private BakedInitialState ConvertBytesToInitialState(byte[] data)
  3892. {
  3893. int startIndex = 0;
  3894. int header = ByteArrayToInt(data, ref startIndex);
  3895. if (!IsValidBakedLiquidHeader(header))
  3896. {
  3897. throw new Exception("Invalid baked liquid data.");
  3898. }
  3899. int particleCount = ByteArrayToInt(data, ref startIndex);
  3900. if (particleCount > MaxNumParticles)
  3901. {
  3902. throw new Exception("Baked data have more particles than max particle count.");
  3903. }
  3904. BakedInitialState initialStateData = new BakedInitialState();
  3905. initialStateData.ParticleCount = particleCount;
  3906. initialStateData.Positions = new Vector4[particleCount];
  3907. if (header == BAKED_LIQUID_PAID_HEADER_VALUE)
  3908. {
  3909. for (int i = 0; i < particleCount; i++)
  3910. {
  3911. for (int j = 0; j < 3; j++)
  3912. {
  3913. initialStateData.Positions[i][j] = ByteArrayToSingle(data, ref startIndex);
  3914. }
  3915. initialStateData.Positions[i].w = 0.0f;
  3916. }
  3917. }
  3918. else if (header == BAKED_LIQUID_PRO_HEADER_VALUE)
  3919. {
  3920. for (int i = 0; i < particleCount; i++)
  3921. {
  3922. for (int j = 0; j < 4; j++)
  3923. {
  3924. initialStateData.Positions[i][j] = ByteArrayToSingle(data, ref startIndex);
  3925. }
  3926. }
  3927. }
  3928. initialStateData.AffineVelocity = new Vector2Int[4 * particleCount];
  3929. for (int i = 0; i < particleCount; i++)
  3930. {
  3931. for (int j = 0; j < 2; j++)
  3932. {
  3933. initialStateData.AffineVelocity[4 * i + 3][j] = ByteArrayToInt(data, ref startIndex);
  3934. }
  3935. }
  3936. return initialStateData;
  3937. }
  3938. private BakedInitialState LoadInitialStateAsset()
  3939. {
  3940. byte[] data = BakedInitialStateAsset.bytes;
  3941. return ConvertBytesToInitialState(data);
  3942. }
  3943. /// <summary>
  3944. /// Apply currently set initial conditions
  3945. /// </summary>
  3946. private void ApplyInitialState()
  3947. {
  3948. switch (InitialState)
  3949. {
  3950. case InitialStateType.NoParticles:
  3951. LiquidParameters.ParticleCount = 0;
  3952. break;
  3953. case InitialStateType.BakedLiquidState:
  3954. if (BakedInitialStateAsset)
  3955. {
  3956. BakedInitialState initialStateData = LoadInitialStateAsset();
  3957. PositionMass.SetData(initialStateData.Positions);
  3958. Affine[0].SetData(initialStateData.AffineVelocity);
  3959. Affine[1].SetData(initialStateData.AffineVelocity);
  3960. LiquidParameters.ParticleCount = initialStateData.ParticleCount;
  3961. }
  3962. else
  3963. {
  3964. LiquidParameters.ParticleCount = 0;
  3965. }
  3966. break;
  3967. }
  3968. }
  3969. private Matrix4x4 CalculateEyeRayCameraCoeficients(Camera cam)
  3970. {
  3971. float fovTan = Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad);
  3972. if (cam.orthographic)
  3973. {
  3974. fovTan = 0.0f;
  3975. }
  3976. Vector3 r = cam.transform.right * cam.aspect * fovTan;
  3977. Vector3 u = -cam.transform.up * fovTan;
  3978. Vector3 v = cam.transform.forward;
  3979. return new Matrix4x4(new Vector4(r.x, r.y, r.z, 0.0f), new Vector4(u.x, u.y, u.z, 0.0f),
  3980. new Vector4(v.x, v.y, v.z, 0.0f), new Vector4(0.0f, 0.0f, 0.0f, 0.0f))
  3981. .transpose;
  3982. }
  3983. void ValidateColliders()
  3984. {
  3985. if (SDFColliders != null)
  3986. {
  3987. HashSet<ZibraLiquidCollider> colliderSet = new HashSet<ZibraLiquidCollider>(SDFColliders);
  3988. colliderSet.Remove(null);
  3989. SDFColliders = new List<ZibraLiquidCollider>(colliderSet);
  3990. SDFColliders.Sort(new SDFColliderCompare());
  3991. }
  3992. }
  3993. void ValidateManipulators()
  3994. {
  3995. if (Manipulators != null)
  3996. {
  3997. HashSet<Manipulator> manipulatorsSet = new HashSet<Manipulator>(Manipulators);
  3998. manipulatorsSet.Remove(null);
  3999. Manipulators = new List<Manipulator>(manipulatorsSet);
  4000. Manipulators.Sort(new ManipulatorCompare());
  4001. }
  4002. }
  4003. internal ZibraLiquidCollider HasGivenCollider(GameObject collider)
  4004. {
  4005. foreach (var col in SDFColliders)
  4006. {
  4007. if (col.gameObject == collider)
  4008. {
  4009. return col;
  4010. }
  4011. }
  4012. return null;
  4013. }
  4014. void AddToStatReporter()
  4015. {
  4016. StatReporterCollection.Add(this);
  4017. }
  4018. void RemoveFromStatReporter()
  4019. {
  4020. StatReporterCollection.Remove(this);
  4021. }
  4022. #endregion
  4023. }
  4024. }