Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

[Updated] Fluid Flow 2.5 - Realtime Flow Simulation

Discussion in 'Assets and Asset Store' started by ChristianSchott, May 14, 2019.

  1. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34


    Hi everyone!
    Fluid Flow version 2.5 is now online!

    Fluid Flow allows you to paint fluid to your objects in real time, and simulate it flowing down the surface dynamically. Use it for blood, paint, or any other kind of fluid.

    The main feature of Fluid Flow is the dynamic flow simulation.
    However, you can also use it just for real-time 3D texture painting/decals, which also supports skinned mesh renderers.

    ️Try the WebGL demo!
    Check out the Documentation!

    Asset Store


    ⚡ The texture painting and flow simulation are handled fully on the GPU for optimal performance!

    New Particle-Based flow simulation!
    ✨ Project Color, Normal, or Fluid Decals!
    Draw Color and Fluid using 3D shapes!
    Update Gravity maps at runtime!
    ✨ Flow reacts to Skinned Mesh Deformations, and Normal Maps!

    Fluid can flow over UV-seams!
    UV-seam artifacts can be hidden! Good UV unwrap is still needed.

    Clean high performance code, with minimal dynamic memory allocations!
    Utilizing Jobs and the Burst compiler!

    Custom Editor tools for easy setup!

    Due to its modular structure, you can decide which parts of Fluid Flow you want to use, without unnecessarily bloating your project.

    Fluid Flow is not a physically accurate fluid simulation, but it provides good-looking fluid for your games at a comparable low performance cost!

    As fluid is painted and simulated in UV space, your meshes require a UV unwrap with non-overlapping UV islands, so there is a 1:1 correlation between the object's surface and the texture.

    Please note that your objects require a specialized shader for overlaying the fluid, or when using the texture atlas system. There are basic surface and shader graph shaders included. Alternatively, you can easily create your own supported shaders with the provided custom shader graph nodes, or shader utility functions.

    ✅ Works with any Rendering Pipeline.
    ✅ Full source code included.
    ✅ Tested on Windows, Android, and WebGL! Should work on any platform!
    ✅ VR/XR Support!

    normal_maps.png particle_blood.png skinned_decals.png uv_stitching.png editors.png

    If you have any further questions or suggestions, feel free to contact me here or via email: mr3d.cs@gmail.com
     
    Last edited: Apr 13, 2023
  2. cmckelvy

    cmckelvy

    Joined:
    Nov 7, 2016
    Posts:
    12
    Bravo sir! I can see some great applications here and am interested in purchasing. Can you confirm if this system is compatible with the HDRP in 2019.1? Thank you!
     
    ChristianSchott likes this.
  3. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hi, I am glad you like it!
    The compute shaders used for the fluid simulation will work independently from the render pipeline you are using.
    But I think the shader used to draw the fluid texture on the object will not work with HDRP.
    It should be pretty easy to write one with shadergraph though. This will definitely be included in the next update!

    I have not played with HDRP much so far, but I have just plugged together a small shader in shadergraph wich seems to work fine.
    So just mail me if you run into any problems :)
     
    cmckelvy likes this.
  4. cmckelvy

    cmckelvy

    Joined:
    Nov 7, 2016
    Posts:
    12
    Thanks! I'll play around and look forward to the update.
     
  5. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Version 1.1 is now released!

    > fluid simulation time is decreased by up to 50%
    > reduced vram usage
    > added shaders for LWRP and HDRP
    > other small fixes and changes
     
  6. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Version 1.2 has been released!

    > added fluid evaporation
    > reduced size of 'FluidObjects' by 50%
    > added possibility to further compress 'FluidObjects'
    > other small fixes and improvements
    > price dropped from 45$ to 40$
     
  7. giraffe1

    giraffe1

    Joined:
    Nov 1, 2014
    Posts:
    305
    how is the performance after the blood has flowed into place and it is just a static mark? What does it impact to have a bunch of AI around 20 units with blood on them? Is it a memory hog?
     
  8. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hi,
    after the simulation is done, there is close to no performance impact.
    However if you have a bunch of simulators it can use quite a bit of gpu memory. Depending on the resolution of the fluid textures.

    Each simulator uses 4 RenderTextures:
    1. contains the geometry data, wich is shared when multiple simulators use the same geometry (128bit per pixel)
    2. contains fluid data and the flow direction (128 bit per pixel)
    3. contains the moving fluid (32 bit per pixel)
    4. conatins the final fluid and normal data (32 bit per pixel)
    And two ComputeBuffers:
    1. filled with geometry data for recalculating the gravity map, wich is also shared between simulators wich use the same geometry (128 bit per triangle)
    2. filled with gravity directions in UV space (128 bit per triangle; I might be able to remove this in the next update)
    This means in the worst case each simulator uses (40 bytes per pixel + 32 bytes per triangle) of gpu memory.
    As long as you keep the fluid texture resolution reasonable (~512) it should be fine.

    I am also thinking of adding a feature next update, wich lets you discard all data except the final fluid texture. So you can't simulate any more, but the fluid is still shown.
     
  9. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Fluid Flow 2 has been released recently!

    It is a complete rewrite of the original system, improving its usability, compatibility, and flexibility a lot.

    Multicolored fluid/paint is now supported, and gravity maps can be updated in real-time, even for skinned meshes.
    Additionally, Fluid Flow can now also be used as a basic real-time 3d texture painting asset, or for painting decals to skinned mesh renderers.

    AssetStore: http://u3d.as/1vef
     
    Last edited: Oct 28, 2021
  10. Nupixo

    Nupixo

    Joined:
    Jan 21, 2016
    Posts:
    8
    Hi, I'm wondering if this is fully compatible with URP? Also, are there cases where it would not work on a skinned mesh model?

    Thanks, this looks very promising.
     
  11. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hi,

    yes, FluidFlow is basically independent of the rendering pipeline you are using. The actual painting and fluid simulation is handled outside of unity's internal rendering loop, so it does not really matter if you are using URP, HDRP, etc.
    So the package generates an internal texture independent of the rendering pipeline, however, you will need a shader, supported by your current rendering pipeline, in order to draw this texture onto your models.

    There is a shadergraph shader for URP included with the asset, which supports this, and it would also not be hard to create one manually (check the corresponding chapter in the documentation).

    And I am not aware of any problems with skinned mesh models. Skinned and non-skinned models are basically handled in the same way by FluidFlow, so there should not be any difference.
     
  12. rwanim8or

    rwanim8or

    Joined:
    Jan 22, 2017
    Posts:
    18
    What is the proper way to go about adding RenderTargets to a FFCanvas at runtime? I tried making new "descriptors" every time one of my NPCs spawned in, but the decal I'm projecting never shows up on their mesh. If I add the same NPC's renderers manually to the RenderTargets before hitting play then it works just fine, but that's not ideal for runtime use.
     
    ChristianSchott likes this.
  13. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hi, I am sorry for the late reply. Somehow, I did not receive a notification for this post.. feel free to also contact me at mr3d.cs@gmail.com if I do not respond within 2-3 business days.

    If you alter the RenderTarget/TextureChannel -Descriptors at runtime, you will have to reinitialize the `FFCanvas`.
    This will allocate the necessary RenderTexture resources and assign the material properties of the renderers.
    However, this will clear all the fluid/paint currently added to the ` FFCanvas`.

    What you probably want to do, is adding a `FFCanvas` component to each NPC, so the required resources are allocated for each NPC instance.
    In general, a single `FFCanvas` component is intended to handle one 'object' (e.g. the player character). The multiple rendertarget slots are intended for cases, where this 'object' consists of multiple (Skinned)MeshRenderers.

    I hope this clears thing up a bit.
    Christian
     
  14. shma_unity

    shma_unity

    Joined:
    Jun 13, 2018
    Posts:
    118
    Heya,
    first of all I want to thank you for this well-made asset. It's really high quality.

    However, I'm having a really weird issue. Everything works and looks fine in the unity editor, but as soon as I make a build, the fluid simulation is frozen (tested with every update method and confirmed via debug that the update is called in the build (calling Fluid.Simulate()).

    I've tested multiple things like a different renderer DX11/Vulkan, as well as different formats for the texture, but nothing seems to work.

    Here is the weirdest thing: When I attach Unity's Frame-Debugger to the build and enable it (which pauses the frame), and then disable it again, it fixes the problem and fluid simulation is running. Obviously, this isn't really a fix, but hopefully some hint on what is going wrong.

    I'm suspecting that there is either something with RenderTextures or maybe with Shader compilation that is causing it.

    My fluid setup is using one RenderTarget and one texture channel. In the editor, everything is working perfectly.

    The unity version I'm using is 2021.3.11f1. I will try to debug this further but I would be thankful for any possible help.

    Let me know if I can provide any more information.
    Thank you,
    schema


    EDIT: After 9 hours, I have found the issue. I took the shaders apart one by one until I found the value that was causing the problem.
    It's not an issue in the asset, but it's a problem that apparently was introduced into unity.

    After building and testing over and over, narrowing down the possible area, it turned out that all shaders and render textures were fully functional in the build, however, one little thing wasn't: unity_WorldTransformParams.w

    The only hint of this value being messed up was on the unity Graphics github for Unity 2023, where I found the following code:

    Code (CSharp):
    1. inline float GetOddNegativeScale()
    2. {
    3.     // FIXME: We should be able to just return unity_WorldTransformParams.w, but it is not
    4.     // properly set at the moment, when doing ray-tracing; once this has been fixed in cpp,
    5.     // we can revert back to the former implementation.
    6.     return unity_WorldTransformParams.w >= 0.0 ? 1.0 : -1.0;
    7. }
    I was wondering if this already applies to Unity 2021, and it turned out that it very much was.
    The value was just plain 0, which set the tangent space binormal to 0 in turn making all gravity 0 as well when normal maps were used.

    Adding this function to the common shader include and then replacing unity_WorldTransformParams with the function in Gravity.shader completely fixed the issue (it comes at the cost of a branch, but as the comment says, it can be eventually reverted).

    I'm not 100% sure what odd negative scale is exactly, but from what I gather it's a really ugly workaround to avoid reverse polygons or something. I've also seem people calling the value obsolete, but I haven't found any official source on that.

    Anyway, I hope this helps should you encounter the issue eventually.
    cheers,
    - schema
     
    Last edited: Dec 30, 2022
    ChristianSchott likes this.
  15. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hello @schema_unity ,
    that does sound like a really weird issue..

    It might be related to an issue, that I thought I fixed some time ago, but it seems like I have never pushed the change to the store, as I am currently working on a bigger update which is not finished yet.

    In the flow map generation shader, I am using `unity_WorldTransformParams.w` which seems to work fine in the editor, but in the build it is set to 0 outside of unity's main rendering loop..
    As in most cases, `unity_WorldTransformParams.w` should be 1 anyway, you can just remove it from the shaders..
    I have attached a screenshot with the two occurrences.

    FF_Flow_Fix.png

    Please let me know if the problem persists.. I will push an update to the store asap..

    Best regards
    Christian

    edit:
    Seems like you have figured it out yourself, before I was able to respond. Thank you for your investigation, this github comment is very interesting!

    As you have already mentioned, the 'OddNegativeScale' has something to do with flipped triangles.
    From my understanding the value should be -1, if one, or all three, XYZ scaling factors of your model are negative.
    This should basically never occur for player characters, but maybe when mirroring some assets..

    Btw. the comparison should not cause a branch here and just do a conditional assignment, so it should not be a big problem.
     
    Last edited: Dec 30, 2022
    shma_unity likes this.
  16. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Fluid Flow v2.5 has just been released!

    The main part of the update is a new particle-based simulation mode.
    Apart from that most of the core systems have been reworked for better performance and usability.

    > AssetStore <

    dyn_normal_flow.png

    Cheers
    Christian
     
  17. nehvaleem

    nehvaleem

    Joined:
    Dec 13, 2012
    Posts:
    440
    hi there! I have just started using this asset and I am already a big fan of it.
    I've got one question though. Is it possible to render a single channel to another texture?
    To give a bit of context:
    - I am trying to stick with default hdrp shaders and use fluid flow only for rendering static decals on skinned meshes (at least for now I don't want to change to custom shaders).
    - I get basic color and normal map rendering working after setup
    - but because how HDRP/Lit is constructed it would be awesome if I could also write only alpha channel to mask texture as it is responsible for smoothnes and mask map have metalic, ao, detail mask & smoothness packed in respective channels. More details here: https://docs.unity3d.com/Packages/c...tion@14.0/manual/Mask-Map-and-Detail-Map.html.

    Is something like this impossible atm or am I missing something?
     
  18. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hi, I am glad to hear you like it so far!
    To be honest I have not really thought about this usecase before, but this definitely seems like a useful feature!

    One possible workaround could be to add a 4-channel packed TextureChannel, and 4 additional 1-channel TextureChannels for metallic, ao, detail & smoothness. And then just write a very basic Blit-Shader, which packs the 4 single-channel textures into one after each change to the textures.
    Something like this (I can send you a full shader if you want):
    Code (CSharp):
    1. return float4(tex2D(_RedTex, i.uv).x, tex2D(_GreenTex, i.uv).x, tex2D(_BlueTex, i.uv).x, tex2D(_AlphaTex, i.uv).x);
    However, this is obviously not a very efficient solution, as this basically doubles memory usage and adds an extra drawcall.

    The best solution would be a new option in the draw methods, which allows you to mask which channels are affected by a given decal/brush. This requires some modifications to the package though.
    I will look into this later today, but this should not take too long to add.
    If you send me your email address, I can send you an updated package as soon as it is done..

    Best regards
    Christian
     
  19. nehvaleem

    nehvaleem

    Joined:
    Dec 13, 2012
    Posts:
    440
    Thanks for the ideas! To be honest - if this is the feature that you could integrate - I'll be happy to just wait for it. I still have to integrate FludFlow into my systems before I'll dig into the FF itself.
    If I can be any of assistance - just let me know, I can test some preview releases or something. I'll dm you my email address.
     
    ChristianSchott likes this.
  20. Setmaster

    Setmaster

    Joined:
    Sep 2, 2013
    Posts:
    239
    What are the difference between particle mode and texture mode? Like performance, limitations, etc.
     
  21. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hi @Setmaster
    in the texture based simulation all fluid data is stored in a 4 channel RenderTexture (color + fluid amout per texel).
    In each simulation tick, the fluid from one texel moves to the surrounding texels based on a separate gravity texture.

    The particle-based simulation stores the fluid data in particles. The particle positions are again updated each step based on the gravity texture. Each particle then draws its current position to a color texture, leaving a trail over time (+blurring, fading, etc.).

    It is very hard to compare performance between the two, as it depends heavily on texture size and number of particles.
    In general, I would say that particle-based is slightly faster, as only active particles have to be processed (inactive particles in the particle buffer do have a small overhead though..). However, the particle-based simulation, also requires this additional step of drawing the particle positions to a texture..

    The biggest difference is probably in the way you add fluid to the simulation.
    For the texture-based simulation, you can just draw a decal to the fluid channel of the FFCanvas, and it will be simulated.
    For the particle-based simulation, you either have to manually push particles with their uv-position and color to the simulation, or project a set of particles onto the surface. Basically throwing a bunch of particles in a specified spot, and hoping some stick. (the second option is a bit hard to explain/hacky, but easier to use in practice).

    Apart from these differences, it is mostly just about your preference. Both are not realistic fluid simulations, and have a different appearance. If you have not already, you can try out the webgl demo and see which mode you like better (https://christianschott.github.io/demos/fluidflow/index.html)

    I hope this helped to clarify the differences a bit further..
    Best regards
    Christian
     
  22. hugo-purespark

    hugo-purespark

    Joined:
    Oct 29, 2022
    Posts:
    15
    Love your work but I'm a bit confused. I used the example scenes and added my own model, and it works. Using the demo script I then modified it to use in my VR project. However to pass the Vector3 position of where the ray hits my character to the getProjection function in the demo script I have to use a Ray. But a ray attached to my VR hand can only return a position if the object that has a collider. I don't have any colliders in the example scene using mouse position and it works fine. Why do I then need colliders in my VR project to return the position of the ray?
     
  23. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hello @hugo-purespark
    you don't necessarily need a collider on your models for drawing/adding fluid to them.

    What may be a bit unintuitive, is that FluidFlow draws to the FFCanvas based on the 3d world-space coordinates of your mesh.
    So every pixel of the FFCanvas' TextureChannel, that e.g. lies within a sphere in world-space or inside a 3d projection frustum, will be painted.
    Just imagine a 3d camera looking at model (only that it is projecting a texture onto the model, like a flashlight).

    One common way to figure out where such a sphere or projection frustum should be placed in 3d world-space is with a raycast+colliders. However, you can also figure this out in many other ways..

    What I think might work in your case, would be an orthogonal projector starting at your VR hand position, in the direction you are pointing.
    Just make sure to set the far clipping plane of the projection to something larger than the distance to your target.
    If you roughly know the distance to your character (e.g. via the intersection with the bounding box), you could move the projector "closer" to the target. Though, this should not really make any difference in case of an orthogonal projection (maybe it can reduce z-fighting for very far away targets).

    I hope this clarifies things.. Best regards
    Christian
     
  24. hugo-purespark

    hugo-purespark

    Joined:
    Oct 29, 2022
    Posts:
    15
    Thanks. I ended up doing exactly that and used a projector rather than a raycast. If I may ask what is the best settings for performance in VR?
     
  25. hugo-purespark

    hugo-purespark

    Joined:
    Oct 29, 2022
    Posts:
    15
    Just to clarify. For Quest 2 direct install via APK
     
  26. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    well, it is hard to give the 'best' settings, as they depend heavily on your use case.. in general, you will get the best performance with the lowest quality settings.
    As usual, it is a tradeoff between quality and performance.

    As a general guideline, I would suggest using the smallest RenderTexture size which still gives you good enough visuals (maybe around 512x512 depending on your model..). Larger RenderTextures will quickly take up a lot of vram, and will cause the simulation to compute for longer. However, if you only have very few simulators active at the same time, you might get away with lager textures.
    Another way to improve performance is to adjust the simulation tick-rate based on how close a simulator is to the player, so only simulators which are actually visible consume resources.

    So you see that these tradeoffs are very similar to any other part of a game.
     
  27. Epikus29

    Epikus29

    Joined:
    Jul 29, 2014
    Posts:
    1
    Hello! This is a very impressive asset, thank you for sharing it.
    Is is possible to use this asset together with a shader that changes the object's geometry (vertex offset / displacement)? Or can it only use geometry deformed by the skin modifier?
     
  28. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hello @Epikus29 , happy to hear that you like it :)
    Sadly, FluidFlow will not consider vertex offset/displacement from a custom shader out of the box.
    FF internally draws the models with a custom shader for the painting/calculating the gravity, so any geometry/vertex functions from the material's shaders will not be considered.
    Only changes to the underlying vertex buffer will be considered (eg. skinning, blend shapes)

    In theory, you could maybe add your custom displacement functions to the internal FF shaders, but this may become quite complex.

    Best regards
    Christian
     
    Epikus29 likes this.
  29. UsefulWeapon

    UsefulWeapon

    Joined:
    Oct 26, 2013
    Posts:
    66
    Hey! @ChristianSchott realy interesting asset. I am considering buying it but i have few questions: Will it work with custom shaders? I am using RealToon HDRP shader at the moment for my game. And how optimized is it? For example if i use it on NPCs in my game? I have 25 MAX on scene at one time.
     
  30. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hello @UsefulWeapon , it can work with custom shaders, however you will have to modify the shader to overlay the fluid texture over your model.
    This is usually not too hard, but it really depends on the complexity of the shader, and how familiar you are with writing/editing shaders (or shader graphs). There are some utility functions included, and you can take a look at the included shaders.. broken down to the most basic level, you would basically just:
    - read from the fluid texture
    - interpolate between the model's color and the fluid color, based on the amount of fluid (something like: `color = lerp(baseColor, fluidColor, fluidAmound)`; similar for other channels)
    There is more detailed information in the documentation https://christianschott.github.io/docs/fluidflow/book/custom_shaders.html

    Regarding performance: as all the simulation and drawing is done on the GPU, it is basically as optimized as it can be (feel free to let me know if you see any possible improvements).
    However, obviously it will create some DrawCalls when drawing to the fluid texture, updating the gravity, or simulating the fluid. Usually, this should not be a big problem even for multiple actors, if you optimize, what gets updated each frame (only update objects in view, update far away objects less, etc.)
    The bigger problem is typically the amount of video memory needed. Each NPC will need at least one 4 channel 16bit floating point render texture, for storing the fluid, and another 4 channel 8bit render texture for the flow map.
    So as long as you keep texture resolution low, you should be fine, but you can probably see how this could add up quickly..

    I hope this answers your questions. Best regards
    Christian
     
    UsefulWeapon likes this.
  31. UsefulWeapon

    UsefulWeapon

    Joined:
    Oct 26, 2013
    Posts:
    66
    Thanks for the fast reply! Sadly the shader is pretty complex and big and i only familiar with shader graph and amplify shader, but this shader is written by hand i think. Maybe i can share it with you and you can tell me if it will be even possible to modify
    Optimization wise thanks for the tips, i think this wont be a huge problem. I just want to draw blood flowing down on the point of bullet impact. Game is low poly so texture size wont be huge
     
  32. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Sure, I can take a look at the shader.. however, I don't have access to my main workstation this week, so I can't really promise when I will find some time..

    Best
    Christian
     
  33. UsefulWeapon

    UsefulWeapon

    Joined:
    Oct 26, 2013
    Posts:
    66
    Thanks! I will send you the shader today, look in your DM's on unity forum :)
     
  34. Eggtooth

    Eggtooth

    Joined:
    Dec 29, 2015
    Posts:
    4
    Hey there. I'm interested in this shader, however I wonder one thing:

    Can this be used with KWS Water system to create dynamic "wetness" on the character? KWS Water does not use collision for its water instances, but has a way of detecting surface of the water and dynamically detects in which water instance you are in.

    Do you think it would be possible to make dynamic wetness mask based on distance from the surface to the water (like in Uncharted Series or any AAA game with water rendering) with this shader that could work with water shader? How would one go about doing that?
     
  35. ChristianSchott

    ChristianSchott

    Joined:
    Sep 19, 2015
    Posts:
    34
    Hello @Eggtooth
    I am not familiar with KWS Water, but in general I think something like this should be possible.
    I don't even think you necessarily need the gravity-based flow simulation, but mostly just the 3d skinned texture painting.

    My rough idea would be detecting if the character is currently in water, and adding a wetness values to all pixels below the surface level of the fluid (via a FFBrush; the built-in FFBrushes should be sufficient, but maybe a custom brush based on a plane-signed-distance-field + some random noise, would yield better results)
    Fading this wetness value over time (via a FFEffects component) to simulate evaporation, and altering the character's shader based on this wetness texture (e.g., increasing the smoothness value).