| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547 |
- using com.zibra.liquid.DataStructures;
- using com.zibra.liquid.Manipulators;
- using com.zibra.common.Utilities;
- using com.zibra.liquid.Bridge;
- #if UNITY_EDITOR
- using com.zibra.liquid.Analytics;
- using com.zibra.common.PresetAnalytics;
- #endif
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Runtime.InteropServices;
- using UnityEngine;
- using UnityEngine.Experimental.Rendering;
- using UnityEngine.Rendering;
- using UnityEngine.Serialization;
- using com.zibra.common.SDFObjects;
- using com.zibra.common.Solver;
- #if UNITY_EDITOR
- using com.zibra.common.Editor.SDFObjects;
- using com.zibra.common.Editor;
- #endif
- #if UNITY_PIPELINE_HDRP
- using UnityEngine.Rendering.HighDefinition;
- #endif // UNITY_PIPELINE_HDRP
- namespace com.zibra.liquid.Solver
- {
- /// <summary>
- /// Main ZibraLiquid component.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Each ZibraLiquid component corresponds to one instance of simulation.
- /// Different instances of simulation can't interact with each other.
- /// </para>
- /// <para>
- /// Some parameters can't be changed after simulation has started and we created GPU buffers.
- /// Normally, simulation starts in playmode in OnEnable and stops in OnDisable.
- /// To change those parameters in runtime you want to have this component disabled,
- /// and after setting them, enable this component.
- /// </para>
- /// <para>
- /// Liquid may run in the edit mode, specifically when you use initial state baking.
- /// In that case, you can't modify some parameters in edit mode too.
- /// </para>
- /// <para>
- /// OnEnable will allocate GPU buffers, which may cause stuttering.
- /// Consider enabling liquid on level load, but with simulation/render paused,
- /// to not pay the cost of liquid initialization during gameplay.
- /// </para>
- /// <para>
- /// Disabling liquid will free GPU buffers.
- /// This means that liquid state will be lost.
- /// </para>
- /// <para>
- /// Various parameters of the liquid are spread throught multiple components.
- /// This is done so you can use Unity's Preset system to only change part of parameters.
- /// </para>
- /// </remarks>
- [AddComponentMenu("Zibra Effects - Liquid/Zibra Liquid")]
- [DisallowMultipleComponent]
- [RequireComponent(typeof(ZibraLiquidMaterialParameters))]
- [RequireComponent(typeof(ZibraLiquidSolverParameters))]
- [RequireComponent(typeof(ZibraLiquidAdvancedRenderParameters))]
- [RequireComponent(typeof(ZibraManipulatorManager))]
- [ExecuteInEditMode]
- public class ZibraLiquid : MonoBehaviour, StatReporter
- {
- #region Public Interface
- #region Properties
- /// <summary>
- /// A list of all enabled instances of this component.
- /// </summary>
- public static List<ZibraLiquid> AllFluids = new List<ZibraLiquid>();
- /// <summary>
- /// Header of initial state baked in the Paid version.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Use <see cref="IsValidBakedLiquidHeader"/> instead,
- /// unless you need to check which version baked this state.
- /// </para>
- /// <para>
- /// You can compare this to first int in .bytes file,
- /// to check whether it is baked liquid state saved specifically by the Paid version.
- /// </para>
- /// <para>
- /// Baked states are compatible across versions,
- /// But state baked in the Pro version also contains data about particle species,
- /// So state from the Pro version has different format and a little bit larger.
- /// </para>
- /// </remarks>
- public const int BAKED_LIQUID_PAID_HEADER_VALUE = 0x071B9AA1;
- /// <summary>
- /// Header of initial state baked in the Pro version.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Use <see cref="IsValidBakedLiquidHeader"/> instead,
- /// unless you need to check which version baked this state.
- /// </para>
- /// <para>
- /// You can compare this to first int in .bytes file,
- /// to check whether it is baked liquid state saved specifically by the Pro version.
- /// </para>
- /// <para>
- /// Baked states are compatible across versions,
- /// But state baked in the Pro version also contains data about particle species,
- /// So state from the Pro version has different format and a little bit larger.
- /// </para>
- /// </remarks>
- public const int BAKED_LIQUID_PRO_HEADER_VALUE = 0x171B9AA1;
- /// <summary>
- /// Default speed of liquid simulation.
- /// </summary>
- /// <remarks>
- /// The defualt value of speed of liquid simulation that defines
- /// relation between simulation time units and seconds.
- /// </remarks>
- public const float DEFAULT_SIMULATION_TIME_SCALE = 40.0f;
- /// <summary>
- /// Checks whether passed int is a valid header for baked liquid state.
- /// </summary>
- /// <remarks>
- /// To use it, read first int from the .bytes file and pass it to this function.
- /// </remarks>
- public bool IsValidBakedLiquidHeader(int header)
- {
- return header == BAKED_LIQUID_PAID_HEADER_VALUE || header == BAKED_LIQUID_PRO_HEADER_VALUE;
- }
- #if UNITY_EDITOR
- /// <summary>
- /// (Editor only) Event that is triggered when state of manipulator changes
- /// to trigger update of custom editor.
- /// </summary>
- /// <remarks>
- /// This is only intended to update custom editors,
- /// You can trigger it when you change some state to update custom editor.
- /// But using it for anything else is a bad idea.
- /// </remarks>
- public event Action OnChanged;
- /// <summary>
- /// (Editor only) Triggers custom editor update.
- /// </summary>
- /// <remarks>
- /// Just triggers <see cref="OnChanged"/>.
- /// </remarks>
- public void NotifyChange()
- {
- if (OnChanged != null)
- {
- OnChanged.Invoke();
- }
- }
- #endif
- /// <summary>
- /// Render target containing rendered mesh.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This is RGBA float render target.
- /// Format during Mesh Render pass:
- /// * xyz - World position
- /// * w - Encoded surface normal
- ///
- /// Format during Visualse SDF pass:
- /// * xyz - Normal
- /// * w - Depth
- /// </para>
- /// <para>
- /// When Visualize SDF is enabled, it will execute after Mesh Render pass,
- /// and so it will overwrite rendered liquid.
- /// </para>
- /// <para>
- /// Only used in Mesh Render mode or Visualize SDF pass.
- /// </para>
- /// </remarks>
- [NonSerialized]
- public RenderTexture Color0;
- /// <summary>
- /// Render target containing raymarched data.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This is RGBA float render target.
- /// Format:
- /// * x - Depth of first light bounce traveling inside liquid
- /// * y - Depth of first light bounce traveling outside liquid (if any)
- /// * z - Depth of second light bounce traveling inside liquid (if any)
- /// * w - 0
- ///
- /// calculation of yz components require RefractionBounces
- /// in ZibraLiquidAdvancedRenderParameters to be set to TwoBounces.
- /// </para>
- /// <para>
- /// Unused if DisableRaymarch in ZibraLiquidAdvancedRenderParameters is enabled.
- /// </para>
- /// <para>
- /// Only used in Mesh Render mode.
- /// </para>
- /// </remarks>
- [NonSerialized]
- public RenderTexture Color1;
- /// <summary>
- /// Render target containing raymarched data.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This is RGBA float render target.
- /// Format:
- /// * xyz - Concentrations of Material1/2/3 respectively.
- /// * w - 0
- /// </para>
- /// <para>
- /// Unused if DisableRaymarch in ZibraLiquidAdvancedRenderParameters is enabled.
- /// </para>
- /// <para>
- /// Only used in Mesh Render mode.
- /// </para>
- /// <para>
- /// Texture exists in non Pro versions too for technical reasons,
- /// but has no functionality in non Pro versions.
- /// </para>
- /// </remarks>
- [NonSerialized]
- public RenderTexture Color2;
- /// <summary>
- /// Render target containing rendered liquid when using downscale.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This is RGBA float render target.
- /// Format:
- /// * xyz - Rendered liquid
- /// * w - 1.0 in pixels with liquid, and 0 othewise
- /// </para>
- /// <para>
- /// Only used when <see cref="EnableDownscale"/> is enabled.
- /// </para>
- /// <para>
- /// Only used in Mesh Render mode.
- /// </para>
- /// </remarks>
- [NonSerialized]
- public RenderTexture UpscaleColor;
- /// <summary>
- /// Render target containing liquid depth when using downscale.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Only used when <see cref="EnableDownscale"/> is enabled.
- /// </para>
- /// <para>
- /// Only used in Mesh Render mode.
- /// </para>
- /// </remarks>
- [NonSerialized]
- public RenderTexture UpscaleDepth;
- /// <summary>
- /// Depth buffer containing liquid depth.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This is depth buffer.
- /// Format:
- /// * r - rendered liquid mesh depth.
- /// </para>
- /// <para>
- /// Only used in Mesh Render mode.
- /// </para>
- /// </remarks>
- [NonSerialized]
- public RenderTexture Depth;
- /// <summary>
- /// Render target containing rendered foam particles.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Only used in Mesh Render mode.
- /// </para>
- /// <para>
- /// This is RGBA float render target.
- /// Format:
- /// * rgba - foam color.
- /// </para>
- /// <para>
- /// Current version only supports monochrome foam
- /// but in future update we'll use all 4 color components
- /// </para>
- /// </remarks>
- [NonSerialized]
- public RenderTexture ParticlesRT;
- /// <summary>
- /// Buffer containing generated mesh counters.
- /// </summary>
- /// <remarks>
- /// This is an int buffer.
- /// Counters[0] = Number of quads.
- /// Counters[1] = Number of vertices.
- /// </remarks>
- [NonSerialized]
- public ComputeBuffer Counters;
- /// <summary>
- /// Buffer containing indices of vertices corresponding to grid nodes.
- /// </summary>
- /// <remarks>
- /// This is an int buffer.
- /// VertexIDGrid[nodeID] = Index of vertex corresponding to grid node with id nodeID
- /// </remarks>
- [NonSerialized]
- public ComputeBuffer VertexIDGrid;
- /// <summary>
- /// Buffer containing indices of vertices corresponding to grid nodes.
- /// </summary>
- /// <remarks>
- /// This is an uint buffer.
- /// VertexIDGrid[3 * vertexID + 0/1/2] = X/Y/Z coordinate
- /// of vertex in simulation space encoded with <c>asuint</c>.
- /// </remarks>
- [NonSerialized]
- public GraphicsBuffer VertexBuffer0;
- /// <summary>
- /// Temporary buffer for internal calculations.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Has same structure as <see cref="VertexBuffer0"/>,
- /// but only contains intermediate data.
- /// </para>
- /// <para>
- /// You can safely reuse it for your needs, to save VRAM,
- /// but it'll get overwritten during liquid mesh generation.
- /// </para>
- /// </remarks>
- [NonSerialized]
- public GraphicsBuffer VertexBuffer1;
- [NonSerialized]
- /// <summary>
- /// Buffer containing information about liquid mesh quads.
- /// </summary>
- /// <remarks>
- /// This is an uint buffer.
- /// Each element contains encoded data about single quad.
- /// Data encoded as follows:
- /// Leas significant 29 bits - ID of grid node corresponding to quad.
- /// Next 2 bits - ID of axis of quad
- /// Next 1 bit - direction of quad, 1 = positive direction, 0 = negative direction
- /// </remarks>
- public ComputeBuffer QuadBuffer;
- /// <summary>
- /// Temporary buffer for internal calculations.
- /// </summary>
- /// <remarks>
- /// Used as intermediate to write to buffers that cannot normally be written from GPU.
- /// </remarks>
- [NonSerialized]
- public ComputeBuffer TransferDataBuffer;
- /// <summary>
- /// Index buffer of liquid mesh.
- /// </summary>
- /// <remarks>
- /// Also, used as intermediate, to copy data to Unity's mesh.
- /// But not used exclusively in Unire Render mode.
- /// </remarks>
- [NonSerialized]
- public GraphicsBuffer MeshRenderIndexBuffer;
- /// <summary>
- /// Buffer containing vertex data of liquid mesh.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Used as intermediate, to copy data to Unity's mesh.
- /// </para>
- /// <para>
- /// This is an uint buffer.
- /// Format:
- /// * VertexProperties[6 * VertexID + 0/1/2] = X/Y/Z coordinate in local space,
- /// encoded with <c>asuint</c>
- /// * VertexProperties[6 * VertexID + 3/4/5] = X/Y/Z normal encoded with <c>asuint</c>
- /// </para>
- /// <para>
- /// Only used in Unity Render mode.
- /// </para>
- /// </remarks>
- [NonSerialized]
- public GraphicsBuffer VertexProperties;
- /// <summary>
- /// Mesh used for rendering in case Unity Render mode is used.
- /// </summary>
- [NonSerialized]
- public Mesh LiquidMesh;
- /// <summary>
- /// 2D texture containing all heightmaps.
- /// </summary>
- /// <remarks>
- /// This is a float 2d texture. Each texel corresponds to a height value.
- /// Format:
- /// * x - Height
- /// </remarks>
- [NonSerialized]
- public RenderTexture HeightmapTexture;
- /// <summary>
- /// 3D texture containing liquid normals.
- /// </summary>
- /// <remarks>
- /// This is a float 3d texture. Each texel corresponds to grid node.
- /// Format:
- /// * xyz - Normal
- /// * w - Blurred liquid density
- /// </remarks>
- [NonSerialized]
- public RenderTexture GridNormalTexture;
- /// <summary>
- /// 3D texture containing liquid normals.
- /// </summary>
- /// <remarks>
- /// This is a float 3d texture. Each texel corresponds to grid node.
- /// Format:
- /// * xyz - Concentrations of liquid materials
- /// * w - Smooth liquid density
- /// </remarks>
- [NonSerialized]
- public RenderTexture DensityTexture;
- /// <summary>
- /// 3D texture containing liquid normals.
- /// </summary>
- /// <remarks>
- /// This is a float 3d texture. Each texel corresponds to grid node.
- /// Format:
- /// * xyz - Momentum of the liquid
- /// * w - Mass of the liquid
- /// </remarks>
- [NonSerialized]
- public RenderTexture VelocityTexture;
- /// <summary>
- /// Maximum number of particles simulation may have.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Directly corresponds to maximum volume of liquid simulation may have.
- /// </para>
- /// <para>
- /// Has noticeable VRAM impact.
- /// </para>
- /// <para>
- /// Having more active particles in the simulation has noticeable performance impact.
- /// </para>
- /// <para>
- /// This parameter can not be changed when liquid has GPU resources initialized.
- /// (See <see cref="Initialized"/>)
- /// </para>
- /// <para>
- /// For UI limit of 10000000 particles is set,
- /// and that's maximum number which guaranteed to work (if you have enough VRAM).
- /// But if you want to, you can set it higher.
- /// </para>
- /// </remarks>
- [Range(1024, 10000000)]
- [Tooltip(
- "Maximum number of particles simulation may have. Directly corresponds to maximum volume of liquid simulation may have. Has noticeable VRAM impact.")]
- public int MaxNumParticles = 262144;
- /// <summary>
- /// Buffer containing positions and particle species information.
- /// </summary>
- /// <remarks>
- /// This is a float4 buffer. Each float4 corresponds to particle.
- /// Format:
- /// * PositionMass[i].xyz - Position of the particle in the simulation space
- /// * PositionMass[i].w - Particle species
- /// </remarks>
- public ComputeBuffer PositionMass { get; private set; }
- /// <summary>
- /// Buffers containing affine velocity matrices, velocities
- /// and foaming values for each particle.
- /// </summary>
- /// <remarks>
- /// <para>
- /// There are exactly 2 buffers, and the active one is flipped each simulation step.
- /// </para>
- /// <para>
- /// This is a float4 buffer. Each pack of 4 float4's corresponds to particle.
- /// Format:
- /// * Affine[particleID * 4 + 0].xyz - 1st row of affine velocity matrix
- /// * Affine[particleID * 4 + 0].w - 1st particle specific random number
- /// * Affine[particleID * 4 + 1].xyz - 2nd row of affine velocity matrix
- /// * Affine[particleID * 4 + 1].w - 2nd particle specific random number
- /// * Affine[particleID * 4 + 2].xyz - 3rd row of affine velocity matrix
- /// * Affine[particleID * 4 + 2].w - 3rd particle specific random number
- /// * Affine[particleID * 4 + 3].xyz - Velocity
- /// * Affine[particleID * 4 + 3].w - Foaming value
- /// </para>
- /// </remarks>
- public ComputeBuffer[] Affine { get; private set; }
- /// <summary>
- /// Buffer containing number of active particles, as well as some additional counters.
- /// </summary>
- /// <remarks>
- /// This is an int buffer.
- /// Format:
- /// * ParticleNumber[0] - Active particle count
- /// * ParticleNumber[1] - Particles emitted in the last simulation step
- /// * Other values are not useful outside of the simulation
- /// </remarks>
- public ComputeBuffer ParticleNumber { get; private set; }
- /// <summary>
- /// If enabled, makes liquid render in lower resolution.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Enabling downscale can significantly improve performance on mobile,
- /// by having way less pixels calculate pixel shader for the liquid.
- /// </para>
- /// <para>
- /// Has no effect in Unity Render mode.
- /// </para>
- /// </remarks>
- [Tooltip("If enabled, makes liquid render in lower resolution")]
- public bool EnableDownscale = false;
- /// <summary>
- /// Factor of resolution downscale.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Lower factor corresponds to better performance, but lower visual quality.
- /// </para>
- /// <para>
- /// If you set this value too high, you may get lower performance compared to downscale disabled.
- /// This is due to fact that we need to do additional pass to upscale liquid,
- /// so when resolution downscale is too high, performance win from lower shading resolution
- /// can potentially be less than performance loss due to cost of doing upscale pass.
- /// That's why value of 1.0 is not allowed and you have to disable downscale for full resolution.
- /// </para>
- /// <para>
- /// Has no effect in Unity Render mode or when <see cref="EnableDownscale"/> is disabled.
- /// </para>
- /// </remarks>
- [Range(0.2f, 0.99f)]
- [Tooltip(
- "Factor of resolution downscale. Lower factor corresponds to better performance, but lower visual quality.")]
- public float DownscaleFactor = 0.5f;
- /// <summary>
- /// See <see cref="InitialState"/>.
- /// </summary>
- public enum InitialStateType
- {
- NoParticles,
- BakedLiquidState
- }
- /// <summary>
- /// Baked initial state.
- /// </summary>
- [Serializable]
- public class BakedInitialState
- {
- /// <summary>
- /// Active particle count in baked state
- /// </summary>
- /// <remarks>
- /// If baked initial state will have more particles <see cref="MaxNumParticles"/> it'll trigger an
- /// error.
- /// </remarks>
- [SerializeField]
- public int ParticleCount;
- /// <summary>
- /// Particle data stored in same format as in buffer <see cref="PositionMass"/>.
- /// </summary>
- [SerializeField]
- public Vector4[] Positions;
- /// <summary>
- /// Particle data stored in same format as in buffers <see cref="Affine"/>.
- /// </summary>
- [SerializeField]
- public Vector2Int[] AffineVelocity;
- }
- /// <summary>
- /// Type of initial state of the liquid.
- /// </summary>
- /// <remarks>
- /// Default is - No Particles, which means that there won't be any liquid on startup.
- /// Alternative is - Baked Liquid State, which uses <see cref="BakedInitialStateAsset"/>
- /// to restore previously recorded liquid state.
- /// </remarks>
- [Tooltip("Type of initial state of the liquid")]
- public InitialStateType InitialState = InitialStateType.NoParticles;
- /// <summary>
- /// Asset containing baked initial state data.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This state is too large to store in the scene file,
- /// So it's stored separately, which has sideeffect of having TextAsset type.
- /// Since any TextAsset can be assigned to it,
- /// we have check to make sure that any specific TextAsset is a baked liquid state.
- /// See <see cref="IsValidBakedLiquidHeader"/>.
- /// </para>
- /// <para>
- /// Has no effect in case <see cref="InitialState"/> is not set to BakedLiquidState.
- /// </para>
- /// </remarks>
- [Tooltip("Asset containing baked initial state data")]
- public TextAsset BakedInitialStateAsset;
- /// <summary>
- /// ID of running liquid instance.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Only valid when liquid resources are initialized.
- /// </para>
- /// <para>
- /// Guaranteed to be unique among all currently initialized liquids.
- /// </para>
- /// </remarks>
- public int CurrentInstanceID { get; private set; }
- /// <summary>
- /// Timestep used in last simulation iteration.
- /// </summary>
- public float Timestep { get; private set; } = 0.0f;
- /// <summary>
- /// Simulation time passed (in simulation time units).
- /// </summary>
- public float SimulationInternalTime { get; private set; } = 0.0f;
- /// <summary>
- /// Number of simulation iterations done so far.
- /// </summary>
- public int SimulationInternalFrame { get; private set; } = 0;
- /// <summary>
- /// Total number of grid nodes.
- /// </summary>
- /// <remarks>
- /// Only valid when liquid resources are initialized.
- /// Or after call to <see cref="UpdateSimulationConstants"/>
- /// </remarks>
- public int GridNodeCount { get; private set; } = 0;
- /// <summary>
- /// See <see cref="CurrentRenderingMode"/>.
- /// </summary>
- public enum RenderingMode
- {
- [Obsolete("Particle Render is no longer support. Please switch to another render mode.",
- true)] ParticleRender = 0,
- MeshRender = 1,
- #if ZIBRA_EFFECTS_OTP_VERSION
- [Obsolete("Unity Render is not supported in OTP version.", true)]
- #endif
- UnityRender = 2
- }
- /// <summary>
- /// Rendering mode of the liquid.
- /// </summary>
- /// <remarks>
- /// <para>
- /// You can choose between:
- ///
- /// * Mesh Render mode - mode in which we:
- /// Generate mesh from the liquid.
- /// Render it with DrawIndirect in Native Plugin
- /// (optionally) Do raymarching pass to calculate light bounching inside the liquid in Native plugin.
- /// Shading inside Unity with customizeable shader.
- /// (optionally) Upscale pass to allow shading in lower resolution.
- ///
- /// * Unity Render mode - mode in which we:
- /// Generate mesh from the liquid.
- /// Copy it to Unity's Mesh Renderer.
- /// And Unity takes care of rendering that mesh.
- /// </para>
- /// <para>
- /// To use Unity Render mode you'll need your own shader for liquid to render with.
- /// </para>
- /// <para>
- /// In Unity Render mode you won't have raymarching results, so visual quality will be lower.
- /// </para>
- /// <para>
- /// Unity Render mode has slight performance penalty,
- /// as it currently can not draw variable number of indices.
- /// </para>
- /// <para>
- /// In Unity Render, material parameters set in liquid object have no effect.
- /// Since liquid can not control arbitrary material that may be set to render the liquid.
- /// </para>
- /// <para>
- /// Mesh Render mode doesn't support VR at the moment,
- /// so will have to switch to Unity Render mode in order for VR to work.
- /// </para>
- /// <para>
- /// Changing this parameter when liquid is initialized has no effect.
- /// During initialization we allocate different set of resources based on render mode.
- /// So changing render mode requires re-initialization.
- /// </para>
- /// <para>
- /// See User Guide for more details.
- /// </para>
- /// </remarks>
- [Tooltip("Rendering mode of the liquid. Please see documentation for more details.")]
- public RenderingMode CurrentRenderingMode = RenderingMode.MeshRender;
- /// <summary>
- /// Injection point where we will insert liquid rendering.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Only used in case of Built-in Render Pipeline.
- /// </para>
- /// <para>
- /// Has no effect when using Unity Render mode.
- /// </para>
- /// </remarks>
- [Tooltip("Injection point where we will insert liquid rendering")]
- public CameraEvent CurrentInjectionPoint = CameraEvent.AfterSkybox;
- /// <summary>
- /// Size of the simulation grid.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Only valid when liquid resources are initialized.
- /// Or after call to <see cref="UpdateSimulationConstants"/>
- /// </para>
- /// <para>
- /// Largest component is equal to <see cref="GridResolution"/>.
- /// Other components are scaled so aspect ratio of GridSize
- /// matches aspect ratio of <see cref="ContainerSize"/>.
- /// </para>
- /// </remarks>
- public Vector3Int GridSize { get; private set; }
- #if UNITY_PIPELINE_HDRP
- /// <summary>
- /// (HDRP Only) Reflection proble used for liquid reflections.
- /// </summary>
- /// <remarks>
- /// Must be set you are using HDRP and Mesh Render mode.
- /// Otherwise liquid won't inialize.
- /// </remarks>
- [FormerlySerializedAs("reflectionProbe")]
- [FormerlySerializedAs("reflectionProbeHDRP")]
- [Tooltip("Reflection proble used for liquid reflections")]
- public HDProbe ReflectionProbeHDRP;
- /// <summary>
- /// (HDRP Only) Light used for liquid shading.
- /// </summary>
- /// <remarks>
- /// Must be set you are using HDRP and Mesh Render mode.
- /// Otherwise liquid won't inialize.
- /// </remarks>
- [FormerlySerializedAs("customLightHDRP")]
- [Tooltip("Light used for liquid shading")]
- public Light CustomLightHDRP;
- #endif // UNITY_PIPELINE_HDRP
- /// <summary>
- /// (URP/Built-in RP Only) Reflection proble used for liquid reflections.
- /// </summary>
- /// <remarks>
- /// It's strongly recommended to set it if you are using URP/Built-in RP and Mesh Render mode.
- /// </remarks>
- #if !UNITY_PIPELINE_HDRP
- [FormerlySerializedAs("reflectionProbe")]
- #endif // !UNITY_PIPELINE_HDRP
- [FormerlySerializedAs("reflectionProbeSRP")]
- [Tooltip("Reflection proble used for liquid reflections")]
- public ReflectionProbe ReflectionProbeBRP;
-
- /// <summary>
- /// Maximum timestep that is allowed in single simulation iteration.
- /// </summary>
- /// <remarks>
- /// Higher values correspond to potentially less stable simulation.
- /// While lower values correspond to higher chance of liquid simulation slowing down during FPS drops.
- /// </remarks>
- [Range(0.0f, 1.0f)]
- [FormerlySerializedAs("timeStepMax")]
- [Tooltip("Maximum timestep that is allowed in single simulation iteration")]
- public float MaxAllowedTimestep = 1.00f;
- /// <summary>
- /// Maximum allowed number of frames queued to render.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Only used when <c>QualitySettings.maxQueuedFrames</c> is not available or invalid.
- /// </para>
- /// <para>
- /// Defines number of frames we'll wait between submitting simulation workload
- /// and reading back simulation information back to the CPU.
- /// Higher values correspond to more delay for simulation info readback,
- /// while lower values can potentially decreasing framerate.
- /// </para>
- /// </remarks>
- [Range(2, 16)]
- [FormerlySerializedAs("maxFramesInFlight")]
- [Tooltip("Fallback maximum allowed number of frames queued to render")]
- public UInt32 MaxFramesInFlight = 3;
- /// <summary>
- /// Speed of liquid simulation.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Defines relation between simulation time units and seconds.
- /// </para>
- /// <para>
- /// You can change the speed of liquid simulation with this parameter dynamically.
- /// </para>
- /// </remarks>
- [Range(0.0f, 100.0f)]
- [FormerlySerializedAs("simTimePerSec")]
- [Tooltip("Speed of liquid simulation")]
- public float SimulationTimeScale = DEFAULT_SIMULATION_TIME_SCALE;
- /// <summary>
- /// Current number of particles in the simulation.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Values greater than 0 correspond to having any liquid in the simulation.
- /// </para>
- /// <para>
- /// This parameter is updated with delay, since we need to read that data from the GPU.
- /// </para>
- /// </remarks>
- public int CurrentParticleNumber { get; private set; } = 0;
- /// <summary>
- /// Number of simulation iterations to execute on each update.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Update for purposes of this parameter is <c>Update()</c>
- /// in case <see cref="UseFixedTimestep"/> is disabled,
- /// and <c>FixedUpdate()</c> otherwise.
- /// </para>
- /// <para>
- /// It's strongly recommended to set it to 1 if you target mobile devices.
- /// </para>
- /// </remarks>
- [Range(1, 10)]
- [FormerlySerializedAs("iterationsPerFrame")]
- [Tooltip("Number of simulation iterations to execute on each update")]
- public int SimulationIterationsPerFrame = 1;
- /// <summary>
- /// Size of each grid node.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Only valid when liquid resources are initialized.
- /// Or after call to <see cref="UpdateSimulationConstants"/>
- /// </para>
- /// <para>
- /// Grid nodes are all same size and all of them are cubes.
- /// This parameter is length of side of that cube.
- /// </para>
- /// </remarks>
- public float NodeSize { get; private set; }
- /// <summary>
- /// Resolution of the simulation grid.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Has major impact on performance and quality.
- /// This is the first option you want to configure when tweaking performance.
- /// </para>
- /// <para>
- /// Changing resolution while liquid resources are intialized has no effect.
- /// </para>
- /// <para>
- /// This parameter defines number of nodes in largest dimension of grid node
- /// </para>
- /// </remarks>
- [Min(16)]
- [FormerlySerializedAs("gridResolution")]
- [Tooltip(
- "Resolution of the simulation grid. Has major impact on performance and quality. Please see documentation for details.")]
- public int GridResolution = 128;
- /// <summary>
- /// Whether to run simulation.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Has no effect when liquid is not initialized.
- /// </para>
- /// <para>
- /// Disabling simulation will improve performance.
- /// </para>
- /// <para>
- /// Simulation will run for 2 frames after liquid initializations independently of this option,
- /// since liquid can't be rendered otherwise.
- /// </para>
- /// </remarks>
- [FormerlySerializedAs("runSimulation")]
- public bool RunSimulation = true;
- /// <summary>
- /// Whether to render liquid.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Has no effect when liquid is not initialized.
- /// </para>
- /// <para>
- /// Disabling rendering will improve performance.
- /// </para>
- /// <para>
- /// Liquid may still be simulated,
- /// which mean that it may still push objects with force interaction,
- /// update data in detectors/emitters/voids,
- /// and сost performance due to simulation calculatons.
- /// </para>
- /// </remarks>
- [FormerlySerializedAs("runRendering")]
- [Tooltip("Whether to render liquid")]
- public bool RunRendering = true;
- /// <summary>
- /// When enabled, during container movement, liquid stays in place in world space.
- /// </summary>
- /// <remarks>
- /// If you want to move liquid container without disturbing simulation you can disable this.
- /// </remarks>
- [Tooltip("When enabled, during container movement, liquid stays in place in world space")]
- public bool EnableContainerMovementFeedback = true;
- /// <summary>
- /// Whether to render visualised SDFs.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Has no effect when liquid is not initialized.
- /// </para>
- /// <para>
- /// This option is only meant for debugging purposes.
- /// It's strongly recommended to not enable it in final builds.
- /// </para>
- /// </remarks>
- [FormerlySerializedAs("visualizeSceneSDF")]
- [Tooltip("Whether to render visualized SDFs")]
- public bool VisualizeSceneSDF = false;
- /// <summary>
- /// Reference to <see cref="DataStructures::ZibraLiquidSolverParameters">ZibraLiquidSolverParameters</see>
- /// corresponding to this object.
- /// </summary>
- public ZibraLiquidSolverParameters SolverParameters
- {
- get {
- if (SolverParametersInternal == null)
- {
- SolverParametersInternal = gameObject.GetComponent<ZibraLiquidSolverParameters>();
- if (SolverParametersInternal == null)
- {
- SolverParametersInternal = gameObject.AddComponent<ZibraLiquidSolverParameters>();
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(this);
- #endif
- }
- }
- return SolverParametersInternal;
- }
- }
- /// <summary>
- /// Reference to
- /// <see cref="DataStructures::ZibraLiquidMaterialParameters">ZibraLiquidMaterialParameters</see>
- /// corresponding to this object.
- /// </summary>
- public ZibraLiquidMaterialParameters MaterialParameters
- {
- get {
- if (MaterialParametersInternal == null)
- {
- MaterialParametersInternal = gameObject.GetComponent<ZibraLiquidMaterialParameters>();
- if (MaterialParametersInternal == null)
- {
- MaterialParametersInternal = gameObject.AddComponent<ZibraLiquidMaterialParameters>();
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(this);
- #endif
- }
- }
- return MaterialParametersInternal;
- }
- }
- /// <summary>
- /// Reference to
- /// <see
- /// cref="DataStructures::ZibraLiquidAdvancedRenderParameters">ZibraLiquidAdvancedRenderParameters</see>
- /// corresponding to this object.
- /// </summary>
- public ZibraLiquidAdvancedRenderParameters AdvancedRenderParameters
- {
- get {
- if (AdvancedRenderParametersInternal == null)
- {
- AdvancedRenderParametersInternal = gameObject.GetComponent<ZibraLiquidAdvancedRenderParameters>();
- if (AdvancedRenderParametersInternal == null)
- {
- AdvancedRenderParametersInternal =
- gameObject.AddComponent<ZibraLiquidAdvancedRenderParameters>();
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(this);
- #endif
- }
- }
- return AdvancedRenderParametersInternal;
- }
- }
- /// <summary>
- /// Liquid container size.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Liquid container is always a axis aligned box, and this Vector3 is sides of the box.
- /// </para>
- /// <para>
- /// This indirectly affects performance,
- /// since aspect ratio of this box affects totan number of grid nodes.
- /// See <see cref="GridNodeCount"/>.
- /// </para>
- /// <para>
- /// Liquid can not leave this box.
- /// You can, however, move this box.
- /// If you do that, liquid will try to stay in place in world space,
- /// unless <see cref="EnableContainerMovementFeedback"/> is disabled.
- /// </para>
- /// </remarks>
- [FormerlySerializedAs("containerSize")]
- public Vector3 ContainerSize = new Vector3(10, 10, 10);
- /// <summary>
- /// Whether liquid resources are initialized.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Can be true in edit mode (e.g. during initial state baking).
- /// Can be false in play mode (e.g. disabled liquid).
- /// </para>
- /// <para>
- /// When liquid resources are initialized,
- /// you won't be able to change a lot of liquid parameters.
- /// This is due to fact, that some resources are initialized based on those parameters
- /// and currently, can't be resized without re-initializing simulation.
- /// </para>
- /// </remarks>
- public bool Initialized { get; private set; } = false;
- /// <summary>
- /// Selects whether to update simulation in Update or FixedUpdate.
- /// </summary>
- /// <remarks>
- /// <para>
- /// True corresponds on updating simulation in FixedUpdate.
- /// </para>
- /// <para>
- /// When enabled, number of simulation iterations each frame
- /// may be inconsistent between frames.
- /// So use with care, as it may introduce stutter.
- /// </para>
- /// <para>
- /// If you want to change fixed timestep interval,
- /// change Fixed Timestep in Time section of Project settings.
- /// </para>
- /// </remarks>
- [Tooltip("Selects whether to update simulation in Update or FixedUpdate")]
- public bool UseFixedTimestep = false;
- #endregion
- #region Methods
- /// <summary>
- /// Simulation needs to do some loading before simulation can start.
- /// Loading starts during initialization of engine.
- /// If it takes too long and you start simulation too early
- /// it can stall engine until loading finishes.
- /// You can use this method to show loading screen to wait for loading to end
- /// and prevent stalling.
- /// </summary>
- /// <returns>
- /// true - if starting simulation won't trigger stall
- /// false - if starting simulation will trigger stall
- /// </returns>
- public bool IsLoaded()
- {
- return LiquidBridge.ZibraLiquid_IsLoaded() != 0;
- }
- /// <summary>
- /// Stalls engine until all loading is finished
- /// See <see cref="IsLoaded"/>
- /// </summary>
- public void WaitLoad()
- {
- LiquidBridge.ZibraLiquid_WaitLoad();
- }
- /// <summary>
- /// Updates values of some constants based on <see cref="ContainerSize"/> and
- /// <see cref="GridResolution"/>.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Update values of <see cref="NodeSize"/>, <see cref="GridSize"/>
- /// and <see cref="GridNodeCount"/>.
- /// </para>
- /// <para>
- /// Has no effect when liquid is initialized, since you can't modify
- /// aforementioned parameters in this case.
- /// </para>
- /// </remarks>
- public void UpdateSimulationConstants()
- {
- if (Initialized)
- {
- return;
- }
- NodeSize = Math.Max(ContainerSize.x, Math.Max(ContainerSize.y, ContainerSize.z)) / GridResolution;
- GridSize = Vector3Int.CeilToInt(ContainerSize / NodeSize);
- GridNodeCount = GridSize[0] * GridSize[1] * GridSize[2];
- }
- /// <summary>
- /// Returns aproximate size each particle will have in case of resting liquid.
- /// </summary>
- public float GetParticleSize()
- {
- UpdateSimulationConstants();
- return (float)(NodeSize / Math.Pow(SolverParameters.ParticleDensity, 1.0f / 3.0f));
- }
- /// <summary>
- /// Checks if liquid has at least one emitter manipulator.
- /// </summary>
- /// <remarks>
- /// Liquid component must have emitter or non empty initial state,
- /// otherwise it won't be able to generate any particles
- /// and will never generate any actual liquid.
- /// </remarks>
- public bool HasEmitter()
- {
- foreach (var manipulator in Manipulators)
- {
- if (manipulator.GetManipulatorType() == Manipulator.ManipulatorType.Emitter)
- {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// Returns read-only list of colliders.
- /// </summary>
- public ReadOnlyCollection<ZibraLiquidCollider> GetColliderList()
- {
- return SDFColliders.AsReadOnly();
- }
- /// <summary>
- /// Checks whether collider list has specified collider.
- /// </summary>
- public bool HasCollider(ZibraLiquidCollider collider)
- {
- return SDFColliders.Contains(collider);
- }
- /// <summary>
- /// Adds collider to the liquid.
- /// </summary>
- /// <remarks>
- /// Can only be used if liquid is not initialized yet,
- /// e.g. when liquid is disabled.
- /// </remarks>
- public void AddCollider(ZibraLiquidCollider collider)
- {
- if (Initialized)
- {
- Debug.LogWarning(
- "We don't yet support changing number of manipulators/colliders while liquid's resources are initialized.");
- return;
- }
- if (!SDFColliders.Contains(collider))
- {
- SDFColliders.Add(collider);
- SDFColliders.Sort(new SDFColliderCompare());
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(this);
- #endif
- }
- }
- /// <summary>
- /// Removes collider from the liquid.
- /// </summary>
- /// <remarks>
- /// Can only be used if liquid is not initialized yet,
- /// e.g. when liquid is disabled.
- /// </remarks>
- public void RemoveCollider(ZibraLiquidCollider collider)
- {
- if (Initialized)
- {
- Debug.LogWarning(
- "We don't yet support changing number of manipulators/colliders while liquid's resources are initialized.");
- return;
- }
- if (SDFColliders.Contains(collider))
- {
- SDFColliders.Remove(collider);
- SDFColliders.Sort(new SDFColliderCompare());
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(this);
- #endif
- }
- }
- /// <summary>
- /// Returns read-only list of colliders.
- /// </summary>
- public ReadOnlyCollection<Manipulator> GetManipulatorList()
- {
- return Manipulators.AsReadOnly();
- }
- /// <summary>
- /// Checks whether manipulator list has specified manipulator.
- /// </summary>
- public bool HasManipulator(Manipulator manipulator)
- {
- return Manipulators.Contains(manipulator);
- }
- /// <summary>
- /// Adds manipulator to the liquid.
- /// </summary>
- /// <remarks>
- /// Can only be used if liquid is not initialized yet,
- /// e.g. when liquid is disabled.
- /// </remarks>
- public void AddManipulator(Manipulator manipulator)
- {
- if (Initialized)
- {
- Debug.LogWarning("We don't yet support changing number of manipulators/colliders at runtime.");
- return;
- }
- if (!Manipulators.Contains(manipulator))
- {
- Manipulators.Add(manipulator);
- Manipulators.Sort(new ManipulatorCompare());
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(this);
- #endif
- }
- }
- /// <summary>
- /// Removes manipulator from the liquid.
- /// </summary>
- /// <remarks>
- /// Can only be used if liquid is not initialized yet,
- /// e.g. when liquid is disabled.
- /// </remarks>
- public void RemoveManipulator(Manipulator manipulator)
- {
- if (Initialized)
- {
- Debug.LogWarning("We don't yet support changing number of manipulators/colliders at runtime.");
- return;
- }
- if (Manipulators.Contains(manipulator))
- {
- Manipulators.Remove(manipulator);
- Manipulators.Sort(new ManipulatorCompare());
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(this);
- #endif
- }
- }
- /// <summary>
- /// Returns approximate VRAM usage corresponding to <see cref="MaxNumParticles"/>.
- /// </summary>
- /// <returns>
- /// Approximate VRAM usage in bytes.
- /// </returns>
- public ulong GetParticleCountFootprint()
- {
- ulong result = 0;
- int particleCountRounded = GetParticleCountRounded();
- result += (ulong)(MaxNumParticles * 4 * sizeof(float)); // PositionMass
- result += (ulong)(2 * 4 * particleCountRounded * 2 * sizeof(int)); // Affine
- result += (ulong)(particleCountRounded * 4 * sizeof(float)); // PositionMassCopy
- result += (ulong)(particleCountRounded * 2 * sizeof(int)); // nodeParticlePairs
- result += (ulong)(particleCountRounded * sizeof(uint)); // TmpSDFBuff
- result += (ulong)(4 * MaxNumParticles * sizeof(int)); // NodeParticlePairs0 NodeParticlePairs1
- int RadixWorkGroups1 = (int)Math.Ceiling((float)MaxNumParticles / (float)(2 * RADIX_THREADS));
- int RadixWorkGroups2 = (int)Math.Ceiling((float)MaxNumParticles / (float)(RADIX_THREADS * RADIX_THREADS));
- int RadixWorkGroups3 = (int)Math.Ceiling((float)RadixWorkGroups2 / (float)RADIX_THREADS);
- result += (ulong)(RadixWorkGroups1 * HISTO_WIDTH * sizeof(int)); // RadixGroupData1
- result += (ulong)(RadixWorkGroups2 * HISTO_WIDTH * sizeof(int)); // RadixGroupData2
- result += (ulong)((RadixWorkGroups3 + 1) * HISTO_WIDTH * sizeof(int)); // RadixGroupData3
- return result;
- }
- /// <summary>
- /// Returns approximate VRAM usage corresponding to manipulators/colliders SDFs.
- /// </summary>
- /// <returns>
- /// Approximate VRAM usage in bytes.
- /// </returns>
- public ulong GetSDFsFootprint()
- {
- ulong result = 0;
- foreach (var collider in SDFColliders)
- {
- if (collider == null)
- {
- continue;
- }
- var sdf = collider.gameObject.GetComponent<SDFObject>();
- if (sdf)
- result += sdf.GetVRAMFootprint();
- }
- return result;
- }
- /// <summary>
- /// Calculates approximate VRAM usage corresponding to <see cref="GridResolution"/>.
- /// </summary>
- /// <returns>
- /// Approximate VRAM usage in bytes.
- /// </returns>
- public ulong GetGridFootprint()
- {
- ulong result = 0;
- UpdateSimulationConstants();
- result += (ulong)(GridNodeCount * 4 * sizeof(int)); // GridData
- result += (ulong)(GridNodeCount * 4 * sizeof(float)); // GridNormal
- result += (ulong)(GridNodeCount * sizeof(float)); // GridBlur0
- result += (ulong)(GridNodeCount * sizeof(float)); // GridBlur1
- result += (ulong)(GridNodeCount * sizeof(float)); // MassCopy
- result += (ulong)(GridNodeCount * 2 * sizeof(int)); // IndexGrid
- result += (ulong)(GridNodeCount * sizeof(int)); // VertexIDGrid
- result += (ulong)(GridNodeCount * 4 * sizeof(float)); // VertexBuffer
- result += (ulong)(GridNodeCount * sizeof(uint)); // QuadBuffer
- result += (ulong)(GridNodeCount * (sizeof(uint) * 4)); // VertexProperties
- result += (ulong)(GridNodeCount * 2 * sizeof(float)); // GridNormalTexture
- result += (ulong)(GridNodeCount * sizeof(float) / 2); // DensityTexture
- result += (ulong)(GridNodeCount * sizeof(float) / 2); // VelocityTexture
- return result;
- }
- /// <summary>
- /// Initializes liquid simulation resources.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This is automatically called in <c>OnEnable()</c> if not in edit mode.
- /// To run liquid simulation in edit mode, you need to call it manually.
- /// </para>
- /// <para>
- /// On success, sets <see cref="Initialize"/> to true.
- /// </para>
- /// <para>
- /// On fail, cleans up simulation resources and throws an <c>Exception</c>.
- /// </para>
- /// <para>
- /// Initialization allocates GPU resources,
- /// so calling this at runtime may cause stutter.
- /// Prefer to initialize liquid on scene load.
- /// </para>
- /// <para>
- /// Has no effect if liquid is already initialized.
- /// </para>
- /// </remarks>
- public void InitializeSimulation()
- {
- if (Initialized)
- {
- return;
- }
- try
- {
- #if UNITY_IOS
- if (SystemInfo.graphicsDeviceName == "Apple iOS simulator GPU")
- {
- throw new Exception("Zibra Liquid doesn't support iOS simulator. " + "Liquid was disabled.");
- }
- #endif
- #if !ZIBRA_EFFECTS_NO_LICENSE_CHECK && UNITY_EDITOR
- if (!ServerAuthManager.GetInstance().IsLicenseVerified(PluginManager.Effect.Liquid))
- {
- string errorMessage =
- "License wasn't verified. " +
- ServerAuthManager.GetInstance().GetErrorMessage(PluginManager.Effect.Liquid) +
- " Liquid won't run in editor.";
- throw new Exception(errorMessage);
- }
- #endif
- // Copy Rendering Mode to internal variable to prevent user from modifying it during liquid lifetime
- ActiveRenderingMode = CurrentRenderingMode;
- #if UNITY_PIPELINE_HDRP
- if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
- {
- bool missingRequiredParameter = false;
- if (CustomLightHDRP == null
- #if !ZIBRA_EFFECTS_OTP_VERSION
- && ActiveRenderingMode != RenderingMode.UnityRender
- #endif
- )
- {
- Debug.LogError("No Custom Light set in Zibra Liquid.");
- missingRequiredParameter = true;
- }
- if (ReflectionProbeHDRP == null
- #if !ZIBRA_EFFECTS_OTP_VERSION
- && ActiveRenderingMode != RenderingMode.UnityRender
- #endif
- )
- {
- Debug.LogError("No reflection probe added to Zibra Liquid.");
- missingRequiredParameter = true;
- }
- if (missingRequiredParameter)
- {
- throw new Exception("Liquid creation failed due to missing parameter.");
- }
- }
- #endif
- ValidateColliders();
- ValidateManipulators();
- if (InitialState == ZibraLiquid.InitialStateType.NoParticles || BakedInitialStateAsset == null)
- {
- bool haveEmitter = false;
- foreach (var manipulator in Manipulators)
- {
- if (manipulator.GetManipulatorType() == Manipulator.ManipulatorType.Emitter &&
- manipulator.GetComponent<SDFObject>() != null)
- {
- haveEmitter = true;
- break;
- }
- }
- if (!haveEmitter)
- {
- throw new Exception(
- "Liquid creation failed. Liquid have neither initial state nor emitters, or all emitters missing SDF component.");
- }
- }
- Camera.onPreRender += RenderCallBackWrapper;
- SolverCommandBuffer = new CommandBuffer { name = "ZibraLiquid.Solver" };
- CurrentInstanceID = NextInstanceId++;
- ForceCloseCommandEncoder(SolverCommandBuffer);
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.CreateFluidInstance);
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- SolverCommandBuffer.Clear();
- InitializeParticles();
- var initializeGPUReadbackParamsBridgeParams = new InitializeGPUReadbackParams();
- UInt32 manipSize = (UInt32)ManipulatorManager.Elements * STATISTICS_PER_MANIPULATOR * sizeof(Int32);
- initializeGPUReadbackParamsBridgeParams.readbackBufferSize = sizeof(Int32) + manipSize;
- switch (SystemInfo.graphicsDeviceType)
- {
- case GraphicsDeviceType.Direct3D11:
- case GraphicsDeviceType.XboxOne:
- case GraphicsDeviceType.Switch:
- case GraphicsDeviceType.Direct3D12:
- case GraphicsDeviceType.XboxOneD3D12:
- initializeGPUReadbackParamsBridgeParams.maxFramesInFlight = QualitySettings.maxQueuedFrames + 1;
- break;
- default:
- initializeGPUReadbackParamsBridgeParams.maxFramesInFlight = (int)MaxFramesInFlight;
- break;
- }
- IntPtr nativeCreateInstanceBridgeParams =
- Marshal.AllocHGlobal(Marshal.SizeOf(initializeGPUReadbackParamsBridgeParams));
- Marshal.StructureToPtr(initializeGPUReadbackParamsBridgeParams, nativeCreateInstanceBridgeParams, true);
- SolverCommandBuffer.Clear();
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.InitializeGpuReadback,
- nativeCreateInstanceBridgeParams);
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- ToFreeOnExit.Add(nativeCreateInstanceBridgeParams);
- InitializeSolver();
- Initialized = true;
- #if UNITY_EDITOR
- ZibraLiquidAnalytics.TrackSimulationInitialization(this);
- ZibraEffectsPresetAnalytics.SendPresetAnalyticsData(new string[]
- {
- AdvancedRenderParameters.PresetName,
- SolverParameters.PresetName,
- MaterialParameters.PresetName,
- });
- #endif
- }
- catch (Exception)
- {
- ClearRendering();
- ClearSolver();
- throw;
- }
- }
- /// <summary>
- /// Releases liquid simulation resources.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This is automatically called in <c>OnDisable()</c>.
- /// When running liquid simulation in edit mode,
- /// you may want to call it manually.
- /// </para>
- /// <para>
- /// Sets <see cref="Initialize"/> to false.
- /// </para>
- /// <para>
- /// Releases GPU resources and so frees up VRAM.
- /// </para>
- /// <para>
- /// Has no effect if liquid is not initialized.
- /// </para>
- /// </remarks>
- public void ReleaseSimulation()
- {
- if (!Initialized)
- {
- return;
- }
- ClearRendering();
- ClearSolver();
- Initialized = false;
- // If ZibraLiquid object gets disabled/destroyed
- // We still may need to do cleanup few frames later
- // So we create new gameobject which allows us to run cleanup code
- ZibraLiquidGPUGarbageCollector.CreateGarbageCollector();
- }
- /// <summary>
- /// Runs liquid simulation.
- /// </summary>
- /// <remarks>
- /// <para>
- /// You don't need to call it manually, unless you want to run liquid in edit mode.
- /// In play mode it's called automatically in <c>Update</c> or <c>FixedUpdate</c>
- /// depending on <see cref="UseFixedTimestep"/>
- /// </para>
- /// <para>
- /// Executes <see cref="SimulationIterationsPerFrame"/> number of liquid simulation iterations.
- /// </para>
- /// </remarks>
- public void UpdateSimulation(float deltaTime)
- {
- UpdateUnityRender();
- UpdateNativeRenderParams();
- if (!IsSimulationEnabled())
- {
- return;
- }
- Timestep =
- Math.Min(SimulationTimeScale * deltaTime / (float)SimulationIterationsPerFrame, MaxAllowedTimestep);
- for (var i = 0; i < SimulationIterationsPerFrame; i++)
- {
- StepPhysics();
- }
- SolverCommandBuffer.Clear();
- // copy grid data to 3d texture for rendering after physics steps
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- #if UNITY_EDITOR
- NotifyChange();
- #endif
- }
- /// <summary>
- /// Updates Mesh object used for Unity Render.
- /// </summary>
- /// <remarks>
- /// <para>
- /// In case <see cref="CurrentRenderingMode"/> is set to Unity Render mode,
- /// creates or enabled mesh used for it.
- /// Otherwise disabled that mesh (if it exists).
- /// </para>
- /// <para>
- /// If you set <see cref="CurrentRenderingMode"/> to Unity Render mode via script,
- /// you may want to call this method so make liquid create liquid mesh used for rendering,
- /// so you can configure that newly created object.
- /// </para>
- /// <para>
- /// Executes <see cref="SimulationIterationsPerFrame"/> number of liquid simulation iterations.
- /// </para>
- /// </remarks>
- /// <returns>
- /// GameObject used for Unity Render, or null if it doesn't exist.
- /// In case <see cref="CurrentRenderingMode"/> is set to Unity Render mode,
- /// valid GameObject is always returned.
- /// Otherwise object may be returned if it was created previously.
- /// </returns>
- public GameObject UpdateUnityRender()
- {
- // This function can be called independently of whether liquid is initialized or not
- // So need special care when querying rendering mode
- RenderingMode effectiveRenderingMode = CurrentRenderingMode;
- if (Initialized)
- {
- effectiveRenderingMode = ActiveRenderingMode;
- }
- #if !ZIBRA_EFFECTS_OTP_VERSION
- if (effectiveRenderingMode == RenderingMode.UnityRender)
- {
- Transform meshTransform = transform.Find("ZibraLiquidMesh");
- if (meshTransform == null)
- {
- GameObject obj = new GameObject();
- obj.name = "ZibraLiquidMesh";
- meshTransform = obj.transform;
- meshTransform.SetParent(transform, false);
- }
- GameObject meshObject = meshTransform.gameObject;
- // Add renderer components if not present
- if (meshObject.GetComponent<MeshFilter>() == null)
- {
- meshObject.AddComponent(typeof(MeshFilter));
- }
- if (meshObject.GetComponent<MeshRenderer>() == null)
- {
- meshObject.AddComponent(typeof(MeshRenderer));
- MeshRenderer meshRenderer = meshObject.GetComponent<MeshRenderer>();
- meshRenderer.material = new Material(Shader.Find("Diffuse"));
- meshRenderer.enabled = true;
- }
- else
- {
- MeshRenderer meshRenderer = meshObject.GetComponent<MeshRenderer>();
- meshRenderer.enabled = true;
- }
- MeshFilter meshFilter = meshObject.GetComponent<MeshFilter>();
- if (meshFilter.sharedMesh != LiquidMesh)
- {
- meshFilter.sharedMesh = LiquidMesh;
- }
- meshObject.SetActive(RunRendering);
- return meshObject;
- }
- else
- #endif
- {
- Transform meshTransform = transform.Find("ZibraLiquidMesh");
- if (meshTransform == null)
- return null;
- GameObject meshObject = meshTransform.gameObject;
- meshObject.SetActive(false);
- return meshObject;
- }
- }
- public List<string> GetStats()
- {
- float ResolutionScale = EnableDownscale ? DownscaleFactor : 1.0f;
- float PixelCountScale = ResolutionScale * ResolutionScale;
- return new List<string> {
- "Liquid Simulation",
- $"Instance: {name}",
- $"Grid size: {GridSize}",
- $"Render resolution: {ResolutionScale * 100.0f}%",
- $"Render pixel count: {PixelCountScale * 100.0f}%",
- $"Max particle count: {MaxNumParticles}",
- $"Current particle count: {CurrentParticleNumber}"
- };
- }
- #if UNITY_EDITOR
- /// <summary>
- /// (Editor only) Validates liquid parameters and fixes them as needed.
- /// </summary>
- public void OnValidate()
- {
- transform.rotation = Quaternion.identity;
- transform.localScale = Vector3.one;
- switch (CurrentRenderingMode)
- {
- case RenderingMode.MeshRender:
- #if !ZIBRA_EFFECTS_OTP_VERSION
- case RenderingMode.UnityRender:
- #endif
- break;
- default:
- CurrentRenderingMode = RenderingMode.MeshRender;
- UnityEditor.EditorUtility.SetDirty(this);
- break;
- }
- ContainerSize[0] = Math.Max(ContainerSize[0], 1e-3f);
- ContainerSize[1] = Math.Max(ContainerSize[1], 1e-3f);
- ContainerSize[2] = Math.Max(ContainerSize[2], 1e-3f);
- UpdateSimulationConstants();
- if (GetComponent<ZibraLiquidMaterialParameters>() == null)
- {
- gameObject.AddComponent<ZibraLiquidMaterialParameters>();
- UnityEditor.EditorUtility.SetDirty(this);
- }
- if (GetComponent<ZibraLiquidSolverParameters>() == null)
- {
- gameObject.AddComponent<ZibraLiquidSolverParameters>();
- UnityEditor.EditorUtility.SetDirty(this);
- }
- if (GetComponent<ZibraLiquidAdvancedRenderParameters>() == null)
- {
- gameObject.AddComponent<ZibraLiquidAdvancedRenderParameters>();
- UnityEditor.EditorUtility.SetDirty(this);
- }
- if (GetComponent<ZibraManipulatorManager>() == null)
- {
- gameObject.AddComponent<ZibraManipulatorManager>();
- UnityEditor.EditorUtility.SetDirty(this);
- }
- ValidateColliders();
- ValidateManipulators();
- if (BakedInitialStateAsset)
- {
- int bakedLiquidHeader = BitConverter.ToInt32(BakedInitialStateAsset.bytes, 0);
- if (!IsValidBakedLiquidHeader(bakedLiquidHeader))
- {
- BakedInitialStateAsset = null;
- UnityEditor.EditorUtility.SetDirty(this);
- }
- }
- }
- /// <summary>
- /// (Editor only) Save current simulation state
- /// </summary>
- public BakedInitialState SerializeCurrentLiquidState()
- {
- int[] ParticleNumberArray = new int[1];
- ParticleNumber.GetData(ParticleNumberArray, 0, 0, 1);
- BakedInitialState initialStateData = new BakedInitialState();
- initialStateData.ParticleCount = ParticleNumberArray[0];
- int currentAffineIndex = 1 - LiquidBridge.ZibraLiquid_GetCurrentAffineBufferIndex(CurrentInstanceID);
- InitialState = InitialStateType.BakedLiquidState;
- Array.Resize(ref initialStateData.Positions, initialStateData.ParticleCount);
- PositionMass.GetData(initialStateData.Positions);
- Array.Resize(ref initialStateData.AffineVelocity, 4 * initialStateData.ParticleCount);
- Affine[currentAffineIndex].GetData(initialStateData.AffineVelocity);
- return initialStateData;
- }
- #endif
- #endregion
- #endregion
- #region Deprecated
- /// @cond SHOW_DEPRECATED
- #region Properties
- #pragma warning disable 0067
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("onChanged is deprecated. Please use OnChanged.", true)]
- public event Action onChanged;
- #pragma warning restore 0067
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("color0 is deprecated. Please use Color0.", true)]
- [NonSerialized]
- public RenderTexture color0;
- [NonSerialized]
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("color1 is deprecated. Please use Color1.", true)]
- public RenderTexture color1;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("color2 is deprecated. Please use Color2.", true)]
- [NonSerialized]
- public RenderTexture color2;
- [NonSerialized]
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("upscaleColor is deprecated. Please use UpscaleColor.", true)]
- public RenderTexture upscaleColor;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("depth is deprecated. Please use Depth.", true)]
- [NonSerialized]
- public RenderTexture depth;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("timestep is deprecated. Please use Timestep.", true)]
- [NonSerialized]
- public float timestep;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("simulationInternalTime is deprecated. Please use SimulationInternalTime.", true)]
- [NonSerialized]
- public float simulationInternalTime;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("simulationInternalFrame is deprecated. Please use SimulationInternalFrame.", true)]
- [NonSerialized]
- public int simulationInternalFrame;
- /// @deprecated
- /// Only used for backwards compatibility
- [NonSerialized]
- [Obsolete(
- "reflectionProbe is deprecated. Use ReflectionProbeBRP or ReflectionProbeHDRP instead depending on your Rendering Pipeline (URP uses ReflectionProbeBRP).",
- true)]
- public ReflectionProbe reflectionProbe;
- #if UNITY_PIPELINE_HDRP
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("reflectionProbeHDRP is deprecated. Please use ReflectionProbeHDRP.", true)]
- [NonSerialized]
- public HDProbe reflectionProbeHDRP;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("customLightHDRP is deprecated. Please use CustomLightHDRP.", true)]
- [NonSerialized]
- public Light customLightHDRP;
- #endif // UNITY_PIPELINE_HDRP
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("reflectionProbeSRP is deprecated. Please use ReflectionProbeBRP.", true)]
- [NonSerialized]
- public ReflectionProbe reflectionProbeSRP;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("timeStepMax is deprecated. Please use MaxAllowedTimestep.", true)]
- [NonSerialized]
- public float timeStepMax;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("maxFramesInFlight is deprecated. Please use MaxFramesInFlight.", true)]
- [NonSerialized]
- public UInt32 maxFramesInFlight;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("simTimePerSec is deprecated. Please use SimulationTimeScale.", true)]
- [NonSerialized]
- public float simTimePerSec;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("activeParticleNumber is deprecated. Please use CurrentParticleNumber.", true)]
- [NonSerialized]
- public int activeParticleNumber;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("iterationsPerFrame is deprecated. Please use SimulationIterationsPerFrame.", true)]
- [NonSerialized]
- public int iterationsPerFrame;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("CellSize is deprecated. Please use NodeSize.", true)]
- [NonSerialized]
- public float CellSize;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("gridResolution is deprecated. Please use GridResolution.", true)]
- [NonSerialized]
- public int gridResolution;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("runSimulation is deprecated. Please use RunSimulation.", true)]
- [NonSerialized]
- public bool runSimulation;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("runRendering is deprecated. Please use RunRendering.", true)]
- [NonSerialized]
- public bool runRendering;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("visualizeSceneSDF is deprecated. Please use VisualizeSceneSDF.", true)]
- [NonSerialized]
- public bool visualizeSceneSDF;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("solverParameters is deprecated. Please use SolverParameters.", true)]
- [NonSerialized]
- public ZibraLiquidSolverParameters solverParameters;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("materialParameters is deprecated. Please use MaterialParameters.", true)]
- [NonSerialized]
- public ZibraLiquidSolverParameters materialParameters;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("renderingParameters is deprecated. Please use AdvancedRenderParameters.", true)]
- [NonSerialized]
- public ZibraLiquidAdvancedRenderParameters renderingParameters;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("containerSize is deprecated. Please use ContainerSize.", true)]
- [NonSerialized]
- public Vector3 containerSize;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("initialized is deprecated. Please use Initialized.", true)]
- [NonSerialized]
- public bool initialized;
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("useFixedTimestep is deprecated. Please use UseFixedTimestep.", true)]
- [NonSerialized]
- public bool useFixedTimestep = false;
- #endregion
- #region Methods
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("Init is deprecated. Please use InitializeSimulation.", true)]
- public void Init()
- {
- }
- /// @deprecated
- /// Only used for backwards compatibility
- [Obsolete("StopSolver is deprecated. Please use ReleaseSimulation.", true)]
- public void StopSolver()
- {
- }
- #endregion
- /// @endcond
- #endregion
- #region Implementation details
- #region Interop structures
- [StructLayout(LayoutKind.Sequential)]
- private class UnityTextureBridge
- {
- public IntPtr texture;
- public LiquidBridge.TextureFormat format;
- }
- [StructLayout(LayoutKind.Sequential)]
- private class RegisterParticlesBuffersBridgeParams
- {
- public IntPtr PositionMass;
- public IntPtr AffineVelocity0;
- public IntPtr AffineVelocity1;
- public IntPtr ParticleNumber;
- }
- [StructLayout(LayoutKind.Sequential)]
- private class InitializeGPUReadbackParams
- {
- public UInt32 readbackBufferSize;
- public Int32 maxFramesInFlight;
- }
- [StructLayout(LayoutKind.Sequential)]
- private struct TextureUploadData
- {
- public IntPtr data;
- public Int32 dataSize;
- public Int32 rowPitch;
- public Int32 dimensionX;
- public Int32 dimensionY;
- public Int32 dimensionZ;
- };
- [StructLayout(LayoutKind.Sequential)]
- private class RegisterManipulatorsBridgeParams
- {
- public Int32 ManipulatorNum;
- public IntPtr ManipulatorBufferDynamic;
- public IntPtr SDFObjectBuffer;
- public IntPtr ManipulatorBufferStatistics;
- public IntPtr ManipulatorParams;
- public Int32 SDFObjectCount;
- public IntPtr SDFObjectData;
- public IntPtr ManipIndices;
- public UnityTextureBridge EmbeddingsTexture;
- public UnityTextureBridge SDFGridTexture;
- public UnityTextureBridge HeightmapTexture;
- public TextureUploadData EmbeddigsData;
- public TextureUploadData SDFGridData;
- }
- [StructLayout(LayoutKind.Sequential)]
- private class RegisterSolverBuffersBridgeParams
- {
- public IntPtr SimulationParams;
- public IntPtr PositionMassCopy;
- public IntPtr GridData;
- public IntPtr IndexGrid;
- public IntPtr GridBlur0;
- public IntPtr GridBlur1;
- public IntPtr MassCopy;
- public IntPtr TmpSDFBuff;
- public IntPtr GridNormal;
- public IntPtr NodeParticlePairs0;
- public IntPtr NodeParticlePairs1;
- public IntPtr RadixGroupData1;
- public IntPtr RadixGroupData2;
- public IntPtr RadixGroupData3;
- public IntPtr Counters;
- public IntPtr VertexIDGrid;
- public IntPtr VertexBuffer0;
- public IntPtr VertexBuffer1;
- public IntPtr QuadBuffer;
- public IntPtr TransferDataBuffer;
- public IntPtr MeshRenderIndexBuffer;
- public IntPtr ParticleSpeciesData;
- public Int32 ParticleSpeciesCount;
- public IntPtr UnityMeshVertexBuffer;
- public IntPtr UnityMeshIndexBuffer;
- public IntPtr VertexData;
- public UnityTextureBridge GridNormals;
- public UnityTextureBridge GridDensity;
- public UnityTextureBridge GridVelocity;
- public IntPtr EffectParticleData0;
- public IntPtr EffectParticleData1;
- }
- [StructLayout(LayoutKind.Sequential)]
- private class RegisterRenderResourcesBridgeParams
- {
- public UnityTextureBridge Depth;
- public UnityTextureBridge Color0;
- public UnityTextureBridge Color1;
- public UnityTextureBridge Color2;
- public UnityTextureBridge SceneDepth;
- public UnityTextureBridge ParticlesRT;
- }
- [StructLayout(LayoutKind.Sequential)]
- private class CameraParams
- {
- public Matrix4x4 View;
- public Matrix4x4 Projection;
- public Matrix4x4 ProjectionInverse;
- public Matrix4x4 ViewProjection;
- public Matrix4x4 ViewProjectionInverse;
- public Matrix4x4 EyeRayCameraCoeficients;
- public Vector3 WorldSpaceCameraPos;
- public Int32 CameraID;
- public Vector4 ZBufferParams;
- public Vector2 CameraResolution;
- public Single CameraDownscaleFactor;
- private Single CameraParamsPadding1;
- }
- [StructLayout(LayoutKind.Sequential)]
- private class MeshRenderGlobalParams
- {
- public Vector2 RenderingParameterPadding1;
- public Int32 DisableRaymarch;
- public Single LiquidIOR;
- public Single RayMarchIsoSurface;
- public Int32 UnderwaterRender;
- public Single RayMarchStepSize;
- public Single RayMarchStepFactor;
- public Int32 RayMarchMaxSteps;
- public Int32 TwoBouncesEnabled;
- public Vector2Int RayMarchResolution;
- public Single FoamingIntensity;
- public Single FoamingDecay;
- public Single FoamingThreshold;
- public Single FoamBrightness;
- public Vector4 Absorption;
- public Single FoamMotionBlur;
- public Single FoamSize;
- public Single FoamDiffusion;
- public Single FoamSpawning;
- public Single FoamingDecaySmoothness;
- public Single FoamingOcclusionDistance;
- public Single SimulationParamPadding2;
- public Single SimulationParamPadding3;
- };
- [StructLayout(LayoutKind.Sequential)]
- private class RenderParams
- {
- public Single BlurRadius;
- public Single RenderParamsPadding1;
- public Single NeuralSamplingDistance;
- public Single SDFDebug;
- public Int32 RenderingMode;
- public Int32 VertexOptimizationIterations;
- public Int32 MeshOptimizationIterations;
- public Single DualContourIsoValue;
- public Single MeshOptimizationStep;
- public Single CameraDensity;
- public Int32 MaxVertexBufferSize;
- public Int32 MaxIndexBufferSize;
- public Vector3 RenderParamsContainerPos;
- public float RenderParams_space0;
- }
- [StructLayout(LayoutKind.Sequential)]
- private class SimulationParams
- {
- public Vector3 GridSize;
- public Int32 ParticleCount;
- public Vector3 ContainerScale;
- public Int32 NodeCount;
- public Vector3 SimulationParamsContainerPos;
- public Single TimeStep;
- public Int32 SimulationFrame;
- public Single DensityBlurRadius;
- public Single LiquidIsosurfaceThreshold;
- public Single VertexOptimizationStep;
- public Vector3 ParticleTranslation;
- public Single GlobalVelocityLimit;
- public Single MinimumVelocity;
- public Single BlurNormalizationConstant;
- public Int32 MaxParticleCount;
- public Int32 VisualizeSDF;
- public Single SimulationTime;
- public Single FoamBuoyancy;
- public Int32 ParticleSpeciesCount;
- public Single SimulationParameterPadding;
- public Int32 MaxEffectParticleCount;
- public Int32 FoamParticleLifetime;
- public Single padding0;
- public Int32 EnableContainerMovementFeedback;
- public Int32 EnableFoam;
- public Single SimulationParamPadding1;
- public Single SimulationParamPadding2;
- public Single SimulationParamPadding3;
- }
- [StructLayout(LayoutKind.Sequential)]
- private class ParticleSpeciesParameters
- {
- public Vector3 Gravity;
- public Single AffineAmmount;
- public Single LiquidStiffness;
- public Single RestDensity;
- public Single SurfaceTension;
- public Single AffineDivergenceDecay;
- public Vector3 Material;
- public Single VelocityLimit;
- }
- #endregion
- private RenderTexture DepthTexture;
- internal const int MPM_THREADS = 256;
- internal const int STATISTICS_PER_MANIPULATOR = 8;
- private const int RADIX_THREADS = 128;
- private const int HISTO_WIDTH = 32;
- private const int DEPTH_COPY_WORKGROUP = 16;
- private const int ADDITIONAL_VERTICES = 3000;
- private static int NextInstanceId = 0;
- private int CopyDepthID;
- #if ZIBRA_EFFECTS_PROFILING_ENABLED
- [NonSerialized]
- internal LiquidBridge.DebugTimestampItem[] DebugTimestampsItems = new LiquidBridge.DebugTimestampItem[100];
- #endif
- internal struct MaterialPair
- {
- public Material CurrentMaterial;
- public Material SharedMaterial;
- // Returns true if dirty
- public bool SetMaterial(Material mat)
- {
- if (SharedMaterial != mat)
- {
- CurrentMaterial = (mat != null ? Material.Instantiate(mat) : null);
- SharedMaterial = mat;
- return true;
- }
- return false;
- }
- }
- internal class CameraResources
- {
- public RenderTexture Background;
- public MaterialPair LiquidMaterial;
- public MaterialPair UpscaleMaterial;
- public MaterialPair SDFRenderMaterial;
- public bool IsDirty = true;
- }
- private enum GraphicsBufferType
- {
- Vertex,
- Index
- }
- private GraphicsBuffer CreateGraphicsBuffer(GraphicsBufferType type, int count, int stride)
- {
- return new GraphicsBuffer(type == GraphicsBufferType.Vertex
- ? GraphicsBuffer.Target.Raw | GraphicsBuffer.Target.Vertex
- : GraphicsBuffer.Target.Raw | GraphicsBuffer.Target.Index,
- count, stride);
- }
- // We need to keep MaxFoamParticlesCount constant during runtime so we cache it on solver init and null on stop
- private int MaxFoamParticles = 0;
- private ZibraLiquidSolverParameters SolverParametersInternal;
- private ZibraLiquidMaterialParameters MaterialParametersInternal;
- private ZibraLiquidAdvancedRenderParameters AdvancedRenderParametersInternal;
- private ZibraManipulatorManager ManipulatorManagerInternal;
- internal ZibraManipulatorManager ManipulatorManager
- {
- get {
- if (ManipulatorManagerInternal == null)
- {
- ManipulatorManagerInternal = gameObject.GetComponent<ZibraManipulatorManager>();
- if (ManipulatorManagerInternal == null)
- {
- ManipulatorManagerInternal = gameObject.AddComponent<ZibraManipulatorManager>();
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(this);
- #endif
- }
- }
- return ManipulatorManagerInternal;
- }
- }
- [NonSerialized]
- private Vector2Int CurrentTextureResolution = new Vector2Int(0, 0);
- // List of all cameras we have added a command buffer to
- private readonly Dictionary<Camera, CommandBuffer> CameraCBs = new Dictionary<Camera, CommandBuffer>();
- // Each camera needs its own resources
- private List<Camera> Cameras = new List<Camera>();
- internal Dictionary<Camera, IntPtr> CamNativeParams = new Dictionary<Camera, IntPtr>();
- private Dictionary<Camera, IntPtr> CamMeshRenderParams = new Dictionary<Camera, IntPtr>();
- private Dictionary<Camera, Vector2Int> CamRenderResolutions = new Dictionary<Camera, Vector2Int>();
- private Dictionary<Camera, Vector2Int> CamNativeResolutions = new Dictionary<Camera, Vector2Int>();
- internal Dictionary<Camera, CameraResources> CameraResourcesMap = new Dictionary<Camera, CameraResources>();
- private CameraParams CameraRenderParams;
- private MeshRenderGlobalParams MeshRenderGlobalParamsContainer;
- private RenderParams RenderParamsContainer;
- #if ZIBRA_EFFECTS_PROFILING_ENABLED
- [NonSerialized]
- public uint DebugTimestampsItemsCount = 0;
- #endif
- private SimulationParams LiquidParameters;
- private ComputeBuffer GridData;
- private ComputeBuffer IndexGrid;
- private ComputeBuffer GridNormal;
- private Texture3D SDFGridTexture;
- private Texture3D EmbeddingsTexture;
- private ComputeBuffer PositionMassCopy;
- private ComputeBuffer GridBlur0;
- private ComputeBuffer GridBlur1;
- private ComputeBuffer MassCopy;
- private ComputeBuffer TmpSDFBuff;
- private ComputeBuffer NodeParticlePairs0;
- private ComputeBuffer NodeParticlePairs1;
- private ComputeBuffer EffectParticleData0;
- private ComputeBuffer EffectParticleData1;
- private ComputeBuffer RadixGroupData1;
- private ComputeBuffer RadixGroupData2;
- private ComputeBuffer RadixGroupData3;
- private ComputeBuffer DynamicManipulatorData;
- private ComputeBuffer SDFObjectData;
- private ComputeBuffer ManipulatorStatistics;
- private ComputeBuffer ParticleSpeciesData;
- private CommandBuffer SolverCommandBuffer;
- private List<IntPtr> ToFreeOnExit = new List<IntPtr>();
- private RenderingMode ActiveRenderingMode = RenderingMode.MeshRender;
- private CameraEvent ActiveInjectionPoint = CameraEvent.AfterSkybox;
- private IntPtr NativeManipData;
- private IntPtr NativeSDFData;
- private IntPtr NativeFluidData;
- private IntPtr NativeSolverData;
- [SerializeField]
- [FormerlySerializedAs("sdfColliders")]
- private List<ZibraLiquidCollider> SDFColliders = new List<ZibraLiquidCollider>();
- [SerializeField]
- [FormerlySerializedAs("manipulators")]
- private List<Manipulator> Manipulators = new List<Manipulator>();
- #if UNITY_PIPELINE_HDRP
- private LiquidHDRPRenderComponent HDRPRenderer;
- #endif // UNITY_PIPELINE_HDRP
- private IntPtr GetNativePtr(ComputeBuffer buffer)
- {
- return buffer == null ? IntPtr.Zero : buffer.GetNativeBufferPtr();
- }
- private IntPtr GetNativePtr(GraphicsBuffer buffer)
- {
- return buffer == null ? IntPtr.Zero : buffer.GetNativeBufferPtr();
- }
- private IntPtr GetNativePtr(RenderTexture texture)
- {
- return texture == null ? IntPtr.Zero : texture.GetNativeTexturePtr();
- }
- private IntPtr GetNativePtr(Texture3D texture)
- {
- return texture == null ? IntPtr.Zero : texture.GetNativeTexturePtr();
- }
- internal bool IsRenderingEnabled()
- {
- // We need at least 2 simulation frames before we can start rendering
- return Initialized && RunRendering && (SimulationInternalFrame > 1)
- #if !ZIBRA_EFFECTS_OTP_VERSION
- && (ActiveRenderingMode != RenderingMode.UnityRender || VisualizeSceneSDF)
- #endif
- ;
- }
- private bool IsSimulationEnabled()
- {
- // We need at least 2 simulation frames before we can start rendering
- // So we need to always simulate first 2 frames
- return Initialized && (RunSimulation || (SimulationInternalFrame <= 2));
- }
- private void SetupScriptableRenderComponent()
- {
- #if UNITY_PIPELINE_HDRP
- #if UNITY_EDITOR
- if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
- {
- HDRPRenderer = gameObject.GetComponent<LiquidHDRPRenderComponent>();
- if (HDRPRenderer != null && HDRPRenderer.customPasses.Count == 0)
- {
- DestroyImmediate(HDRPRenderer);
- HDRPRenderer = null;
- }
- if (HDRPRenderer == null)
- {
- HDRPRenderer = gameObject.AddComponent<LiquidHDRPRenderComponent>();
- HDRPRenderer.injectionPoint = CustomPassInjectionPoint.BeforePreRefraction;
- HDRPRenderer.AddPassOfType(typeof(LiquidHDRPRenderComponent.FluidHDRPRender));
- LiquidHDRPRenderComponent.FluidHDRPRender renderer =
- HDRPRenderer.customPasses[0] as LiquidHDRPRenderComponent.FluidHDRPRender;
- renderer.name = "ZibraLiquidRenderer";
- renderer.liquid = this;
- }
- }
- #endif
- #endif // UNITY_PIPELINE_HDRP
- }
- private void ForceCloseCommandEncoder(CommandBuffer cmdList)
- {
- #if UNITY_EDITOR_OSX || (!UNITY_EDITOR && UNITY_STANDALONE_OSX) || (!UNITY_EDITOR && UNITY_IOS)
- // Unity bug workaround
- // For whatever reason, Unity sometimes doesn't close command encoder when we request it from native plugin
- // So when we try to start our command encoder with active encoder already present it leads to crash
- // This happens when scene have Terrain (I still have no idea why)
- // So we force change command encoder like that, and this one closes gracefully
- if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal)
- {
- cmdList.DispatchCompute(MaterialParameters.NoOpCompute, 0, 1, 1, 1);
- }
- #endif
- }
- private UnityTextureBridge MakeTextureNativeBridge(RenderTexture texture)
- {
- var unityTextureBridge = new UnityTextureBridge();
- if (texture != null)
- {
- unityTextureBridge.texture = GetNativePtr(texture);
- unityTextureBridge.format = LiquidBridge.ToBridgeTextureFormat(texture.graphicsFormat);
- }
- else
- {
- unityTextureBridge.texture = IntPtr.Zero;
- unityTextureBridge.format = LiquidBridge.TextureFormat.None;
- }
- return unityTextureBridge;
- }
- private UnityTextureBridge MakeTextureNativeBridge(Texture3D texture)
- {
- var unityTextureBridge = new UnityTextureBridge();
- unityTextureBridge.texture = GetNativePtr(texture);
- unityTextureBridge.format = LiquidBridge.ToBridgeTextureFormat(texture.graphicsFormat);
- return unityTextureBridge;
- }
- void OnDrawGizmosInternal(bool isSelected)
- {
- if (!enabled)
- {
- return;
- }
- Gizmos.color = Color.yellow;
- if (!isSelected)
- {
- Gizmos.color = new Color(Gizmos.color.r, Gizmos.color.g, Gizmos.color.b, Gizmos.color.a * 0.5f);
- }
- Gizmos.DrawWireCube(transform.position, ContainerSize);
- Gizmos.color = new Color(0.2f, 0.8f, 0.8f);
- if (!isSelected)
- {
- Gizmos.color = new Color(Gizmos.color.r, Gizmos.color.g, Gizmos.color.b, Gizmos.color.a * 0.5f);
- }
- Vector3 voxelSize =
- new Vector3(ContainerSize.x / GridSize.x, ContainerSize.y / GridSize.y, ContainerSize.z / GridSize.z);
- const int GizmosVoxelCubeSize = 2;
- for (int i = -GizmosVoxelCubeSize; i <= GizmosVoxelCubeSize; i++)
- for (int j = -GizmosVoxelCubeSize; j <= GizmosVoxelCubeSize; j++)
- for (int k = -GizmosVoxelCubeSize; k <= GizmosVoxelCubeSize; k++)
- Gizmos.DrawWireCube(transform.position +
- new Vector3(i * voxelSize.x, j * voxelSize.y, k * voxelSize.z),
- voxelSize);
- }
- private void OnDrawGizmosSelected()
- {
- OnDrawGizmosInternal(true);
- }
- private void OnDrawGizmos()
- {
- OnDrawGizmosInternal(false);
- }
- private void Awake()
- {
- SetupScriptableRenderComponent();
- }
- private void OnEnable()
- {
- #if UNITY_EDITOR
- foreach (var manipulator in Manipulators)
- {
- if (manipulator is ZibraLiquidEmitter)
- {
- ZibraLiquidEmitter emitter = manipulator as ZibraLiquidEmitter;
- if (emitter.InitialVelocity.magnitude > SolverParameters.MaximumVelocity)
- {
- Debug.LogWarning("Too high velocity magnitude " + emitter.InitialVelocity.magnitude +
- " on emitter '" + emitter.name + "'. Liquid instance '" + this.name +
- "' MaximumVelocity is " + SolverParameters.MaximumVelocity);
- }
- }
- }
- #endif
- SetupScriptableRenderComponent();
- AllFluids?.Add(this);
- UpdateUnityRender();
- #if UNITY_EDITOR
- if (!UnityEditor.EditorApplication.isPlaying)
- {
- return;
- }
- #endif
- AddToStatReporter();
- InitializeSimulation();
- }
- private void InitializeParticles()
- {
- UpdateSimulationConstants();
- LiquidParameters = new SimulationParams();
- NativeFluidData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SimulationParams)));
- NativeSolverData = Marshal.AllocHGlobal((SolverParameters.AdditionalParticleSpecies.Count +
- ZibraLiquidSolverParameters.MAX_RUNTIME_ADDED_SPECIES) *
- Marshal.SizeOf(typeof(ParticleSpeciesParameters)));
- var numParticlesRounded =
- (int)Math.Ceiling((double)MaxNumParticles / MPM_THREADS) * MPM_THREADS; // round to workgroup size
- PositionMass = new ComputeBuffer(MaxNumParticles, 4 * sizeof(float));
- Affine = new ComputeBuffer[2];
- Affine[0] = new ComputeBuffer(4 * numParticlesRounded, 2 * sizeof(int));
- Affine[1] = new ComputeBuffer(4 * numParticlesRounded, 2 * sizeof(int));
- ParticleNumber = new ComputeBuffer(128, sizeof(int));
- int[] particleNumberInitialData = new int[128];
- ParticleNumber.SetData(particleNumberInitialData);
- #if ZIBRA_EFFECTS_DEBUG
- PositionMass.name = "PositionMass";
- Affine[0].name = "Affine0";
- Affine[1].name = "Affine1";
- ParticleNumber.name = "ParticleNumber";
- #endif
- // We mush apply state before we send buffers to native plugin
- // SetData seems to recreate buffers, at least on Metal
- ApplyInitialState();
- int[] Pnums = new int[128];
- for (int i = 0; i < 128; i++)
- {
- Pnums[i] = 0;
- }
- ParticleNumber.SetData(Pnums);
- ManipulatorManager.UpdateConst(Manipulators, SDFColliders);
- ManipulatorManager.HeightmapCountSqrt = (int)Mathf.Ceil(Mathf.Sqrt(ManipulatorManager.HeightmapCount));
- ManipulatorManager.HeightmapSize = Vector2Int.one * Mathf.Max(1, ManipulatorManager.HeightmapCountSqrt *
- SolverParameters.HeightmapResolution);
- CreateTexture(ref HeightmapTexture, ManipulatorManager.HeightmapSize, FilterMode.Point, 0,
- RenderTextureFormat.RHalf, false);
- ManipulatorManager.UpdateDynamic(SolverCommandBuffer, this);
- if (ManipulatorManager.TextureCount > 0)
- {
- EmbeddingsTexture = new Texture3D(
- ManipulatorManager.EmbeddingTextureDimension, ManipulatorManager.EmbeddingTextureDimension,
- ManipulatorManager.EmbeddingTextureDimension, TextureFormat.RGBA32, false);
- SDFGridTexture =
- new Texture3D(ManipulatorManager.SDFTextureDimension, ManipulatorManager.SDFTextureDimension,
- ManipulatorManager.SDFTextureDimension, TextureFormat.RHalf, false);
- EmbeddingsTexture.filterMode = FilterMode.Trilinear;
- SDFGridTexture.filterMode = FilterMode.Trilinear;
- }
- else
- {
- EmbeddingsTexture = new Texture3D(1, 1, 1, TextureFormat.RGBA32, 0);
- SDFGridTexture = new Texture3D(1, 1, 1, TextureFormat.RHalf, 0);
- EmbeddingsTexture.filterMode = FilterMode.Trilinear;
- SDFGridTexture.filterMode = FilterMode.Trilinear;
- }
- int ManipSize = Marshal.SizeOf(typeof(ZibraManipulatorManager.ManipulatorParam));
- int SDFSize = Marshal.SizeOf(typeof(ZibraManipulatorManager.SDFObjectParams));
- // Need to create at least some buffer to bind to shaders
- NativeManipData = Marshal.AllocHGlobal(ManipulatorManager.Elements * ManipSize);
- NativeSDFData = Marshal.AllocHGlobal(ManipulatorManager.SDFObjectList.Count * SDFSize);
- DynamicManipulatorData = new ComputeBuffer(Math.Max(ManipulatorManager.Elements, 1), ManipSize);
- SDFObjectData = new ComputeBuffer(Math.Max(ManipulatorManager.SDFObjectList.Count, 1),
- Marshal.SizeOf(typeof(ZibraManipulatorManager.SDFObjectParams)));
- int ManipulatorStatisticsSize = Math.Max(STATISTICS_PER_MANIPULATOR * ManipulatorManager.Elements, 1);
- // flag ComputeBufferType.IndirectArguments is needed to make R32_UINT buffer on d3d11
- ManipulatorStatistics =
- new ComputeBuffer(ManipulatorStatisticsSize, sizeof(int), ComputeBufferType.IndirectArguments);
- int[] manipulatorStatisticsSizeInitialData = new int[ManipulatorStatisticsSize];
- ManipulatorStatistics.SetData(manipulatorStatisticsSizeInitialData);
- #if ZIBRA_EFFECTS_DEBUG
- DynamicManipulatorData.name = "DynamicManipulatorData";
- SDFObjectData.name = "SDFObjectData";
- ManipulatorStatistics.name = "ManipulatorStatistics";
- #endif
- var gcparamBuffer2 = GCHandle.Alloc(ManipulatorManager.Indices, GCHandleType.Pinned);
- UpdateInteropBuffers();
- var registerManipulatorsBridgeParams = new RegisterManipulatorsBridgeParams();
- registerManipulatorsBridgeParams.ManipulatorNum = ManipulatorManager.Elements;
- registerManipulatorsBridgeParams.ManipulatorBufferDynamic = GetNativePtr(DynamicManipulatorData);
- registerManipulatorsBridgeParams.SDFObjectBuffer = GetNativePtr(SDFObjectData);
- registerManipulatorsBridgeParams.ManipulatorBufferStatistics = ManipulatorStatistics.GetNativeBufferPtr();
- registerManipulatorsBridgeParams.ManipulatorParams = NativeManipData;
- registerManipulatorsBridgeParams.SDFObjectCount = ManipulatorManager.SDFObjectList.Count;
- registerManipulatorsBridgeParams.SDFObjectData = NativeSDFData;
- registerManipulatorsBridgeParams.ManipIndices = gcparamBuffer2.AddrOfPinnedObject();
- registerManipulatorsBridgeParams.EmbeddingsTexture = MakeTextureNativeBridge(EmbeddingsTexture);
- registerManipulatorsBridgeParams.SDFGridTexture = MakeTextureNativeBridge(SDFGridTexture);
- registerManipulatorsBridgeParams.HeightmapTexture = MakeTextureNativeBridge(HeightmapTexture);
- GCHandle embeddingDataHandle = default(GCHandle);
- if (ManipulatorManager.Embeddings.Length > 0)
- {
- embeddingDataHandle = GCHandle.Alloc(ManipulatorManager.Embeddings, GCHandleType.Pinned);
- registerManipulatorsBridgeParams.EmbeddigsData.dataSize =
- Marshal.SizeOf(new Color32()) * ManipulatorManager.Embeddings.Length;
- registerManipulatorsBridgeParams.EmbeddigsData.data = embeddingDataHandle.AddrOfPinnedObject();
- registerManipulatorsBridgeParams.EmbeddigsData.rowPitch =
- Marshal.SizeOf(new Color32()) * EmbeddingsTexture.width;
- registerManipulatorsBridgeParams.EmbeddigsData.dimensionX = EmbeddingsTexture.width;
- registerManipulatorsBridgeParams.EmbeddigsData.dimensionY = EmbeddingsTexture.height;
- registerManipulatorsBridgeParams.EmbeddigsData.dimensionZ = EmbeddingsTexture.depth;
- }
- GCHandle sdfGridHandle = default(GCHandle);
- if (ManipulatorManager.SDFGrid.Length > 0)
- {
- sdfGridHandle = GCHandle.Alloc(ManipulatorManager.SDFGrid, GCHandleType.Pinned);
- registerManipulatorsBridgeParams.SDFGridData.dataSize =
- Marshal.SizeOf(new byte()) * ManipulatorManager.SDFGrid.Length;
- registerManipulatorsBridgeParams.SDFGridData.data = sdfGridHandle.AddrOfPinnedObject();
- registerManipulatorsBridgeParams.SDFGridData.rowPitch =
- Marshal.SizeOf(new byte()) * 2 * SDFGridTexture.width;
- registerManipulatorsBridgeParams.SDFGridData.dimensionX = SDFGridTexture.width;
- registerManipulatorsBridgeParams.SDFGridData.dimensionY = SDFGridTexture.height;
- registerManipulatorsBridgeParams.SDFGridData.dimensionZ = SDFGridTexture.depth;
- }
- IntPtr nativeRegisterManipulatorsBridgeParams =
- Marshal.AllocHGlobal(Marshal.SizeOf(registerManipulatorsBridgeParams));
- Marshal.StructureToPtr(registerManipulatorsBridgeParams, nativeRegisterManipulatorsBridgeParams, true);
- SolverCommandBuffer.Clear();
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.RegisterManipulators,
- nativeRegisterManipulatorsBridgeParams);
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- gcparamBuffer2.Free();
- CameraRenderParams = new CameraParams();
- RenderParamsContainer = new RenderParams();
- MeshRenderGlobalParamsContainer = new MeshRenderGlobalParams();
- var registerParticlesBuffersParams = new RegisterParticlesBuffersBridgeParams();
- registerParticlesBuffersParams.PositionMass = GetNativePtr(PositionMass);
- registerParticlesBuffersParams.AffineVelocity0 = GetNativePtr(Affine[0]);
- registerParticlesBuffersParams.AffineVelocity1 = GetNativePtr(Affine[1]);
- registerParticlesBuffersParams.ParticleNumber = GetNativePtr(ParticleNumber);
- IntPtr nativeRegisterParticlesBuffersParams =
- Marshal.AllocHGlobal(Marshal.SizeOf(registerParticlesBuffersParams));
- Marshal.StructureToPtr(registerParticlesBuffersParams, nativeRegisterParticlesBuffersParams, true);
- SolverCommandBuffer.Clear();
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.RegisterParticlesBuffers,
- nativeRegisterParticlesBuffersParams);
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- ToFreeOnExit.Add(nativeRegisterParticlesBuffersParams);
- }
- private int GetParticleCountRounded()
- {
- return (int)Math.Ceiling((double)MaxNumParticles / MPM_THREADS) * MPM_THREADS; // round to workgroup size;
- }
- private void InitVolumeTexture(ref RenderTexture volume, GraphicsFormat format)
- {
- if (volume)
- return;
- volume = new RenderTexture(GridSize.x, GridSize.y, 0, format);
- volume.volumeDepth = GridSize.z;
- volume.dimension = UnityEngine.Rendering.TextureDimension.Tex3D;
- volume.enableRandomWrite = true;
- volume.filterMode = FilterMode.Trilinear;
- volume.Create();
- if (!volume.IsCreated())
- {
- volume = null;
- throw new NotSupportedException("Failed to create 3D texture.");
- }
- }
- private void InitializeSolver()
- {
- SimulationInternalTime = 0.0f;
- SimulationInternalFrame = 0;
- MaxFoamParticles = MaterialParameters.MaxFoamParticles;
- GridNodeCount = GridSize[0] * GridSize[1] * GridSize[2];
- GridData = new ComputeBuffer(GridNodeCount * 4, sizeof(uint));
- GridNormal = new ComputeBuffer(GridNodeCount, 4 * sizeof(float));
- GridBlur0 = new ComputeBuffer(GridNodeCount, sizeof(float));
- GridBlur1 = new ComputeBuffer(GridNodeCount, sizeof(float));
- MassCopy = new ComputeBuffer(GridNodeCount, sizeof(float));
- ParticleSpeciesData = new ComputeBuffer(SolverParameters.AdditionalParticleSpecies.Count +
- ZibraLiquidSolverParameters.MAX_RUNTIME_ADDED_SPECIES,
- Marshal.SizeOf(typeof(ParticleSpeciesParameters)));
- Counters = new ComputeBuffer(8, sizeof(uint));
- VertexIDGrid = new ComputeBuffer(GridNodeCount, sizeof(int));
- VertexBuffer0 = CreateGraphicsBuffer(GraphicsBufferType.Vertex, 6 * GridNodeCount, sizeof(uint));
- VertexBuffer1 = CreateGraphicsBuffer(GraphicsBufferType.Vertex, 4 * GridNodeCount, sizeof(uint));
- TransferDataBuffer = new ComputeBuffer(1, sizeof(uint));
- MeshRenderIndexBuffer = CreateGraphicsBuffer(GraphicsBufferType.Index, 3 * GridNodeCount, sizeof(uint));
- #if !ZIBRA_EFFECTS_OTP_VERSION
- if (ActiveRenderingMode == RenderingMode.UnityRender)
- {
- LiquidMesh = new Mesh();
- var layout = new[] {
- new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
- new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3),
- };
- int maxVertexCount = GridNodeCount;
- int maxTriangleCount =
- (int)(maxVertexCount * AdvancedRenderParameters.MaxLiquidMeshSize / 3.0f + ADDITIONAL_VERTICES);
- int indexBufferSize = maxTriangleCount * 3;
- int vertexBufferSize = maxTriangleCount * 2;
- LiquidMesh.SetVertexBufferParams(indexBufferSize, layout);
- LiquidMesh.SetIndexBufferParams(vertexBufferSize, IndexFormat.UInt32);
- LiquidMesh.MarkDynamic();
- LiquidMesh.SetVertices(new Vector3[vertexBufferSize], 0, vertexBufferSize);
- LiquidMesh.SetIndices(new int[indexBufferSize], MeshTopology.Triangles, 0);
- LiquidMesh.bounds = new Bounds(Vector3.zero, ContainerSize);
- LiquidMesh.vertexBufferTarget |= GraphicsBuffer.Target.CopyDestination;
- LiquidMesh.indexBufferTarget |= GraphicsBuffer.Target.CopyDestination;
- }
- #endif
- QuadBuffer = new ComputeBuffer(GridNodeCount, sizeof(int));
- VertexProperties = CreateGraphicsBuffer(GraphicsBufferType.Vertex, GridNodeCount, 6 * sizeof(uint));
- IndexGrid = new ComputeBuffer(GridNodeCount, 2 * sizeof(int));
- InitVolumeTexture(ref GridNormalTexture,
- SystemInfo.IsFormatSupported(GraphicsFormat.R16G16B16A16_SFloat, FormatUsage.LoadStore)
- ? GraphicsFormat.R16G16B16A16_SFloat
- : GraphicsFormat.R32G32B32A32_SFloat);
- GridNormalTexture.name = "GridNormalTexture";
- InitVolumeTexture(ref DensityTexture,
- SystemInfo.IsFormatSupported(GraphicsFormat.R16G16B16A16_SFloat, FormatUsage.LoadStore)
- ? GraphicsFormat.R16G16B16A16_SFloat
- : GraphicsFormat.R32G32B32A32_SFloat);
- DensityTexture.name = "DensityTexture";
- InitVolumeTexture(ref VelocityTexture,
- SystemInfo.IsFormatSupported(GraphicsFormat.R16G16B16A16_SFloat, FormatUsage.LoadStore)
- ? GraphicsFormat.R16G16B16A16_SFloat
- : GraphicsFormat.R32G32B32A32_SFloat);
- VelocityTexture.name = "VelocityTexture";
- int NumParticlesRounded = GetParticleCountRounded();
-
- PositionMassCopy = new ComputeBuffer(NumParticlesRounded, 4 * sizeof(float));
- TmpSDFBuff = new ComputeBuffer(NumParticlesRounded, sizeof(uint));
- NodeParticlePairs0 = new ComputeBuffer(2 * NumParticlesRounded, sizeof(int));
- NodeParticlePairs1 = new ComputeBuffer(2 * NumParticlesRounded, sizeof(int));
- EffectParticleData0 = new ComputeBuffer(4 * Math.Max(MaxFoamParticles, 1), sizeof(uint));
- EffectParticleData1 = new ComputeBuffer(4 * Math.Max(MaxFoamParticles, 1), sizeof(uint));
- int RadixWorkGroups1 = (int)Math.Ceiling((float)MaxNumParticles / (float)(2 * RADIX_THREADS));
- int RadixWorkGroups2 = (int)Math.Ceiling((float)MaxNumParticles / (float)(RADIX_THREADS * RADIX_THREADS));
- int RadixWorkGroups3 = (int)Math.Ceiling((float)RadixWorkGroups2 / (float)RADIX_THREADS);
- RadixGroupData1 = new ComputeBuffer(RadixWorkGroups1 * HISTO_WIDTH, sizeof(uint));
- RadixGroupData2 = new ComputeBuffer(RadixWorkGroups2 * HISTO_WIDTH, sizeof(uint));
- RadixGroupData3 = new ComputeBuffer((RadixWorkGroups3 + 1) * HISTO_WIDTH, sizeof(uint));
- #if ZIBRA_EFFECTS_DEBUG
- GridData.name = "GridData";
- GridNormal.name = "GridNormal";
- GridBlur0.name = "GridBlur0";
- GridBlur1.name = "GridBlur1";
- MassCopy.name = "MassCopy";
- TmpSDFBuff.name = "TmpSDFBuff";
- IndexGrid.name = "IndexGrid";
- PositionMassCopy.name = "PositionMassCopy";
- NodeParticlePairs0.name = "NodeParticlePairs0";
- NodeParticlePairs1.name = "NodeParticlePairs1";
- RadixGroupData1.name = "RadixGroupData1";
- RadixGroupData2.name = "RadixGroupData2";
- RadixGroupData3.name = "RadixGroupData3";
- ParticleSpeciesData.name = "ParticleSpeciesData";
- #endif
- SetFluidParameters();
- var gcparamBuffer = GCHandle.Alloc(LiquidParameters, GCHandleType.Pinned);
- var registerSolverBuffersBridgeParams = new RegisterSolverBuffersBridgeParams();
- registerSolverBuffersBridgeParams.SimulationParams = gcparamBuffer.AddrOfPinnedObject();
- registerSolverBuffersBridgeParams.ParticleSpeciesCount =
- SolverParameters.AdditionalParticleSpecies.Count + 1;
- registerSolverBuffersBridgeParams.PositionMassCopy = GetNativePtr(PositionMassCopy);
- registerSolverBuffersBridgeParams.GridData = GetNativePtr(GridData);
- registerSolverBuffersBridgeParams.IndexGrid = GetNativePtr(IndexGrid);
- registerSolverBuffersBridgeParams.GridBlur0 = GetNativePtr(GridBlur0);
- registerSolverBuffersBridgeParams.GridBlur1 = GetNativePtr(GridBlur1);
- registerSolverBuffersBridgeParams.MassCopy = GetNativePtr(MassCopy);
- registerSolverBuffersBridgeParams.TmpSDFBuff = GetNativePtr(TmpSDFBuff);
- registerSolverBuffersBridgeParams.GridNormal = GetNativePtr(GridNormal);
- registerSolverBuffersBridgeParams.NodeParticlePairs0 = GetNativePtr(NodeParticlePairs0);
- registerSolverBuffersBridgeParams.NodeParticlePairs1 = GetNativePtr(NodeParticlePairs1);
- registerSolverBuffersBridgeParams.EffectParticleData0 = GetNativePtr(EffectParticleData0);
- registerSolverBuffersBridgeParams.EffectParticleData1 = GetNativePtr(EffectParticleData1);
- registerSolverBuffersBridgeParams.RadixGroupData1 = GetNativePtr(RadixGroupData1);
- registerSolverBuffersBridgeParams.RadixGroupData2 = GetNativePtr(RadixGroupData2);
- registerSolverBuffersBridgeParams.RadixGroupData3 = GetNativePtr(RadixGroupData3);
- registerSolverBuffersBridgeParams.Counters = GetNativePtr(Counters);
- registerSolverBuffersBridgeParams.VertexIDGrid = GetNativePtr(VertexIDGrid);
- registerSolverBuffersBridgeParams.VertexBuffer0 = GetNativePtr(VertexBuffer0);
- registerSolverBuffersBridgeParams.VertexBuffer1 = GetNativePtr(VertexBuffer1);
- registerSolverBuffersBridgeParams.QuadBuffer = GetNativePtr(QuadBuffer);
- registerSolverBuffersBridgeParams.GridDensity = MakeTextureNativeBridge(DensityTexture);
- registerSolverBuffersBridgeParams.GridVelocity = MakeTextureNativeBridge(VelocityTexture);
- registerSolverBuffersBridgeParams.GridNormals = MakeTextureNativeBridge(GridNormalTexture);
- #if !ZIBRA_EFFECTS_OTP_VERSION
- if (ActiveRenderingMode == RenderingMode.UnityRender)
- {
- registerSolverBuffersBridgeParams.UnityMeshVertexBuffer = LiquidMesh.GetNativeVertexBufferPtr(0);
- registerSolverBuffersBridgeParams.UnityMeshIndexBuffer = LiquidMesh.GetNativeIndexBufferPtr();
- }
- else
- #endif
- {
- registerSolverBuffersBridgeParams.UnityMeshVertexBuffer = IntPtr.Zero;
- registerSolverBuffersBridgeParams.UnityMeshIndexBuffer = IntPtr.Zero;
- }
- registerSolverBuffersBridgeParams.TransferDataBuffer = GetNativePtr(TransferDataBuffer);
- registerSolverBuffersBridgeParams.MeshRenderIndexBuffer = GetNativePtr(MeshRenderIndexBuffer);
- registerSolverBuffersBridgeParams.VertexData = GetNativePtr(VertexProperties);
- registerSolverBuffersBridgeParams.ParticleSpeciesData = GetNativePtr(ParticleSpeciesData);
- IntPtr nativeRegisterSolverBuffersBridgeParams =
- Marshal.AllocHGlobal(Marshal.SizeOf(registerSolverBuffersBridgeParams));
- Marshal.StructureToPtr(registerSolverBuffersBridgeParams, nativeRegisterSolverBuffersBridgeParams, true);
- SolverCommandBuffer.Clear();
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.RegisterSolverBuffers,
- nativeRegisterSolverBuffersBridgeParams);
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- gcparamBuffer.Free();
- SolverCommandBuffer.Clear();
- CopyDepthID = MaterialParameters.RendererCompute.FindKernel("CS_CopyDepth");
- ToFreeOnExit.Add(nativeRegisterSolverBuffersBridgeParams);
- }
- private void Update()
- {
- if (!Initialized)
- {
- return;
- }
- ZibraLiquidGPUGarbageCollector.GCUpdateWrapper();
- #if UNITY_EDITOR
- if (!UnityEditor.EditorApplication.isPlaying)
- {
- return;
- }
- #endif
- if (!UseFixedTimestep)
- UpdateSimulation(Time.smoothDeltaTime);
- UpdateReadback();
- #if ZIBRA_EFFECTS_PROFILING_ENABLED
- if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan)
- {
- UpdateDebugTimestamps();
- }
- #endif
- }
- private void FixedUpdate()
- {
- #if UNITY_EDITOR
- if (!UnityEditor.EditorApplication.isPlaying)
- {
- return;
- }
- #endif
- if (UseFixedTimestep)
- UpdateSimulation(Time.fixedDeltaTime);
- }
- #if ZIBRA_EFFECTS_PROFILING_ENABLED
- public void UpdateDebugTimestamps()
- {
- if (!IsSimulationEnabled())
- {
- return;
- }
- DebugTimestampsItemsCount =
- LiquidBridge.ZibraLiquid_GetDebugTimestamps(CurrentInstanceID, DebugTimestampsItems);
- }
- #endif
- private void UpdateReadback()
- {
- if (!IsSimulationEnabled())
- {
- return;
- }
- SolverCommandBuffer.Clear();
- // This must be called at most ONCE PER FRAME
- // Otherwise you'll get deadlock
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.UpdateReadback);
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- /// ParticleNumber GPUReadback
- UInt32 size = sizeof(UInt32);
- IntPtr readbackData = LiquidBridge.ZibraLiquid_GPUReadbackGetData(CurrentInstanceID, size);
- if (readbackData != IntPtr.Zero)
- {
- CurrentParticleNumber = Marshal.ReadInt32(readbackData);
- }
- UpdateManipulatorStatistics();
- }
- /// <summary>
- /// Update the material parameters
- /// </summary>
- private bool SetMaterialParams(Camera cam)
- {
- bool isDirty = false;
- CameraResources camRes = CameraResourcesMap[cam];
- Material usedUpscaleMaterial = EnableDownscale ? MaterialParameters.UpscaleMaterial : null;
- isDirty = camRes.UpscaleMaterial.SetMaterial(usedUpscaleMaterial) || isDirty;
- bool usingMainMaterial = ActiveRenderingMode == RenderingMode.MeshRender;
- Material CurrentSharedMaterial = usingMainMaterial ? MaterialParameters.FluidMeshMaterial : null;
- isDirty = camRes.LiquidMaterial.SetMaterial(CurrentSharedMaterial) || isDirty;
- Material CurrentMaterial = camRes.LiquidMaterial.CurrentMaterial;
- if (usingMainMaterial)
- {
- if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
- {
- #if UNITY_PIPELINE_HDRP
- if (CustomLightHDRP == null)
- Debug.LogError("No Custom Light set in Zibra Liquid.");
- else
- CurrentMaterial.SetVector("WorldSpaceLightPos", CustomLightHDRP.transform.position);
- if (ReflectionProbeHDRP == null)
- Debug.LogError("No reflection probe added to Zibra Liquid.");
- #endif // UNITY_PIPELINE_HDRP
- }
- else
- {
-
- CurrentMaterial.SetKeyword(new LocalKeyword(CurrentMaterial.shader, "USE_CUBEMAP_REFRACTION"),
- MaterialParameters.UseCubemapRefraction);
- if (ReflectionProbeBRP != null) // custom reflection probe
- {
- CurrentMaterial.EnableKeyword("CUSTOM_REFLECTION_PROBE");
- CurrentMaterial.SetTexture("ReflectionProbe", ReflectionProbeBRP.texture);
- CurrentMaterial.SetVector("ReflectionProbe_HDR", ReflectionProbeBRP.textureHDRDecodeValues);
- CurrentMaterial.SetVector("ReflectionProbe_BoxMax", ReflectionProbeBRP.bounds.max);
- CurrentMaterial.SetVector("ReflectionProbe_BoxMin", ReflectionProbeBRP.bounds.min);
- CurrentMaterial.SetVector("ReflectionProbe_ProbePosition",
- ReflectionProbeBRP.transform.position);
- }
- else
- {
- CurrentMaterial.DisableKeyword("CUSTOM_REFLECTION_PROBE");
- }
- }
- CurrentMaterial.SetFloat("AbsorptionAmount", MaterialParameters.AbsorptionAmount);
- CurrentMaterial.SetFloat("ScatteringAmount", MaterialParameters.ScatteringAmount);
- CurrentMaterial.SetFloat("Metalness", MaterialParameters.Metalness);
- CurrentMaterial.SetFloat("FresnelStrength", MaterialParameters.FresnelStrength);
- CurrentMaterial.SetFloat("RefractionDistortion", MaterialParameters.IndexOfRefraction - 1.0f);
- CurrentMaterial.SetFloat("LiquidIOR", MaterialParameters.IndexOfRefraction);
- CurrentMaterial.SetFloat("Roughness", MaterialParameters.Roughness);
- CurrentMaterial.SetVector("RefractionColor", MaterialParameters.Color);
- CurrentMaterial.SetVector("ReflectionColor", MaterialParameters.ReflectionColor);
- CurrentMaterial.SetVector("EmissiveColor", MaterialParameters.EmissiveColor);
- CurrentMaterial.SetVector("Material1Color", MaterialParameters.Material1.Color);
- CurrentMaterial.SetVector("Material2Color", MaterialParameters.Material2.Color);
- CurrentMaterial.SetVector("Material3Color", MaterialParameters.Material3.Color);
- CurrentMaterial.SetVector("Material1Emission", MaterialParameters.Material1.EmissiveColor);
- CurrentMaterial.SetVector("Material2Emission", MaterialParameters.Material2.EmissiveColor);
- CurrentMaterial.SetVector("Material3Emission", MaterialParameters.Material3.EmissiveColor);
- CurrentMaterial.SetVector("MatMetalness", new Vector3(MaterialParameters.Material1.Metalness,
- MaterialParameters.Material2.Metalness,
- MaterialParameters.Material3.Metalness));
- CurrentMaterial.SetVector("MatAbsorption", new Vector3(MaterialParameters.Material1.AbsorptionAmount,
- MaterialParameters.Material2.AbsorptionAmount,
- MaterialParameters.Material3.AbsorptionAmount));
- CurrentMaterial.SetVector("MatScattering", new Vector3(MaterialParameters.Material1.ScatteringAmount,
- MaterialParameters.Material2.ScatteringAmount,
- MaterialParameters.Material3.ScatteringAmount));
- CurrentMaterial.SetVector("MatRoughness", new Vector3(MaterialParameters.Material1.Roughness,
- MaterialParameters.Material2.Roughness,
- MaterialParameters.Material3.Roughness));
- #if UNITY_PIPELINE_HDRP
- CurrentMaterial.SetVector("LightColor",
- CustomLightHDRP.color * Mathf.Log(CustomLightHDRP.intensity) / 8.0f);
- CurrentMaterial.SetVector("LightDirection", CustomLightHDRP.transform.rotation * new Vector3(0, 0, -1));
- #endif
- CurrentMaterial.SetVector("ContainerScale", ContainerSize);
- CurrentMaterial.SetVector("ContainerPosition", transform.position);
- CurrentMaterial.SetVector("GridSize", (Vector3)GridSize);
- CurrentMaterial.SetFloat("RayMarchResolutionDownscale",
- AdvancedRenderParameters.RayMarchingResolutionDownscale);
- CurrentMaterial.SetFloat("RefractionMinimumDepth", 1e-4f);
- CurrentMaterial.SetFloat("RefractionDepthBias", 1.25f);
- CurrentMaterial.SetTexture("GridNormals", GridNormalTexture);
- CurrentMaterial.SetTexture("MeshRenderData", Color0);
- CurrentMaterial.SetTexture("MeshDepth", Depth, RenderTextureSubElement.Depth);
- CurrentMaterial.SetTexture("GridDensity", DensityTexture);
- if (AdvancedRenderParameters.RefractionBounces ==
- ZibraLiquidAdvancedRenderParameters.RayMarchingBounces.TwoBounces)
- {
- if (MeshRenderGlobalParamsContainer.TwoBouncesEnabled == 0)
- isDirty = true;
- MeshRenderGlobalParamsContainer.TwoBouncesEnabled = 1;
- }
- else
- {
- if (MeshRenderGlobalParamsContainer.TwoBouncesEnabled == 1)
- isDirty = true;
- MeshRenderGlobalParamsContainer.TwoBouncesEnabled = 0;
- }
- #if UNITY_IOS && !UNITY_EDITOR
- if (!EnableDownscale)
- {
- CurrentMaterial.DisableKeyword("FLIP_BACKGROUND_TEXTURE");
- CurrentMaterial.EnableKeyword("FLIP_NATIVE_TEXTURES");
- CurrentMaterial.EnableKeyword("FLIP_PARTICLES_TEXTURE");
- }
- else
- {
- CurrentMaterial.DisableKeyword("FLIP_NATIVE_TEXTURES");
- CurrentMaterial.EnableKeyword("FLIP_BACKGROUND_TEXTURE");
- CurrentMaterial.DisableKeyword("FLIP_PARTICLES_TEXTURE");
- }
- #endif
- #if UNITY_ANDROID && !UNITY_EDITOR
- if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan && !EnableDownscale)
- {
- if (!EnableDownscale)
- {
- CurrentMaterial.DisableKeyword("FLIP_BACKGROUND_TEXTURE");
- CurrentMaterial.EnableKeyword("FLIP_NATIVE_TEXTURES");
- }
- else
- {
- CurrentMaterial.DisableKeyword("FLIP_NATIVE_TEXTURES");
- CurrentMaterial.EnableKeyword("FLIP_BACKGROUND_TEXTURE");
- }
- }
- #endif
- if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3)
- {
- CurrentMaterial.EnableKeyword("FLIP_PARTICLES_TEXTURE");
- }
- CurrentMaterial.SetTexture("Background", GetBackgroundToBind(cam));
- CurrentMaterial.SetTexture("FluidColor", Color0);
- if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
- {
- #if UNITY_PIPELINE_HDRP
- CurrentMaterial.SetTexture("ReflectionProbe", ReflectionProbeHDRP.texture);
- CurrentMaterial.SetVector("ReflectionProbe_HDR", new Vector4(0.01f, 1.0f));
- CurrentMaterial.SetVector("ReflectionProbe_BoxMax", ReflectionProbeHDRP.bounds.max);
- CurrentMaterial.SetVector("ReflectionProbe_BoxMin", ReflectionProbeHDRP.bounds.min);
- CurrentMaterial.SetVector("ReflectionProbe_ProbePosition", ReflectionProbeHDRP.transform.position);
- CurrentMaterial.EnableKeyword("HDRP");
- #endif
- }
- }
- Material usedSDFRenderMaterial = VisualizeSceneSDF ? MaterialParameters.SDFRenderMaterial : null;
- isDirty = camRes.SDFRenderMaterial.SetMaterial(usedSDFRenderMaterial) || isDirty;
- if (VisualizeSceneSDF)
- {
- Material CurrentSDFRenderMaterial = camRes.SDFRenderMaterial.CurrentMaterial;
- CurrentSDFRenderMaterial.SetTexture("SDFRender", Color0);
- if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
- {
- #if UNITY_PIPELINE_HDRP
- CurrentSDFRenderMaterial.SetVector("LightColor", CustomLightHDRP.color *
- Mathf.Log(CustomLightHDRP.intensity) / 8.0f);
- CurrentSDFRenderMaterial.SetVector("LightDirection",
- CustomLightHDRP.transform.rotation * new Vector3(0, 0, -1));
- CurrentSDFRenderMaterial.EnableKeyword("HDRP");
- #endif
- }
- }
- return isDirty;
- }
- internal Vector2Int ApplyDownscaleFactor(Vector2Int val)
- {
- if (!EnableDownscale)
- return val;
- return new Vector2Int((int)(val.x * DownscaleFactor), (int)(val.y * DownscaleFactor));
- }
- private Vector2Int ApplyRenderPipelineRenderScale(Vector2Int val, float renderPipelineRenderScale)
- {
- return new Vector2Int((int)(val.x * renderPipelineRenderScale), (int)(val.y * renderPipelineRenderScale));
- }
- private bool CreateTexture(ref RenderTexture texture, Vector2Int resolution, FilterMode filterMode, int depth,
- RenderTextureFormat format, bool enableRandomWrite = false)
- {
- if (texture == null || texture.width != resolution.x || texture.height != resolution.y)
- {
- ZibraLiquidGPUGarbageCollector.SafeRelease(texture);
- texture = null;
- texture = new RenderTexture(resolution.x, resolution.y, depth, format);
- texture.enableRandomWrite = enableRandomWrite;
- texture.filterMode = filterMode;
- texture.Create();
- return true;
- }
- return false;
- }
- private bool CreateRenderBuffer(ref ComputeBuffer buffer, Vector2Int resolution)
- {
- if (buffer == null || buffer.count != resolution.x * resolution.y)
- {
- ZibraLiquidGPUGarbageCollector.SafeRelease(buffer);
- buffer = new ComputeBuffer(resolution.x * resolution.y * 3, sizeof(uint));
- return true;
- }
- return false;
- }
- // Returns resolution that is enough for all cameras
- private Vector2Int GetRequiredTextureResolution()
- {
- if (CamRenderResolutions.Count == 0)
- Debug.Log("camRenderResolutions dictionary was empty when GetRequiredTextureResolution was called.");
- Vector2Int result = new Vector2Int(0, 0);
- foreach (var item in CamRenderResolutions)
- {
- result = Vector2Int.Max(result, item.Value);
- }
- return result;
- }
- internal bool IsBackgroundCopyNeeded(Camera cam)
- {
- return !EnableDownscale || (cam.activeTexture == null);
- }
- private RenderTexture GetBackgroundToBind(Camera cam)
- {
- if (!IsBackgroundCopyNeeded(cam))
- return cam.activeTexture;
- return CameraResourcesMap[cam].Background;
- }
- /// <summary>
- /// Removes disabled/inactive cameras from cameraResources
- /// </summary>
- private void UpdateCameraList()
- {
- List<Camera> toRemove = new List<Camera>();
- foreach (var camResource in CameraResourcesMap)
- {
- if (camResource.Key == null ||
- (!camResource.Key.isActiveAndEnabled && camResource.Key.cameraType != CameraType.SceneView))
- {
- toRemove.Add(camResource.Key);
- continue;
- }
- }
- foreach (var cam in toRemove)
- {
- if (CameraResourcesMap[cam].Background)
- {
- CameraResourcesMap[cam].Background.Release();
- CameraResourcesMap[cam].Background = null;
- }
- CameraResourcesMap.Remove(cam);
- }
- }
- private void UpdateCameraResolution(Camera cam, float renderPipelineRenderScale)
- {
- Vector2Int cameraResolution = new Vector2Int(cam.pixelWidth, cam.pixelHeight);
- cameraResolution = ApplyRenderPipelineRenderScale(cameraResolution, renderPipelineRenderScale);
- CamNativeResolutions[cam] = cameraResolution;
- Vector2Int cameraResolutionDownscaled = ApplyDownscaleFactor(cameraResolution);
- CamRenderResolutions[cam] = cameraResolutionDownscaled;
- }
- /// <summary>
- /// Update Native textures for a given camera
- /// </summary>
- private bool UpdateNativeTextures(Camera cam, float renderPipelineRenderScale)
- {
- UpdateCameraList();
- Vector2Int cameraResolution = new Vector2Int(cam.pixelWidth, cam.pixelHeight);
- cameraResolution = ApplyRenderPipelineRenderScale(cameraResolution, renderPipelineRenderScale);
- Vector2Int textureResolution = GetRequiredTextureResolution();
- int pixelCount = textureResolution.x * textureResolution.y;
- if (!Cameras.Contains(cam))
- {
- Cameras.Add(cam);
- }
- int CameraID = Cameras.IndexOf(cam);
- bool isGlobalTexturesDirty = false;
- bool isCameraDirty = CameraResourcesMap[cam].IsDirty;
- FilterMode defaultFilter = EnableDownscale ? FilterMode.Bilinear : FilterMode.Point;
- if (IsBackgroundCopyNeeded(cam))
- {
- if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
- {
- #if UNITY_PIPELINE_HDRP
- isCameraDirty = CreateTexture(ref CameraResourcesMap[cam].Background, cameraResolution,
- FilterMode.Point, 0, RenderTextureFormat.ARGBHalf) ||
- isCameraDirty;
- #endif
- }
- else
- {
- var format =
- SystemInfo.IsFormatSupported(GraphicsFormat.B10G11R11_UFloatPack32, FormatUsage.LoadStore)
- ? RenderTextureFormat.RGB111110Float
- : RenderTextureFormat.ARGB32; // 8 bits per component
- isCameraDirty = CreateTexture(ref CameraResourcesMap[cam].Background, cameraResolution,
- FilterMode.Point, 0, format) ||
- isCameraDirty;
- }
- }
- else
- {
- if (CameraResourcesMap[cam].Background != null)
- {
- isCameraDirty = true;
- CameraResourcesMap[cam].Background.Release();
- CameraResourcesMap[cam].Background = null;
- }
- }
- isGlobalTexturesDirty = CreateTexture(ref DepthTexture, cameraResolution, defaultFilter, 32,
- RenderTextureFormat.RFloat, true) ||
- isGlobalTexturesDirty;
- isGlobalTexturesDirty =
- CreateTexture(ref Depth, textureResolution, defaultFilter, 32, RenderTextureFormat.Depth) ||
- isGlobalTexturesDirty;
- isGlobalTexturesDirty = CreateTexture(ref Color0, textureResolution, FilterMode.Point, 0,
- RenderTextureFormat.ARGBFloat, true) ||
- isGlobalTexturesDirty;
- isGlobalTexturesDirty = CreateTexture(ref Color1, textureResolution, FilterMode.Point, 0,
- RenderTextureFormat.ARGBFloat, true) ||
- isGlobalTexturesDirty;
- isGlobalTexturesDirty = CreateTexture(ref Color2, textureResolution, FilterMode.Point, 0,
- RenderTextureFormat.ARGBFloat, true) ||
- isGlobalTexturesDirty;
- isGlobalTexturesDirty = CreateTexture(ref UpscaleColor, textureResolution, FilterMode.Point, 0,
- RenderTextureFormat.ARGBHalf, false) ||
- isGlobalTexturesDirty;
- isGlobalTexturesDirty = CreateTexture(ref UpscaleDepth, textureResolution, FilterMode.Point, 32,
- RenderTextureFormat.Depth, false) ||
- isGlobalTexturesDirty;
- isGlobalTexturesDirty = CreateTexture(ref ParticlesRT, textureResolution, FilterMode.Point, 0,
- RenderTextureFormat.ARGBFloat, true) ||
- isGlobalTexturesDirty;
- if (isGlobalTexturesDirty || isCameraDirty)
- {
- if (isGlobalTexturesDirty)
- {
- foreach (var camera in CameraResourcesMap)
- {
- camera.Value.IsDirty = true;
- }
- CurrentTextureResolution = textureResolution;
- }
- CameraResourcesMap[cam].IsDirty = false;
- var registerRenderResourcesBridgeParams = new RegisterRenderResourcesBridgeParams();
- registerRenderResourcesBridgeParams.Depth = MakeTextureNativeBridge(Depth);
- registerRenderResourcesBridgeParams.Color0 = MakeTextureNativeBridge(Color0);
- registerRenderResourcesBridgeParams.Color1 = MakeTextureNativeBridge(Color1);
- registerRenderResourcesBridgeParams.Color2 = MakeTextureNativeBridge(Color2);
- registerRenderResourcesBridgeParams.SceneDepth = MakeTextureNativeBridge(DepthTexture);
- registerRenderResourcesBridgeParams.ParticlesRT = MakeTextureNativeBridge(ParticlesRT);
- IntPtr nativeRegisterRenderResourcesBridgeParams =
- Marshal.AllocHGlobal(Marshal.SizeOf(registerRenderResourcesBridgeParams));
- Marshal.StructureToPtr(registerRenderResourcesBridgeParams, nativeRegisterRenderResourcesBridgeParams,
- true);
- SolverCommandBuffer.Clear();
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.RegisterRenderResources,
- nativeRegisterRenderResourcesBridgeParams);
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.InitializeGraphicsPipeline);
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- ToFreeOnExit.Add(nativeRegisterRenderResourcesBridgeParams);
- }
- return isGlobalTexturesDirty || isCameraDirty;
- }
- private int IntDivCeil(int a, int b)
- {
- return (a + b - 1) / b;
- }
- /// <summary>
- /// Render the liquid from the native plugin
- /// </summary>
- /// <param name="cmdBuffer">Command Buffer to add the rendering commands to</param>
- internal void RenderLiquidNative(CommandBuffer cmdBuffer, Camera cam, Rect? viewport = null)
- {
- var renderEffectParticles = MaterialParametersInternal.EnableFoam && MaxFoamParticles > 0;
- ForceCloseCommandEncoder(cmdBuffer);
- if (renderEffectParticles)
- {
- cmdBuffer.SetComputeVectorParam(MaterialParameters.RendererCompute, "Resolution",
- new Vector2(cam.pixelWidth, cam.pixelHeight));
- cmdBuffer.SetComputeTextureParam(MaterialParameters.RendererCompute, CopyDepthID, "_DepthOUT", DepthTexture);
- cmdBuffer.DispatchCompute(MaterialParameters.RendererCompute, CopyDepthID, IntDivCeil(cam.pixelWidth, DEPTH_COPY_WORKGROUP),
- IntDivCeil(cam.pixelHeight, DEPTH_COPY_WORKGROUP), 1);
- }
- LiquidBridge.SubmitInstanceEvent(cmdBuffer, CurrentInstanceID, LiquidBridge.EventID.SetCameraParams,
- CamNativeParams[cam]);
- LiquidBridge.SubmitInstanceEvent(cmdBuffer, CurrentInstanceID,
- LiquidBridge.EventID.UpdateMeshRenderGlobalParameters,
- CamMeshRenderParams[cam]);
- if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan)
- {
- cmdBuffer.SetRenderTarget(Color0, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, Depth,
- RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
- cmdBuffer.ClearRenderTarget(true, true, Color.clear);
- }
- LiquidBridge.SubmitInstanceEvent(cmdBuffer, CurrentInstanceID, LiquidBridge.EventID.DrawLiquid);
- if (renderEffectParticles)
- {
- if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan)
- {
- cmdBuffer.SetRenderTarget(ParticlesRT);
- cmdBuffer.ClearRenderTarget(false, true, Color.clear);
- }
- LiquidBridge.SubmitInstanceEvent(cmdBuffer, CurrentInstanceID,
- LiquidBridge.EventID.DrawEffectParticles);
- }
- }
- internal void RenderLiquidMain(CommandBuffer cmdBuffer, Camera cam, Rect? viewport = null)
- {
- switch (ActiveRenderingMode)
- {
- case RenderingMode.MeshRender:
- RenderLiquidMesh(cmdBuffer, cam, viewport);
- break;
- #if !ZIBRA_EFFECTS_OTP_VERSION
- case RenderingMode.UnityRender:
- break;
- #endif
- default:
- Debug.LogError("Unknown Rendering mode");
- break;
- }
- }
- /// <summary>
- /// Upscale the liquid surface to currently bound render target
- /// Used for URP where we can't change render targets
- /// Used for URP where we can't change render targets
- /// </summary>
- internal void UpscaleLiquidDirect(CommandBuffer cmdBuffer, Camera cam,
- RenderTargetIdentifier? sourceColorTexture = null,
- RenderTargetIdentifier? sourceDepthTexture = null, Rect? viewport = null)
- {
- Material CurrentUpscaleMaterial = CameraResourcesMap[cam].UpscaleMaterial.CurrentMaterial;
- Vector2Int cameraNativeResolution = CamNativeResolutions[cam];
- cmdBuffer.SetViewport(new Rect(0, 0, cameraNativeResolution.x, cameraNativeResolution.y));
- if (sourceColorTexture == null)
- {
- cmdBuffer.SetGlobalTexture("ShadedLiquid", UpscaleColor);
- cmdBuffer.SetGlobalTexture("ShadedLiquidDepth", UpscaleDepth);
- }
- else
- {
- cmdBuffer.SetGlobalTexture("ShadedLiquid", sourceColorTexture.Value);
- cmdBuffer.SetGlobalTexture("ShadedLiquidDepth", sourceDepthTexture.Value);
- }
- cmdBuffer.DrawProcedural(transform.localToWorldMatrix, CurrentUpscaleMaterial, 0, MeshTopology.Triangles,
- 6);
- }
- /// <summary>
- /// Render the liquid surface
- /// Camera's targetTexture must be copied to cameraResources[cam].background
- /// using corresponding Render Pipeline before calling this method
- /// </summary>
- /// <param name="cmdBuffer">Command Buffer to add the rendering commands to</param>
- internal void RenderFluid(CommandBuffer cmdBuffer, Camera cam, RenderTargetIdentifier? renderTargetParam = null,
- RenderTargetIdentifier? depthTargetParam = null, Rect? viewport = null)
- {
- RenderTargetIdentifier renderTarget =
- renderTargetParam ?? new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget);
- RenderTargetIdentifier depthTarget =
- depthTargetParam ?? new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget);
- // Render fluid to temporary RenderTexture if downscale enabled
- // Otherwise render straight to final RenderTexture
- if (EnableDownscale)
- {
- cmdBuffer.SetRenderTarget(UpscaleColor, UpscaleDepth);
- cmdBuffer.ClearRenderTarget(true, true, Color.clear);
- }
- else
- {
- cmdBuffer.SetRenderTarget(renderTarget, depthTarget);
- }
- RenderLiquidMain(cmdBuffer, cam, viewport);
- if (VisualizeSceneSDF)
- {
- LiquidBridge.SubmitInstanceEvent(cmdBuffer, CurrentInstanceID, LiquidBridge.EventID.RenderSDF);
- if (EnableDownscale)
- {
- cmdBuffer.SetRenderTarget(UpscaleColor, UpscaleDepth);
- }
- else
- {
- cmdBuffer.SetRenderTarget(renderTarget, depthTarget);
- }
- RenderSDFVisualization(cmdBuffer, cam, viewport);
- }
- // If downscale enabled then we need to blend it on top of final RenderTexture
- if (EnableDownscale)
- {
- cmdBuffer.SetRenderTarget(renderTarget, depthTarget);
- UpscaleLiquidDirect(cmdBuffer, cam, null, null, viewport);
- }
- }
- /// <summary>
- /// Render the liquid surface
- /// Camera's targetTexture must be copied to cameraResources[cam].background
- /// using corresponding Render Pipeline before calling this method
- /// </summary>
- /// <param name="cmdBuffer">Command Buffer to add the rendering commands to</param>
- private void RenderLiquidMesh(CommandBuffer cmdBuffer, Camera cam, Rect? viewport = null)
- {
- Vector2Int cameraRenderResolution = CamRenderResolutions[cam];
- Material CurrentMaterial = CameraResourcesMap[cam].LiquidMaterial.CurrentMaterial;
- // Render fluid to temporary RenderTexture if downscale enabled
- // Otherwise render straight to final RenderTexture
- if (EnableDownscale)
- {
- cmdBuffer.SetViewport(new Rect(0, 0, cameraRenderResolution.x, cameraRenderResolution.y));
- }
- else
- {
- if (viewport != null)
- {
- cmdBuffer.SetViewport(viewport.Value);
- }
- }
- cmdBuffer.SetGlobalTexture("Background", GetBackgroundToBind(cam));
- if (RenderPipelineDetector.GetRenderPipelineType() == RenderPipelineDetector.RenderPipeline.HDRP)
- {
- #if UNITY_PIPELINE_HDRP
- cmdBuffer.SetGlobalTexture("ReflectionProbe", ReflectionProbeHDRP.texture);
- cmdBuffer.SetGlobalVector("ReflectionProbe_HDR", new Vector4(0.01f, 1.0f));
- cmdBuffer.SetGlobalVector("ReflectionProbe_BoxMax", ReflectionProbeHDRP.bounds.max);
- cmdBuffer.SetGlobalVector("ReflectionProbe_BoxMin", ReflectionProbeHDRP.bounds.min);
- cmdBuffer.SetGlobalVector("ReflectionProbe_ProbePosition", ReflectionProbeHDRP.transform.position);
- CurrentMaterial.EnableKeyword("HDRP");
- #endif
- }
- cmdBuffer.DrawProcedural(transform.localToWorldMatrix, CurrentMaterial, 0, MeshTopology.Triangles, 6);
- }
- internal void RenderSDFVisualization(CommandBuffer cmdBuffer, Camera cam, Rect? viewport = null)
- {
- Vector2Int cameraRenderResolution = CamRenderResolutions[cam];
- Material CurrentMaterial = CameraResourcesMap[cam].SDFRenderMaterial.CurrentMaterial;
- // Render fluid to temporary RenderTexture if downscale enabled
- // Otherwise render straight to final RenderTexture
- if (EnableDownscale)
- {
- cmdBuffer.SetViewport(new Rect(0, 0, cameraRenderResolution.x, cameraRenderResolution.y));
- }
- else
- {
- if (viewport != null)
- {
- cmdBuffer.SetViewport(viewport.Value);
- }
- }
- cmdBuffer.DrawProcedural(transform.localToWorldMatrix, CurrentMaterial, 0, MeshTopology.Triangles, 6);
- }
- /// <summary>
- /// Update the camera parameters for the particle renderer
- /// </summary>
- private void UpdateCamera(Camera cam)
- {
- Vector2Int resolution = CamRenderResolutions[cam];
- Material CurrentMaterial = CameraResourcesMap[cam].LiquidMaterial.CurrentMaterial;
- Material CurrentUpscaleMaterial = CameraResourcesMap[cam].UpscaleMaterial.CurrentMaterial;
- Material CurrentSDFRenderMaterial = CameraResourcesMap[cam].SDFRenderMaterial.CurrentMaterial;
- Matrix4x4 Projection = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true);
- Matrix4x4 ProjectionInverse = Projection.inverse;
- Matrix4x4 View = cam.worldToCameraMatrix;
- Matrix4x4 ViewProjection = Projection * View;
- Matrix4x4 ViewProjectionInverse = ViewProjection.inverse;
- CurrentMaterial.SetVector("Resolution", CameraRenderParams.CameraResolution);
- CameraRenderParams.View = cam.worldToCameraMatrix;
- CameraRenderParams.Projection = Projection;
- CameraRenderParams.ProjectionInverse = ProjectionInverse;
- CameraRenderParams.ViewProjection = ViewProjection;
- CameraRenderParams.ViewProjectionInverse = ViewProjectionInverse;
- CameraRenderParams.EyeRayCameraCoeficients = CalculateEyeRayCameraCoeficients(cam);
- CameraRenderParams.WorldSpaceCameraPos = cam.transform.position;
- CameraRenderParams.CameraResolution = new Vector2(resolution.x, resolution.y);
- CameraRenderParams.CameraID = Cameras.IndexOf(cam);
- CameraRenderParams.CameraDownscaleFactor = EnableDownscale ? DownscaleFactor : 1f;
- { // Same as Unity's built-in _ZBufferParams
- float y = cam.farClipPlane / cam.nearClipPlane;
- float x = 1 - y;
- CameraRenderParams.ZBufferParams = new Vector4(x, y, x / cam.farClipPlane, y / cam.farClipPlane);
- }
- MeshRenderGlobalParamsContainer.LiquidIOR = MaterialParameters.IndexOfRefraction;
- MeshRenderGlobalParamsContainer.RayMarchIsoSurface = AdvancedRenderParameters.RayMarchIsoSurface;
- MeshRenderGlobalParamsContainer.DisableRaymarch = AdvancedRenderParameters.DisableRaymarch ? 1 : 0;
- MeshRenderGlobalParamsContainer.UnderwaterRender = AdvancedRenderParameters.UnderwaterRender ? 1 : 0;
- MeshRenderGlobalParamsContainer.RayMarchMaxSteps = AdvancedRenderParameters.RayMarchMaxSteps;
- MeshRenderGlobalParamsContainer.RayMarchStepSize = AdvancedRenderParameters.RayMarchStepSize;
- MeshRenderGlobalParamsContainer.RayMarchStepFactor = AdvancedRenderParameters.RayMarchStepFactor;
- Vector2 renderingResolution = resolution;
- Vector2 rayMarchResolution = renderingResolution * AdvancedRenderParameters.RayMarchingResolutionDownscale;
- MeshRenderGlobalParamsContainer.RayMarchResolution =
- new Vector2Int((int)rayMarchResolution.x, (int)rayMarchResolution.y);
- MeshRenderGlobalParamsContainer.FoamingIntensity = MaterialParameters.FoamIntensity;
- MeshRenderGlobalParamsContainer.FoamingDecay = MaterialParameters.FoamDecay;
- MeshRenderGlobalParamsContainer.FoamingDecaySmoothness = MaterialParameters.FoamDecaySmoothness;
- MeshRenderGlobalParamsContainer.FoamingOcclusionDistance = MaterialParameters.FoamingOcclusionDistance;
- MeshRenderGlobalParamsContainer.FoamingThreshold = MaterialParameters.FoamingThreshold;
- MeshRenderGlobalParamsContainer.FoamBrightness = MaterialParameters.FoamBrightness;
- MeshRenderGlobalParamsContainer.FoamMotionBlur = MaterialParameters.FoamMotionBlur;
- MeshRenderGlobalParamsContainer.FoamSize = MaterialParameters.FoamSize;
- MeshRenderGlobalParamsContainer.FoamDiffusion = MaterialParameters.FoamDiffusion;
- MeshRenderGlobalParamsContainer.FoamSpawning = MaterialParameters.FoamSpawning;
- MeshRenderGlobalParamsContainer.Absorption = new Vector4(
- MaterialParameters.Material1.ScatteringAmount, MaterialParameters.Material2.ScatteringAmount,
- MaterialParameters.Material3.ScatteringAmount, MaterialParameters.ScatteringAmount);
- Marshal.StructureToPtr(MeshRenderGlobalParamsContainer, CamMeshRenderParams[cam], true);
- Vector2 textureScale = new Vector2(resolution.x, resolution.y) / GetRequiredTextureResolution();
- // update the data at the pointer
- Marshal.StructureToPtr(CameraRenderParams, CamNativeParams[cam], true);
- if (ActiveRenderingMode == RenderingMode.MeshRender)
- {
- CurrentMaterial.SetMatrix("ProjectionInverse", CameraRenderParams.ProjectionInverse);
- CurrentMaterial.SetMatrix("ViewProjectionInverse", CameraRenderParams.ViewProjectionInverse);
- CurrentMaterial.SetMatrix("EyeRayCameraCoeficients", CameraRenderParams.EyeRayCameraCoeficients);
- CurrentMaterial.SetVector("TextureScale", textureScale);
- if (AdvancedRenderParameters.UnderwaterRender)
- {
- CurrentMaterial.EnableKeyword("UNDERWATER_RENDER");
- }
- else
- {
- CurrentMaterial.DisableKeyword("UNDERWATER_RENDER");
- }
- if (AdvancedRenderParameters.DisableRaymarch)
- {
- CurrentMaterial.EnableKeyword("RAYMARCH_DISABLED");
- }
- else
- {
- CurrentMaterial.DisableKeyword("RAYMARCH_DISABLED");
- CurrentMaterial.SetTexture("RayMarchData", Color1);
- CurrentMaterial.SetTexture("MaterialData", Color2);
- }
- #if !UNITY_ANDROID
- if (MaxFoamParticles > 0 && MaterialParameters.EnableFoam)
- {
- CurrentMaterial.DisableKeyword("FOAM_DISABLED");
- CurrentMaterial.SetTexture("ParticlesTex", ParticlesRT);
- }
- else
- #endif
- {
- CurrentMaterial.EnableKeyword("FOAM_DISABLED");
- }
- }
- if (EnableDownscale)
- {
- CurrentUpscaleMaterial.SetVector("TextureScale", textureScale);
- }
- if (VisualizeSceneSDF)
- {
- CurrentSDFRenderMaterial.SetVector("TextureScale", textureScale);
- CurrentSDFRenderMaterial.SetMatrix("EyeRayCameraCoeficients",
- CameraRenderParams.EyeRayCameraCoeficients);
- }
- }
- /// <summary>
- /// Update render parameters for a given camera
- /// </summary>
- private void InitializeNativeCameraParams(Camera cam)
- {
- if (!CamNativeParams.ContainsKey(cam))
- {
- // allocate memory for camera parameters
- CamNativeParams[cam] = Marshal.AllocHGlobal(Marshal.SizeOf(CameraRenderParams));
- }
- if (!CamMeshRenderParams.ContainsKey(cam))
- {
- // allocate memory for mesh render parameters
- CamMeshRenderParams[cam] = Marshal.AllocHGlobal(Marshal.SizeOf(MeshRenderGlobalParamsContainer));
- }
- }
- private void UpdateNativeRenderParams()
- {
- #if ZIBRA_EFFECTS_DEBUG
- RenderParamsContainer.NeuralSamplingDistance = MaterialParameters.NeuralSamplingDistance;
- RenderParamsContainer.SDFDebug = MaterialParameters.SDFDebug;
- #endif
- RenderParamsContainer.RenderingMode = (int)ActiveRenderingMode;
- RenderParamsContainer.VertexOptimizationIterations = AdvancedRenderParameters.VertexOptimizationIterations;
- RenderParamsContainer.MeshOptimizationIterations = AdvancedRenderParameters.MeshOptimizationIterations;
- RenderParamsContainer.DualContourIsoValue = AdvancedRenderParameters.DualContourIsoSurfaceLevel;
- RenderParamsContainer.MeshOptimizationStep = AdvancedRenderParameters.MeshOptimizationStep;
- int maxVertexCount = GridNodeCount;
- int maxTriangleCount =
- (int)(maxVertexCount * AdvancedRenderParameters.MaxLiquidMeshSize / 3.0f + ADDITIONAL_VERTICES);
- RenderParamsContainer.MaxVertexBufferSize = maxTriangleCount * 6;
- RenderParamsContainer.MaxIndexBufferSize = maxTriangleCount * 3;
- RenderParamsContainer.RenderParamsContainerPos = transform.position;
- GCHandle gcparamBuffer = GCHandle.Alloc(RenderParamsContainer, GCHandleType.Pinned);
- SolverCommandBuffer.Clear();
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.SetRenderParameters,
- gcparamBuffer.AddrOfPinnedObject());
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- gcparamBuffer.Free();
- }
- private void ClearCameraCommandBuffers()
- {
- // clear all rendering command buffers if not rendering
- foreach (KeyValuePair<Camera, CommandBuffer> entry in CameraCBs)
- {
- if (entry.Key != null)
- {
- entry.Key.RemoveCommandBuffer(ActiveInjectionPoint, entry.Value);
- }
- }
- CameraCBs.Clear();
- Cameras.Clear();
- }
- /// <summary>
- /// Rendering callback which is called by every camera in the scene
- /// </summary>
- internal void RenderCallBack(Camera cam, float renderPipelineRenderScale = 1.0f)
- {
- if (cam.cameraType == CameraType.Preview || cam.cameraType == CameraType.Reflection ||
- cam.cameraType == CameraType.VR)
- {
- ClearCameraCommandBuffers();
- return;
- }
- if (!cam.isActiveAndEnabled && cam.cameraType != CameraType.SceneView)
- {
- return;
- }
- UpdateCameraResolution(cam, renderPipelineRenderScale);
- // Need at least 2 simulation frames to start rendering
- if (!IsRenderingEnabled())
- {
- return;
- }
- if (!CameraResourcesMap.ContainsKey(cam))
- {
- CameraResourcesMap[cam] = new CameraResources();
- }
- // Re-add command buffers to cameras with new injection points
- if (CurrentInjectionPoint != ActiveInjectionPoint)
- {
- foreach (KeyValuePair<Camera, CommandBuffer> entry in CameraCBs)
- {
- entry.Key.RemoveCommandBuffer(ActiveInjectionPoint, entry.Value);
- entry.Key.AddCommandBuffer(CurrentInjectionPoint, entry.Value);
- }
- ActiveInjectionPoint = CurrentInjectionPoint;
- }
- bool visibleInCamera =
- (RenderPipelineDetector.GetRenderPipelineType() != RenderPipelineDetector.RenderPipeline.BuiltInRP) ||
- ((cam.cullingMask & (1 << this.gameObject.layer)) != 0);
- if (!visibleInCamera || MaterialParameters.FluidMeshMaterial == null ||
- (EnableDownscale && MaterialParameters.UpscaleMaterial == null) ||
- (VisualizeSceneSDF && MaterialParameters.SDFRenderMaterial == null))
- {
- if (CameraCBs.ContainsKey(cam))
- {
- cam.RemoveCommandBuffer(ActiveInjectionPoint, CameraCBs[cam]);
- CameraCBs[cam].Clear();
- CameraCBs.Remove(cam);
- }
- return;
- }
- bool isDirty = SetMaterialParams(cam);
- isDirty = UpdateNativeTextures(cam, renderPipelineRenderScale) || isDirty;
- isDirty = !CameraCBs.ContainsKey(cam) || isDirty;
- InitializeNativeCameraParams(cam);
- UpdateCamera(cam);
- if (RenderPipelineDetector.GetRenderPipelineType() != RenderPipelineDetector.RenderPipeline.BuiltInRP)
- {
- #if UNITY_PIPELINE_HDRP || UNITY_PIPELINE_URP
- // upload camera parameters
- SolverCommandBuffer.Clear();
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.SetCameraParameters, CamNativeParams[cam]);
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- #endif
- }
- else
- {
- if (!CameraCBs.ContainsKey(cam) || isDirty)
- {
- CommandBuffer renderCommandBuffer;
- if (isDirty && CameraCBs.ContainsKey(cam))
- {
- renderCommandBuffer = CameraCBs[cam];
- renderCommandBuffer.Clear();
- }
- else
- {
- // Create render command buffer
- renderCommandBuffer = new CommandBuffer { name = "ZibraLiquid.Render" };
- // add command buffer to camera
- cam.AddCommandBuffer(ActiveInjectionPoint, renderCommandBuffer);
- // add camera to the list
- CameraCBs[cam] = renderCommandBuffer;
- }
- // enable depth texture
- cam.depthTextureMode = DepthTextureMode.Depth;
- // update native camera parameters
- if (IsBackgroundCopyNeeded(cam))
- {
- renderCommandBuffer.Blit(BuiltinRenderTextureType.CurrentActive,
- CameraResourcesMap[cam].Background);
- }
- if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan)
- {
- renderCommandBuffer.SetRenderTarget(
- Color0, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, Depth,
- RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
- renderCommandBuffer.ClearRenderTarget(true, true, Color.clear);
- }
- RenderLiquidNative(renderCommandBuffer, cam);
- RenderFluid(renderCommandBuffer, cam);
- }
- }
- }
- private ParticleSpeciesParameters GetSpeciesParametersDefault()
- {
- ParticleSpeciesParameters speciesParameters = new ParticleSpeciesParameters();
- speciesParameters.Gravity = SolverParameters.Gravity / 100.0f;
- speciesParameters.AffineAmmount = 4.0f * (1.0f - SolverParameters.Viscosity);
- speciesParameters.LiquidStiffness = SolverParameters.FluidStiffness;
- speciesParameters.RestDensity = SolverParameters.ParticleDensity;
- speciesParameters.SurfaceTension = SolverParameters.SurfaceTension;
- speciesParameters.AffineDivergenceDecay = 1.0f;
- speciesParameters.Material =
- new Vector3(SolverParameters.Material1, SolverParameters.Material2, SolverParameters.Material3);
- speciesParameters.VelocityLimit = SolverParameters.MaximumVelocity;
- return speciesParameters;
- }
- private ParticleSpeciesParameters GetSpeciesParameters(
- ZibraLiquidSolverParameters.SolverSettings thisSolverParameters)
- {
- ParticleSpeciesParameters speciesParameters = new ParticleSpeciesParameters();
- speciesParameters.Gravity = thisSolverParameters.Gravity / 100.0f;
- speciesParameters.AffineAmmount = 4.0f * (1.0f - thisSolverParameters.Viscosity);
- speciesParameters.LiquidStiffness = thisSolverParameters.FluidStiffness;
- speciesParameters.RestDensity = thisSolverParameters.ParticleDensity;
- speciesParameters.SurfaceTension = thisSolverParameters.SurfaceTension;
- speciesParameters.AffineDivergenceDecay = 1.0f;
- speciesParameters.Material = new Vector3(thisSolverParameters.Material1, thisSolverParameters.Material2,
- thisSolverParameters.Material3);
- speciesParameters.VelocityLimit = thisSolverParameters.MaximumVelocity;
- return speciesParameters;
- }
- private void SetInteropBuffer<T>(IntPtr NativeBuffer, List<T> list)
- {
- long LongPtr = NativeBuffer.ToInt64();
- for (int I = 0; I < list.Count; I++)
- {
- IntPtr Ptr = new IntPtr(LongPtr);
- Marshal.StructureToPtr(list[I], Ptr, true);
- LongPtr += Marshal.SizeOf(typeof(T));
- }
- }
- private void UpdateInteropBuffers()
- {
- Marshal.StructureToPtr(LiquidParameters, NativeFluidData, true);
- if (ManipulatorManager.Elements > 0)
- {
- SetInteropBuffer(NativeManipData, ManipulatorManager.ManipulatorParams);
- }
- if (ManipulatorManager.SDFObjectList.Count > 0)
- {
- SetInteropBuffer(NativeSDFData, ManipulatorManager.SDFObjectList);
- }
- List<ParticleSpeciesParameters> SpeciesList = new List<ParticleSpeciesParameters>();
- SpeciesList.Add(GetSpeciesParametersDefault());
- foreach (var species in SolverParameters.AdditionalParticleSpecies)
- {
- SpeciesList.Add(GetSpeciesParameters(species));
- }
- SetInteropBuffer(NativeSolverData, SpeciesList);
- }
- private void UpdateSolverParameters()
- {
- // Update fluid parameters
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.UpdateLiquidParameters, NativeFluidData);
- if (ManipulatorManager.Elements > 0)
- {
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.UpdateManipulatorParameters, NativeManipData);
- }
- if (ManipulatorManager.SDFObjectList.Count > 0)
- {
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.UpdateSDFObjects, NativeSDFData);
- }
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.UpdateSolverParameters, NativeSolverData);
- }
- private void RenderCallBackWrapper(Camera cam)
- {
- try
- {
- RenderCallBack(cam);
- }
- catch (Exception e)
- {
- Debug.LogException(e);
- }
- }
- private void StepPhysics()
- {
- SolverCommandBuffer.Clear();
- ForceCloseCommandEncoder(SolverCommandBuffer);
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.ClearSDFAndID);
- SetFluidParameters();
- ManipulatorManager.UpdateDynamic(SolverCommandBuffer, this, Timestep);
- UpdateInteropBuffers();
- UpdateSolverParameters();
- // execute simulation
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID, LiquidBridge.EventID.StepPhysics);
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- // update internal time
- SimulationInternalTime += Timestep;
- SimulationInternalFrame++;
- }
- private void UpdateManipulatorStatistics()
- {
- /// ManipulatorStatistics GPUReadback
- if (!IsSimulationEnabled() || ManipulatorManager.Elements == 0)
- {
- return;
- }
- UInt32 size = (UInt32)ManipulatorManager.Elements * STATISTICS_PER_MANIPULATOR;
- IntPtr readbackData = LiquidBridge.ZibraLiquid_GPUReadbackGetData(CurrentInstanceID, size * sizeof(Int32));
- if (readbackData != IntPtr.Zero)
- {
- Int32[] Stats = new Int32[size];
- Marshal.Copy(readbackData, Stats, 0, (Int32)size);
- ManipulatorManager.UpdateStatistics(this, Stats, Manipulators, SolverParameters, SDFColliders);
- }
- }
- private void SetFluidParameters()
- {
- SolverParameters.ValidateParameters();
- LiquidParameters.GridSize = GridSize;
- LiquidParameters.ContainerScale = ContainerSize;
- LiquidParameters.NodeCount = GridNodeCount;
- LiquidParameters.SimulationParamsContainerPos = transform.position;
- LiquidParameters.TimeStep = Timestep;
- LiquidParameters.SimulationFrame = SimulationInternalFrame;
- LiquidParameters.DensityBlurRadius = MaterialParameters.FluidSurfaceBlur;
- LiquidParameters.LiquidIsosurfaceThreshold = AdvancedRenderParameters.IsoSurfaceLevel;
- LiquidParameters.VertexOptimizationStep = AdvancedRenderParameters.VertexOptimizationStep;
- LiquidParameters.EnableContainerMovementFeedback = EnableContainerMovementFeedback ? 1 : 0;
- // ParticleTranslation is set by native plugin
- #if UNITY_ANDROID
- var FoamParticlesEnabled = 0;
- var MaxFoamParticles = 0;
- #else
- var FoamParticlesEnabled = MaterialParameters.EnableFoam ? 1 : 0;
- var MaxFoamParticles = this.MaxFoamParticles;
- #endif
- float MaxVelocityLimit = SolverParameters.MaximumVelocity;
- for (int i = 0; i < SolverParameters.AdditionalParticleSpecies.Count; i++)
- {
- MaxVelocityLimit =
- Mathf.Max(MaxVelocityLimit, SolverParameters.AdditionalParticleSpecies[i].MaximumVelocity);
- }
- LiquidParameters.GlobalVelocityLimit = MaxVelocityLimit;
- LiquidParameters.MinimumVelocity = SolverParameters.MinimumVelocity;
- // BlurNormalizationConstant set by native plugin
- LiquidParameters.MaxParticleCount = MaxNumParticles;
- LiquidParameters.VisualizeSDF = VisualizeSceneSDF ? 1 : 0;
- LiquidParameters.SimulationTime = SimulationInternalTime;
- LiquidParameters.FoamParticleLifetime = MaterialParameters.FoamParticleLifetime;
- LiquidParameters.MaxEffectParticleCount = MaxFoamParticles;
- LiquidParameters.FoamBuoyancy = SolverParameters.FoamBuoyancy;
- LiquidParameters.ParticleSpeciesCount = SolverParameters.AdditionalParticleSpecies.Count + 1;
- LiquidParameters.EnableFoam = FoamParticlesEnabled;
- }
- private void ClearRendering()
- {
- Camera.onPreRender -= RenderCallBackWrapper;
- ClearCameraCommandBuffers();
- // free allocated memory
- foreach (var data in CamNativeParams)
- {
- Marshal.FreeHGlobal(data.Value);
- }
- foreach (var resource in CameraResourcesMap)
- {
- if (resource.Value.Background != null)
- {
- resource.Value.Background.Release();
- resource.Value.Background = null;
- }
- }
- CameraResourcesMap.Clear();
- ZibraLiquidGPUGarbageCollector.SafeRelease(Color0);
- Color0 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(Color1);
- Color1 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(Color2);
- Color2 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(UpscaleColor);
- UpscaleColor = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(VertexIDGrid);
- VertexIDGrid = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(VertexBuffer0);
- VertexBuffer0 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(VertexBuffer1);
- VertexBuffer1 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(TransferDataBuffer);
- TransferDataBuffer = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(MeshRenderIndexBuffer);
- MeshRenderIndexBuffer = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(QuadBuffer);
- QuadBuffer = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(VertexProperties);
- VertexProperties = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(GridNormalTexture);
- GridNormalTexture = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(DensityTexture);
- DensityTexture = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(VelocityTexture);
- VelocityTexture = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(SDFGridTexture);
- SDFGridTexture = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(EmbeddingsTexture);
- EmbeddingsTexture = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(HeightmapTexture);
- HeightmapTexture = null;
- CamNativeParams.Clear();
- MaxFoamParticles = 0;
- }
- private void ClearSolver()
- {
- if (SolverCommandBuffer != null)
- {
- LiquidBridge.SubmitInstanceEvent(SolverCommandBuffer, CurrentInstanceID,
- LiquidBridge.EventID.ReleaseResources);
- Graphics.ExecuteCommandBuffer(SolverCommandBuffer);
- }
- if (SolverCommandBuffer != null)
- {
- SolverCommandBuffer.Release();
- SolverCommandBuffer = null;
- }
- ZibraLiquidGPUGarbageCollector.SafeRelease(PositionMass);
- PositionMass = null;
- if (Affine != null)
- {
- ZibraLiquidGPUGarbageCollector.SafeRelease(Affine[0]);
- Affine[0] = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(Affine[1]);
- Affine[1] = null;
- }
- ZibraLiquidGPUGarbageCollector.SafeRelease(GridData);
- GridData = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(IndexGrid);
- IndexGrid = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(NodeParticlePairs0);
- NodeParticlePairs0 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(NodeParticlePairs1);
- NodeParticlePairs1 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(EffectParticleData0);
- EffectParticleData0 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(EffectParticleData1);
- EffectParticleData1 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(RadixGroupData1);
- RadixGroupData1 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(RadixGroupData2);
- RadixGroupData2 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(RadixGroupData3);
- RadixGroupData3 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(PositionMassCopy);
- PositionMassCopy = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(GridNormal);
- GridNormal = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(GridBlur0);
- GridBlur0 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(GridBlur1);
- GridBlur1 = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(MassCopy);
- MassCopy = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(TmpSDFBuff);
- TmpSDFBuff = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(ParticleNumber);
- ParticleNumber = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(DynamicManipulatorData);
- DynamicManipulatorData = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(ParticleSpeciesData);
- ParticleSpeciesData = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(SDFObjectData);
- SDFObjectData = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(ManipulatorStatistics);
- ManipulatorStatistics = null;
- ZibraLiquidGPUGarbageCollector.SafeRelease(Counters);
- Counters = null;
- if (!Application.isEditor)
- {
- Destroy(LiquidMesh);
- }
- else
- {
- DestroyImmediate(LiquidMesh);
- }
- Marshal.FreeHGlobal(NativeManipData);
- NativeManipData = IntPtr.Zero;
- Marshal.FreeHGlobal(NativeFluidData);
- NativeFluidData = IntPtr.Zero;
- CurrentTextureResolution = new Vector2Int(0, 0);
- GridSize = new Vector3Int(0, 0, 0);
- CurrentParticleNumber = 0;
- GridNodeCount = 0;
- SimulationInternalFrame = 0;
- SimulationInternalTime = 0.0f;
- Timestep = 0.0f;
- CamRenderResolutions.Clear();
- CamNativeResolutions.Clear();
- // DO NOT USE AllFluids.Remove(this)
- // This will not result in equivalent code
- // ZibraLiquid::Equals is overriden and don't have correct implementation
- if (AllFluids != null)
- {
- for (int i = 0; i < AllFluids.Count; i++)
- {
- var fluid = AllFluids[i];
- if (ReferenceEquals(fluid, this))
- {
- AllFluids.RemoveAt(i);
- break;
- }
- }
- }
- }
- private void OnApplicationQuit()
- {
- // On quit we need to destroy liquid before destroying any colliders/manipulators
- OnDisable();
- }
- // dispose the objects
- private void OnDisable()
- {
- RemoveFromStatReporter();
- ReleaseSimulation();
- }
- private float ByteArrayToSingle(byte[] array, ref int startIndex)
- {
- float value = BitConverter.ToSingle(array, startIndex);
- startIndex += sizeof(float);
- return value;
- }
- private int ByteArrayToInt(byte[] array, ref int startIndex)
- {
- int value = BitConverter.ToInt32(array, startIndex);
- startIndex += sizeof(int);
- return value;
- }
- private BakedInitialState ConvertBytesToInitialState(byte[] data)
- {
- int startIndex = 0;
- int header = ByteArrayToInt(data, ref startIndex);
- if (!IsValidBakedLiquidHeader(header))
- {
- throw new Exception("Invalid baked liquid data.");
- }
- int particleCount = ByteArrayToInt(data, ref startIndex);
- if (particleCount > MaxNumParticles)
- {
- throw new Exception("Baked data have more particles than max particle count.");
- }
- BakedInitialState initialStateData = new BakedInitialState();
- initialStateData.ParticleCount = particleCount;
- initialStateData.Positions = new Vector4[particleCount];
- if (header == BAKED_LIQUID_PAID_HEADER_VALUE)
- {
- for (int i = 0; i < particleCount; i++)
- {
- for (int j = 0; j < 3; j++)
- {
- initialStateData.Positions[i][j] = ByteArrayToSingle(data, ref startIndex);
- }
- initialStateData.Positions[i].w = 0.0f;
- }
- }
- else if (header == BAKED_LIQUID_PRO_HEADER_VALUE)
- {
- for (int i = 0; i < particleCount; i++)
- {
- for (int j = 0; j < 4; j++)
- {
- initialStateData.Positions[i][j] = ByteArrayToSingle(data, ref startIndex);
- }
- }
- }
- initialStateData.AffineVelocity = new Vector2Int[4 * particleCount];
- for (int i = 0; i < particleCount; i++)
- {
- for (int j = 0; j < 2; j++)
- {
- initialStateData.AffineVelocity[4 * i + 3][j] = ByteArrayToInt(data, ref startIndex);
- }
- }
- return initialStateData;
- }
- private BakedInitialState LoadInitialStateAsset()
- {
- byte[] data = BakedInitialStateAsset.bytes;
- return ConvertBytesToInitialState(data);
- }
- /// <summary>
- /// Apply currently set initial conditions
- /// </summary>
- private void ApplyInitialState()
- {
- switch (InitialState)
- {
- case InitialStateType.NoParticles:
- LiquidParameters.ParticleCount = 0;
- break;
- case InitialStateType.BakedLiquidState:
- if (BakedInitialStateAsset)
- {
- BakedInitialState initialStateData = LoadInitialStateAsset();
- PositionMass.SetData(initialStateData.Positions);
- Affine[0].SetData(initialStateData.AffineVelocity);
- Affine[1].SetData(initialStateData.AffineVelocity);
- LiquidParameters.ParticleCount = initialStateData.ParticleCount;
- }
- else
- {
- LiquidParameters.ParticleCount = 0;
- }
- break;
- }
- }
- private Matrix4x4 CalculateEyeRayCameraCoeficients(Camera cam)
- {
- float fovTan = Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad);
- if (cam.orthographic)
- {
- fovTan = 0.0f;
- }
- Vector3 r = cam.transform.right * cam.aspect * fovTan;
- Vector3 u = -cam.transform.up * fovTan;
- Vector3 v = cam.transform.forward;
- return new Matrix4x4(new Vector4(r.x, r.y, r.z, 0.0f), new Vector4(u.x, u.y, u.z, 0.0f),
- new Vector4(v.x, v.y, v.z, 0.0f), new Vector4(0.0f, 0.0f, 0.0f, 0.0f))
- .transpose;
- }
- void ValidateColliders()
- {
- if (SDFColliders != null)
- {
- HashSet<ZibraLiquidCollider> colliderSet = new HashSet<ZibraLiquidCollider>(SDFColliders);
- colliderSet.Remove(null);
- SDFColliders = new List<ZibraLiquidCollider>(colliderSet);
- SDFColliders.Sort(new SDFColliderCompare());
- }
- }
- void ValidateManipulators()
- {
- if (Manipulators != null)
- {
- HashSet<Manipulator> manipulatorsSet = new HashSet<Manipulator>(Manipulators);
- manipulatorsSet.Remove(null);
- Manipulators = new List<Manipulator>(manipulatorsSet);
- Manipulators.Sort(new ManipulatorCompare());
- }
- }
- internal ZibraLiquidCollider HasGivenCollider(GameObject collider)
- {
- foreach (var col in SDFColliders)
- {
- if (col.gameObject == collider)
- {
- return col;
- }
- }
- return null;
- }
- void AddToStatReporter()
- {
- StatReporterCollection.Add(this);
- }
- void RemoveFromStatReporter()
- {
- StatReporterCollection.Remove(this);
- }
- #endregion
- }
- }
|