- Category: Blueprints
- Update: 2.0 (9-06-2023)
- Unreal Engine: 4.26 - 5.2
- Platforms: PC, Console
The Fluid Flux is a powerful water system based on 2D shallow-water fluid simulations.
- Realtime shallow water simulation – fluid data modifiers, wave generator, and extendable interface
- Fluid surface rendering – caustics, wetness, underwater, waterline, advected foam, advected waves, blending with the ocean, dynamic audio detection
- Fluid Interaction – simple cheap ripple solver moving with character, optimized to an absolute minimum
- Ocean wave blending – rendering tillable ocean heightmap texture in a single pass
- Niagara environment interaction – High-quality effects, bouncy, plants, character swimming, boats,
- Clean, efficient, GPU-friendly implementation, interface designed with the KISS (Keep It Simple, Stupid) rule in mind
- Tool for generating ultra-fast static meshes with flow maps baked into vertex color.
- Advanced fluid state management, loading state in gameplay.
- Niagara fluid async readback system for sampling height and flow of fluid in blueprints.
- Dynamic audio analyzer. The sound source is positioned based on fluid movement.
- Four example maps – beach, island, river, and baked static river
- Velocity-based fluid flow advection method for foam caustics and waves
With great power comes great responsibility. I am committed to being a reliable marketplace creator, so it is important for me to clearly communicate the limitations and disadvantages of using simulations. The Fluid Flux system is somewhat overhyped, so please read the description below and ensure that everything aligns with your expectations and requirements before making a purchase. Ensuring that is crucial for the Refund Policy:
- Overall, I cannot address every conceivable water issue in every type of project. While Fluid Flux represents a significant advancement for the game industry, it also introduces additional challenges. Controlling and adjusting simulations can be demanding; sometimes, a single parameter change can alter the fluid flow across an entire map.
- The Fluid Flux simulation is based on the Shallow Water Equations (SWE) solver, the algorithm was published by Matthias Müller in “Real-time Simulation of Large Bodies of Water with Small Scale Details”. Simulation is calculated on heightfield mesh which means all obstacles are rendered to heightmap using top-down projection. Fluid can not be simulated in caves however, it is possible to make the algorithm ignore certain objects, such as bridges, so they do not interfere with the simulation.
- Scalability is a real problem. The simulation requires allocating floating-point render targets so the maximum recommended resolution of texture is 1024×1024. That means if 1 pixel represents 100 cm in real-world (very low quality) then your simulation area can cover approximately 1km x 1km square with low detailed water. It’s not that much but still useful. The simulation frame can be baked to static mesh and used as mesh placed on the level.
- Efficiency may be a problem. I recommend avoiding the use of resolutions larger than 1024×1024 in games. The calculation of a large-scale simulation often requires a substantial number of computations. As a result, I suggest utilizing the lowest feasible resolution for the simulation. For example in the example demos I provide, the maximum resolution employed is 1024×256 (BeachMap).
- Multiplayer is not supported for dynamic simulation because synchronization of render targets is limited. However, the system can be used in a multiplayer game as long as your gameplay is not dependent on fluid simulation results.
- Statically generated LOD mesh can be inconsistent with waterline post-process this issue will be addressed in the future.
- Water Plugin is not supported in the current version. It is possible to use my water material with the water plugin mesh but it is not officially supported.
- Niagara fluid readback used for buoyancy and fluid detection returns results with (at least) one frame delay. It’s good enough for most features like swimming fluid detection etc. but not 100% reliable. Trace hits with dynamic fluids are not supported now.
- My support time is very limited because I am also working on the updates that will improve the quality and efficiency.
- The system is enormously advanced and complicated so it may be overwhelming for beginners.
- The documentation may be incomplete in some areas. I was pushed to release as soon as possible and could not find enough time to prepare many simple examples. The Fluid Flux system is clean and elegant but blueprint reading skill and example code analysis is required to use.
- The simulation area can’t be rotated. The product supports only axis-aligned rectangular volume.
- The simulation area can’t be moved in runtime. Movable volume is one of the most important features for future updates.
- The simulation does not support the wave break effect because this approximation of fluid does not contain the needed data to render it.
- Underwater glass, holes, and the submarine view are not supported yet.
- The weakest point of this product is its documentation. I may not excel at explaining things, but in case of any issues, I will make an effort to resolve them for you. Please don’t hesitate to ask.
Good and bad practices
- Try to avoid using huge simulation resolution because you will run out of memory very fast, 1024×1024 seems like a good compromise for now.
- Don’t make your gameplay rely on fluid simulation in multiplayer because it can’t be synchronized.
- Avoid using Fluid Flux on flat surfaces, subtle slopes are always better.
- Avoid hard-edged geometry (boxes) it can be approximated wrongly in height maps and large slopes sometimes look terrible
- Try not to overestimate this system. If I haven’t prepared the ocean with ships and a huge island covered by rivers and simulated lakes, there is probably a reason for that.
- Try to not update the simulation ground in every frame it may cost you a lot of performance.
- Meshes using the materials with “PixelDepthOffset” active may not render properly into a ground height map. There is a simple workaround described in the chapter “Ground Capture->Solving issues”.
Questions & Answers
- Unreal Engine 5
The Fluid Flux was originally developed and tested on Unreal Engine 4.26. While it can be used with the latest version of Unreal Engine 5, please note that Unreal Engine 5 is still in the early stage of development. Especially new features like Lumen may not be supported properly.
As a result, I cannot provide support for engine-related bugs or address differences between UE4 and UE5. To ensure you are aware of the most common issues that may arise, please refer to the ‘Known Issues’ chapter.
- Why is the price so high? Can you offer any promotions or discounts?
- Creating a Fluid Flux required over 20+ months of research and development. Typically, a system of this nature would cost the company at least $200,000. The current price is making it a significant time and cost-saving solution for everyone.
- The price of the Fluid Flux pack includes a subscription for all future updates and my support. This kind of system requires a lot of support, especially with ongoing engine updates. Since I have other products on my marketplace profile, my time is currently limited. I already quit my regular job to fully focus on developing and improving products, and I may need to hire someone to help me manage everything.
- The asset combines several significant features that have been designed to seamlessly work together, making your development process easier. You no longer need to purchase multiple separate products and spend time integrating them. It includes a ripple solver simulation, shallow water fluid simulation, water surface rendering, ocean wave generator, buoyancy support, waterline effects, post-processing capabilities, coastline rendering, and even support for Niagara particles. I have taken care of all these aspects so that you don’t have to worry about them.
- Please check my marketplace profile to confirm that I am a trustworthy creator with hundreds of positive reviews. The price of my products is always determined based on the actual work and time required to develop them. Eventually, you will come to realize that time is a genuine currency with significant value in this world.
- There will be a promotional sale but first I need to feel that I am ready to support more customers. If you are not in a rush then just add my product to the wishlist and please be patient. If you want to be notified a few days earlier about a planned promotional sale then join my Discord server.
- I’m not forcing anyone to buy my product. There are alternatives like Niagara Fluids and Water Plugin, you can try them for free and compare results with my demo, maybe you don’t even need the Fluid Flux. Choose wisely.
- Can I use it in my open-world game?
The true open-world setup has not been tested yet. The demo examples are showing how the system can be used. I can’t promise anything more at this point of development. Just assume that you get what you see in my videos no more no less.
- Does it support multiplayer/replication?
Unfortunately, multiplayer is not supported. The Fluid Flux can be used in multiplayer games only as a visual addition and should not affect gameplay. There are many reasons:
- Technical limitations. Fluid Flux uses Niagara readback for sampling wave data (it’s the only way to read from GPU). Niagara is not working on the server.
- Bandwidth limitations. There is too much data changing dynamically so simulation can’t be synchronized over the internet. Everything would break very fast without correcting the differences between a server and a client.
- Human limitations. I am not a multiplayer programmer so it’s even harder for me to jump into it and find reasonable workarounds.
- External packs integrations ALS/UDS/Fluid Ninja
I am planning to work on some integrations in the future. If you have some specific pack in mind let me know.
- Can I use it with Voxel Plugin?
Yes, you can use Fluid Flux with Voxel Plugin but it is also limited to heightfield projection so caves and planets are not supported.
Use Simulation.RuntimeCaptureDelay = 1.0 to force simulation to wait for the voxel plugin map to generate mesh before rendering it to the height map.
The heightmap in this presentation is updated every frame using CaptureGroundHeightmap. It is not very efficient and should be probably optimized to only update the area around the brush when something changes on the map. The UpdateGroundMap(Position, Size) function would be a better choice in this case.
- What about VR and mobile?
The VR devices and mobile are currently not supported by me.
Dynamic fluid simulations with high precision can’t be calculated on mobile so only baked meshes/states can be used on this platform. I am planning to add VR and mobile support in future updates. The pack will receive a cheap surface material mode similar to the solution presented in Aquatic Surface. One user notified me that my demo maps are working without issues on Oculus Quest 2 but I did not test it yet so I can’t confirm it.
- How to add swimming to ALS? Can you show me?
This task is on your side. The Fluid Flux BP_FluxDataComponent) can give you all the data that you need to implement swimming. I’ve also prepared an example swimming implementation (BP_FluxSwimmingComponent) for testing.
- Should I switch to Fluid Flux? Is it better than WaterPlugin/Oceanology or Aquatic Surface?
It depends on your specific requirements. Fluid Flux excels at creating dynamic river simulations on heightfields and interactive scenes, but it doesn’t scale very well. If you only need a background ocean without detailed simulations, then you might not want to go through the trouble of using simulations at all. However, Fluid Flux 2.0 introduces a new coastline domain system that can handle landscapes of up to 10km x 10km and provides an infinite ocean. I recommend playing the demo of Fluid Flux to get a better sense of whether it aligns with what you’re looking for.
- Why blueprints? Is Fluid Flux slow because of that?
This system is fully implemented in blueprints but relies mainly on GPU (shaders/render targets). Yes might be faster in C++ but it would also stretch out the development time. The cost of blueprint code will be reduced by Niagara implementations in the future so it will work even better.
- Is Fluid Flux calculated deterministically?
If you simulate on the same machine it is deterministic (constant delta time is used) but there are probably differences between floating-point operations on different GPUs so it can’t be fully deterministic. In the case of multiplayer games, the biggest problem is the synchronization of state when someone joins the game and when the player loses some frames because of spikes and the simulation can’t work it off – I’ve decided to limit the number of accumulated iterations per frame in this case.
- Do I need this pack? Other water systems like your Aquatic Surface can do the same.
Well, if you can’t see the difference then probably you don’t need the Fluid Flux. I’ve prepared a simple comparison of Fluid Flux and Aquatic Surface that visualizes the difference:
That does not mean Aquatic Surface is bad. It’s a great product with a completely different feature list. You have to choose a product that fits your requirements.
- Is it efficient?
It depends on GPU, resolution, etc. You can download the demo and try it yourself there is an FPS counter on the screen.
GPU Resolution River map Island map RTX 3080 2560×1440 320-380 FPS 260-310 FPS RTX 2080 2560×1440 160-200 FPS 110-160 FPS GTX 860M in 8 years old notebook Lenovo Y50 1920×1080 25-30 FPS 20-25 FPS
- What about the future of this project?
I have plans for numerous updates but I don’t have a specific timeframe as of now. It’s crucial to make your purchase decisions based on the product demonstrated in the demo, rather than relying on promises. You can keep track of the current progress of improvements at Trello.
- Scalability – Large-scale simulations locally updated with the moving areas are in my plans.
- Niagara fluids – The system will be rewritten to Niagara fluids once it is stable and ready for the transition.
- Audio detection – the current system uses an ambient audio source and a simple dynamic source I am planning to improve to three dynamic sources of audio that work at a different distance.
- Simulation volume – Moveable simulation area and the ability to work with multiple simulations simultaneously.
- Alternative material modes
- Meshes with dithering enabled can not be cached by ground capture. There is a workaround for this problem presented in the M_Photoscan_Master material. More info in chapters related to ground capture.
- It seems like construction scripts are working differently when the level is loading during the editor starts in UE5.1.Render targets are not initializing properly because of that. If you see that something is not loaded then just reopen the map/restart the simulation and everything will work fine again – sorry for that.
- Plants will not load properly on the map if you are not in “Real-Time” render mode in the editor. Its limitation of blueprints I don’t have any event that could execute after the loading and adjust Niagara effects.
- “Real-Time” render mode is required to simulate in the editor. Otherwise, the view will not refresh after each frame.
- If you downloaded Fluid Flux 2.0 for UE5.1 and later updated the engine to 5.2, it is essential to update Fluid Flux as well. This is because certain engine features have been deprecated between those versions.
This section covers the fundamentals of Fluid Flux and its tools. If you are new to Unreal Engine, you should become familiar with the Unreal Editor interface, Blueprint visual scripting, and the types of content. Working according to the documentation can provide the best possible experience with this product.
The effective use of the Fluid Flux pack requires activating specific built-in engine plugins and integrating TPP input configuration for testing the example character implementation from the demo. As a marketplace creator, I cannot incorporate these changes into the asset pack, so developers need to implement them in their projects.
I recommend using the template example project for your initial trials with Fluid Flux. The easiest way to run the demo is described below:
- Download the FluidFlux_Template and unpack it.
- Open and run the FluidFlux.uproject file (it will automatically register the FluidFlux project in the launcher projects list). The template project is prepared for 4.26 but can be converted to any higher version including UE5.
- Download the Fluid Flux asset pack to the template project using the marketplace launcher.
Working with an external project is a bit more challenging because every project may use some specific configuration characters and use a different version or feature set of the engine so requires configuring everything by hand.
Below you can find a list of plugins that are required by Fluid Flux:
- Editor Scripting Utilities
- Procedural mesh Component
The first place to visit in the demo folder is Demo/Maps. This folder contains all example maps that are working perfectly with the TPP example character (BP_DemoCharacter). If your project uses another character template then probably input should be changed to make it work properly.
You can also set it up by hand in project settings or download it from this link: DefaultInput and copy it into your Configs/DefaultInput.ini file.
In the final stage of configuring your project make sure that:
- DBuffer is enabled in your project settings because it’s required for proper decal (wetness and caustics) rendering. If you don’t want to use those effects then you can disable decal material in the surface actor.
- CustomDepth-Stencil Pass is enabled in your project setting. This feature is required for proper underwater masking.
- Strta/Substrate materials should be disabled in your project. This feature is still experimental and not supported by Fluid Flux.
- Real-time rendering is active in your viewport it is required for simulating fluid in the editor.
The Fluid Flux project is organized in a certain way, this short description will bring you closer to what kind of content can be found in each folder.
- Demo – The demo is the most important folder for new users. The demo examples present how to use this pack, how effects can be achieved, and how to integrate systems with characters. Everything that can’t be found in this documentation probably will be presented in a very clean way in the demo folder.
- Editor – editor-related tools, icons, utilities, procedural mesh generator
- Simulation – Shallow water simulation actor and tools for controlling fluids and generating state.
- Coastline – Generating coastline data for oceans.
- Interaction – A simple system of interactions that adds detailed lightweight ripple fluid simulations.
- Surface – Renders surface, underwater volume, post-process, caustics, and playing audio.
- Environment – Niagara particle systems that allow readback pieces of information from simulation implementing swimming, buoyancy, and drive particles using fluid state.
- Waves – a system designed for generating ocean waves that can be used in the background and mixed with fluid simulation. Before starting work with the pack it’s worth being familiar with the structure of the pack and the systems that it provides.
The latest version of the product is detailed on the marketplace page and at the beginning of the documentation. Frequent updates for Fluid Flux are planned, so always ensure that the Fluid Flux package version is up to date. However, be mindful of potential issues when updating.
Changes that can be made during updates:
- fixing bugs
- adding features and examples
- removing/renaming files
- improving quality and exposing parameters
I am always trying to minimize the update damage however it is not an easy task when an update system on the marketplace supports only adding or replacing files. There are a few basic rules worth noticing before updating:
- It’s better to make some backup first. Copy your version of the pack before doing the update,
- Remove the pack from the project before updating it. This way you will get a clean, and fresh version of the pack without any ghost files.
- Do not modify the pack on your own. If you need modifications then you can inherit classes/materials and override functions. Store child classes and custom material instances outside the Fluid Flux folder.
- If you need some small trivial modification that could improve usability then you can let me know we will figure out some solution maybe put it into the next update.
The code that doesn’t exist is the code you don’t need to debug. I am trying to do my best and solve all possible bugs or find good workarounds but there is always something that can be broken it’s like a typical lifetime of applications nowadays.
Simulations can be unpredictable some edge cases are probably still not handled. In case of finding some specific bug, you can report it to me and I will take a look at it in a few days. Before sending the report:
- make sure that you use the newest version of my pack.
- prepare a detailed explanation of the repro steps needed to recreate your bug, and make sure that the explanation is as clear as possible.
- create a minimal example project that can show me the bug (it will increase the chance of fixing it)
- attach information about the engine version you use, and your development platform.
- prepare a video or screenshots presenting the problem and reproduction steps.
Now you can report this bug by sending an e-mail to firstname.lastname@example.org
Ground capture is a fundamental aspect of Fluid Flux systems, as the fluid requires a designated vessel. The recognition of water blockers is achieved by rendering the scene into a height map using a top-down projection. A height map also referred to as a ground map, is a specialized texture that stores the height information of the geometry in pixels.
In the Fluid Flux pack this task is handled by a component FluxHeightmapComponent that is used in both the simulation domain and the coastline domain. The generated height data play a pivotal role in determining the appearance and movement of water on slopes.
The ground scene capture component renders the current scene into a heightmap texture. Sometimes, we need to exclude certain actors, such as bridges, that should not act as fluid blockers. In the ‘Domain:Heightmap: CaptureVisibility‘ tab, you can find options that may help determine which meshes should be visible in the heightmap:
VisibilityMode can be used to determine whether the capture actor should render the entire scene and exclude specified actors (HideAllListed) or just build a list of actors that should be used as blockers (ShowOnlyListed).”
- ActorsReferences – exclude chosen actor objects on your scene
- Actos of Class – can be used for excluding by type of actor class and its child classes
- ActorsWithTag = “FluxHide” that every actor that uses this tag will be added to the list of excluded objects.
- Use M_PhantomMesh material to render mesh ONLY during processing ground (invisible in the world) good for imitating soft slopes of waterfalls or just creating an alternative version of ground when the environment is more complicated (like indoor meshes).
If you notice that some objects should not be rendered to heightmap you can exclude them and if something is not rendering you can start investigating what is going on without simulating the fluid.
In case of any problems bugs or unexpected behavior, the debug preview option is the most important feature. It shows a height map that will be used for blocking the water on the scene.
It’s noticeable that not every detail will be captured in-ground map and the accuracy depends on the simulation resolution scale. The shader used for rendering this preview is coloring lines based on slope and exposes the discontinuity of the ground.
- Green lines – easy to simulate very stable fluid
- Blue lines – Good slope for moving fluid in some direction
- Red lines – can cause some instability if fluid flows on it but good for walls
- White lines – there may be some cave that can expose holes in the fluid mesh.
- Fully red polygons represent holes and discontinuity in the mesh. It should be eliminated if fluid can flow into this area.
Landscape or mesh is not rendering to the ground map
If the “PixelDepthOffset” feature is used in the material then it may be not rendered to a ground map and cause some simulation problems. This problem can be easily fixed in your material by simple modification. Use the MF_FluxPixelDepthOffset material node that will automatically disable “PixelDepthOffset” while caching the ground map.
The M_Photoscan_Master material is an example of a workaround for this problem with the use of the MF_FluxPixelDepthOffset node.
The BP_FluxSurface is an abstract actor responsible for the general implementation of an audiovisual representation of the simulation and coastline domain data.
An abstract actor is like a guide for creating new actors. It defines some common features that all related classes should have, but it’s not complete on its own. Other classes need to finish the details. For example, an abstract class may not specify any ambient water audio, but a customized ocean template has sounds that match the type of water it represents.
The surface actor implements a list of advanced subsystems:
|Volume Absorption, Volume Scattering||
The BP_FluxSurface is an abstract base parent class which means it can’t be placed directly on a level. Configuring all these subsystems can be time-consuming, particularly for new users. This is why the package includes basic configured surface child actors templates that can be found in the FluidFlux/Surface/Templates folder.
|Default water surface, spawned dynamically when the domain.SurfaceActorReference is not specified.|
|Simple river/waterfall material and basic underwater post-process, reiver audio|
|Advanced ocean materials, ocean audio, materials blended with wave actor, underwater mesh, underwater scattering, and absorption volume.|
|Rendering two domains simulation and coastline at the same time. Useful or large oceans and islands.|
Users can also implement their surface templates and extend the functionalities of the surface as well.
The BP_FluxInteractionCapture is a system designed for adding efficient detailed interaction simulated in small areas around the camera (or specified object).
- It is a perfect addition that can improve the quality of baked simulation almost for free.
- It is currently supporting the simplest fast ripple solver (but there are plans to simulate a fluid pressure solver in the future)
A demonstration of the interaction system configuration is highlighted in the BP_DemoCharacter. This blueprint illustrates the application of components for enabling character interactions with water. A detailed explanation of the implementation can be found below:
- BP_FluxDataComponent – This component reads the fluid data like height and velocity that are needed during further calculations of interaction. You can find more info about this component and configuration in the section Async readback.
- BP_FluxInteractionComponent – This component stores a list of interaction sources. The interaction source is a sphere attached to a component (or skeletal mesh bone) that will generate waves after interacting with fluid.
- Interaction sources are attached to skeletal mesh with the tag specified in the OwnerComponentTag attribute so it’s important to add this tag (FluxInteractionOwner) to skeletal mesh that will move the interaction sources.
- The BPI_FluxInteraction is the interface that takes care of communication between the actor and the interaction capture system. It should be added in the Class Settings of the actor that will interact.
- Implement the GetInteractions in BPI_FluxInteraction. When BP_FluxInteractionCapture is an overlapping interactive actor then it’s calling this GetInteractions function to find pieces of information about interactions that occurred.
There are many steps to do before interaction start working but no worries you can debug and make sure that every part of your implementation works correctly:
1. Test it on demo maps at first
2. Enable DrawDebug in BP_FluxInteractionCapture
3. Enable DebugDraw in BP_FluxDataComponent
4. Enable DebugDraw in BP_FluxInteractionComponent
5. Make sure that “GetInteractions” is evaluated. Put a breakpoint in this function to check.
Interactions with a fluid surface may generate splashes, which add realism and immersion to the simulation. This is achieved through a straightforward mechanism that detects when the interaction source intersects the fluid surface. If this condition is met, a splash effect is created to simulate the disturbance caused by the interaction.
The InteractionComponent->Source->SplashType defines the index of splash that is indexed is stored in the Surface->InteractionSplashes array.
World painter and brush
The FluxWorldBrush is a unique actor designed to manipulate data stored in the WorldPainterComponent canvas. The system offers three distinct types of canvas on which the FluxWorldBrush can perform painting operations:
- ColorPainter ( BP_FluxWorldPainter), interpolation between the base color and painter color.
- WaveSize (BP_FluxCoastlineDomain), interpolation between no wave and highest wave.
- WaveType (BP_FluxWorldDomain), interpolation between Oceanic wave and coastline wave
This two-minute tutorial presents the workflow and possibilities of brushes:
Reading fluid data
The Fluid Flux uses Niagara asynchronous readback events to read data from fluid render targets and pass them to blueprints. The BP_FluxDataComponent is a listener that can receive, update, and store fluid data at a certain location.
The Fluid Flux uses this feature in multiple situations:
- buoyancy and floating objects
- automatic dam breaking
- interaction detection
- swimming system
- fluid sound source analyzer
- underwater camera detection
Add BP_FluxDataComponent to your actor and it will automatically detect the fluid surface under the actor. BP_FluxRotatorActor is a good simple example of an actor that can react to fluid.
The Readback data component can be attached to the scene component in the owner actor by adding a tag to it “FluxReadbackOwner“.
Use Debug option in FluxDataComponent to make sure that component is following your actor and sampling proper values.
The Niagara integration is based on three elements:
- BP_FluxNiagaraActor communicates with the simulation and data to the Niagara system.
- NE_FluxData emitter should be inherited by the Niagara system to read the data.
- NMS_FluxData special module that extracts simulation data to Stage Transients variables that can be used to drive the particles.
All particle systems (trash, plants, splashes) in the pack are constructed the same way, feel free to check the examples and modify them.
The BP_FluxSimulationDomain blueprint is the heart of the Fluid Flux system. This blueprint is responsible for handling important tasks like:
- Rendering of the ground height map to texture.
- Updating simulation of shallow water fluid, foam, and wetness.
- Baking and exporting simulation state.
- Sending data to the fluid surface renderer.
The Shallow Water simulation is based on the idea of assuming linear vertical pressure profiles so it is simulated in two dimensions. In general, the algorithm can be described in a few steps:
- Simulation data is stored on 2D render targets.
Ground map – information about landscape and obstacles
Velocity (RG) Depth(B) Foam(A) map – stores information about fluid
Height(R) Wetness(G) map – stores surface height and wetness of the surface
- The slope of the ground heightfield and the slope of fluid are combined and used for calculating the pressure and velocity.
- Simulation is an interactive process of updating fluid height and velocity.
- The result of integration is used for foam and velocity advection.
- Fluid modifiers can be used as input for simulation to change the current state.
- The simulation frame is used for accumulating fluid wetness and generating the fluid surface mesh displacement.
The BP_FluxSimulationDomain actor placed on the map is doing nothing because it’s empty and needs to be filled with fluid. The simplest way to fill containers with fluid is by using a Modifier source actor.
The BP_FluxSimulationDomain blueprint comes with a simple editor that allows simulating the state of the fluid on the map in the editor mode. Simulation can be prepared in the editor baked to state or dynamically updated by the simulation blueprint.
A modifier component is a powerful tool that affects the simulation state and changes the current simulation state. It’s the simplest way to interact with the simulation. Modifiers can be used for:
- Adding/removing fluid in the simulation domain.
- Changing the velocity and flow direction of the fluid
- Simulating custom interaction with fluid
- Generating waves
The tutorial below presents how to add a source modifier on the scene and fill the simulation domain with fluid:
The Fluid Flux contains predefined modifiers:
- BP_FluxModifierComponent – Base parent class for all fluid modifiers. Every modifier component extends it and implements specific behavior. Users can create custom modifier classes and materials for specific use cases like whirlpools/waves. Describing the architecture is outside of the documentation scope, the BP_FluxModifierSourceComponent component is a good example of a modifier that can be used as a starting point for learning how the system is designed.
- BP_FluxModifierSourceComponent – Simple modifier that allows adding/removing fluid and changing velocity in a specific area.
Parameters Volume The quantity of fluid applied by modifier (depending on Mode). Velocity The velocity of fluid applied by the modifier (depending on Mode). Shape The shape of the fluid modifier Mode Defines how the modifier is applied to the simulation. All modifiers are rendered to a simulation buffer. Mode is a method of blending used during this process.
Add – This mode will add the ‘volume’ of fluid and its velocity to the current fluid on the map.
Adjust – adjusting the current state of fluid to the height of the modifier.
Set – will set the constant height of fluid in the area.
Edge The softness/hardness of the modifier edge. Useful for soft mixing with fluid or uniform filling the vessel. Intensity Scale the effect of the modifier on the domain (0.0, 1.0>. Duration Defines how long the fluid source will be active. (less than 0 means infinite), (0 Rendered in a single frame and then modifier will be disabled), (more than 0 is the duration in seconds) SortPriority Affecting an order of modifiers in the queue. It may be useful when the user needs to fill the domain and then remove some fluid. A value larger than 1000 forces the system to add on the end without sorting. AutoActivate The modifier can be inactive at the beginning and activated by an event from gameplay or a sequencer.
There are many ways to remove fluid in the simulation domain. It depends on the mode you choose:
Mode= Set, Volume=0 – will set 0 water in the area of the modifier
Mode= Adjust, Actor.Z position – lock fluid at a specific height
Mode= Add, Volume negative – slowly removes fluid
- BP_FluxModifierGerstnerComponent – Generates waves/fluid on borders of the simulation domain. More info and use cases can be found in the chapters related to ocean configuration.
- BP_FluxModifierForceComponent – Generates forces when the actor is moving (based on the velocity). Can be added to the character.
The modifier container is a special type of actor that can store multiple modifiers and send them to the simulation. If the actor implements the BPI_FluxModifierContainer interface then it’s considered a modifier container.
BPI_FluxModifierContainer interface can be implemented by any actor. A good example is BP_DemoCharacter that uses BP_FluxModifierForceComponent to interact with a fluid. AddModiffiers function only needs to be implemented to make it work.
BP_FluxModifierContainerActor is a basic container that can combine multiple modifier components in a single actor that works simultaneously.
BP_FluxModifierSourceActor is a specific type of container actor that simplifies the process of adding simple source modifiers to the scene.
Every modifier is rendered in an additional render target pass, so it’s not cheap. It’s good practice to minimize the number of fluid modifiers inside the simulation to achieve the best possible performance.
Unexpected spikes sometimes destroy the simulation. Shallow water simulation can exhibit unpredictable behavior due to the loss of stability when encountering steep slopes. This is a widely recognized problem that can be resolved by fine-tuning specific parameters and enhancing the reliability of the simulation.
- Slope Scale (Increase)
Increasing this parameter will scale down the height of the scene on the Z-axis and make your fluid move slower on slopes. (This parameter will be probably redesigned in the future version for better consistency with the world scale measurements).
- OvershootineBlend(increase), OvershootingEdge(Decrease) Fixes overshooting problem bysmootcheening
- Simulation Delta Time (Decrease)
Fluid flux is updating with constant delay time. That means the time that elapsed between two frames of the game is divided by delta time and the result is the number of iterations. In general, more iterations mean less performance. By default, the Simulation Delta Time attribute is set to 0.2, it is not safe in terms of accuracy but can work with the highest performance.
- Debug Preview / Debug Hidden In-Game (Debug)
Pay attention to the ground debug preview. If you will spot some red spikes in places where the simulation does not work properly then probably the problem of your ground texture and geometry should be adjusted.
- Try to tweak other variables like Slope Clamp, Velocity Clamp, Friction, Damping, Gravity, and even World Pixel Scale can make a difference.
I am still experimenting with different solutions for this spikes problem and trying to figure out some method to force stability even in bad conditions. You can expect multiple improvements in future updates.
The PDA_FluxSimulationState is a special data asset created especially for storing the current frame of the simulation. The simulation state is the most important structure in the system.
Simulation states are dynamically updated by the simulation actor. A dynamic simulation state is automatically created in the constructor script and stored in BP_FluxSimulationDomain.CurrentState actor. Data can be easily previewed and used for rendering and further fluid analysis.
The simulation state can be exported to the data asset and used later in many ways.
- Can be loaded in runtime
- Can be used as a starting point for the simulation
- Can be rendered by the surface actor
- Can be used in other gameplay tools in Niagara emitters and materials
BP_FluxSimulationDomain.CurrentState can be baked to an asset by clicking the right button on BP_FluxSimulationDomain and choosing Scripted Actions -> Flux Export Simulation. The short tutorial below presents the process of generating and exporting the fluid state to a data asset:
- (0:07) Prepare data assets that will store the state
- (0:20) Start the simulation of fluid on your map and stop when it’s ready
- (0:50) Choose SimulationDomain->ContextMenu->ScriptedActions->FluxExportSimulation
- (0.54) Select the newly created state as a target and adjust settings.
After those actions, you should see the generated state and additional textures
Pay attention to simulation resolution! The “Power of Two” rule is a fundamental necessity due to the way game engines work. You will not be able to export simulation state if it is size is not power of two (128/256/512/1024 etc.)
Use case 1: Initial state
Using the state as the initial state of simulation allows to start the simulation from a specific frame. It means that a simulation of flowing water does not have to be generated every time the game starts it can start from the saved frame.
- Select SimulationDomain
- Find InisialState attribute
- Set the state exported before
Since now simulation will start by reading data from the state.
Use case 2: Loading state in gameplay
Sometimes there is a need to load state during the gameplay in blueprints like a checkpoint. Simulation->LoadInitialState function can be used to handle these tasks. Example use presented on the screenshot below:
Use case 3: Using state without simulation
If you are not planning to update the simulation dynamically then a better option is removing (or disabling) the SimulationDomain actor and using SimulationState directly in the Surface actor. It may be way faster, more reliable, and save some memory. Use this configuration:
- Configure SimulationDomain.
- Click the right mouse button on SimulationDomian and expert it to state
- Set SimulationDomain->AffectWorld = false
- Set Surface->SimulationState directly using the exported asset.
BP_FluxSimulationDomain.SurfaceActorReference is set then actors are communicating together and the state is automatically passed to BP_FluxSurface.SimulationState but changing the AffectWorld=false automatically disabling this process.
SimulationDomain can be removed or set IsEditorOnlyActor to avoid spanning it in the final build and wasting memory.
The Fluid Flux uses a static ground map for simulating fluids on it but updating is also allowed from time to time. It’s not a very cheap operation so it should not be done every frame.
The BP_BreakableDam presented in the video can be destroyed when the player hits the trigger. It is a good example of updating the ground after the dynamic object. Take a look at the Break function which is the heart of the dam system.
It evaluates UpdatGroundMap on a simulation actor, which takes the position and the size of the object that will disappear to recreate the ground in this area. You can do the same operation when adding something on your level.
In the tutorial below, we will go through a useful workflow for generating static meshes based on a baked state of the simulation. With this method you can achieve the highest performance, unfortunately, the waterline effect will not correlate very well with static mesh geometry.
- Setting up LOD and padding
- Converting a generated mesh to a static mesh asset
- Preparing material for static meshes
- Using static mesh in Surface actor
Mesh generation tools can be found in the BP_FluxSurface – Procedural Mesh tab.
Switch GenerateProceduralMeshView = true to see a preview of the generated mesh. After choosing this option surface automatically generates static mesh based on the Procedural Mesh tab configuration.
The last step is selecting SurfaceProceduralMesh Component and clicking “Create StaticMesh” which will export the mesh to the static mesh asset.
If SurfaceProceduralMesh is not visible on the list of BP_FluidSurface components then you have to deselect the surface and select it again. It’s working like that because the engine does not refresh the list of components after switching on/off generation mode.
Now you can find your static mesh in the content browser and preview it.
The river is simulated on the map and then converted to static mesh. The velocity flow map still works, mesh can be directly used by the surface actor.
If you create a static mesh and try to save it, you might get an error saying it can’t be saved. This happens because the static mesh is using a material instance created dynamically in the blueprint. To fix it, just clear the material slot in the static mesh asset and then save the mesh.
The material configuration “MI_River_SurfaceOverStatic” is designed for static meshes and can handle fluid data such as foam and velocity encoded in vertex color. By setting “MI_River_SurfaceOverStatic.UseSimulation = false“, the system will read the data from the vertex color instead of sampling render targets. This flag allows you to use the static mesh data as a source of water information.
BP_FluxSurface can render static meshes using SurfaceMeshMode=StaticMesh which means the mesh will not be transformed by simulation state scale and geometry will be taken from SurfaceOverMesh component configuration.
Sequencer gives users the ability to create in-game cinematics through its specialized multi-track editor. Unreal Engine has many options that can be used for previewing scenes, but some of them are not supported by Fluid Flux:
- Real-time – You can preview the simulation by hitting “play” (green button) in the editor. It will show you how it would behave in real-time.
- Editor – Clicking “Start Simulation” in BP_FluxSimulation actor on the scene (as presented in tutorials) allows you to generate some specific frame and sawing int to state (an initial state that can be pinned to the simulation actor as the first frame).
- Sequencer editor – Simulation can’t be previewed in the sequencer because the Fluid Flux system does not allow rewinding simulation in the current version and the sequencer affects actors – the topic is very complicated.
- Capture Movie – Sequencer Render Movie to Video. It works the same as in real-time mode and Fluid Flux water will render properly in the final video.
- Capture 360 – This option was never tested
If you want to preview the simulation with a sequencer then this setup may be useful for you:
- Drag and drop the sequencer on your map.
- Switch the AutoPlay option in LevelSequenceActor.
- Press “Play in selected viewport” or “Simulate”
Fluid Flux provides an option to use modifier activation/deactivation functions from a sequencer. The process of using this functionality is really simple:
- Add Sequencer on the level and set parameter: Autoplay=True
- Add Source modifier on the level and set parameters Duration=-1, AutoActivate=false
- Drag and drop the Source modifier to the sequencer.
- Add Track->FluxModifierSource
- Choose the moment of activation on the timeline and click “Add a new key” then change the properties of the event as presented on the screen below. You can choose the Activate/Deactivate function.
Now you can test the scene by rendering a video or playing the game. The modifier should activate automatically by sequencer event.
The BP_FluxCoastlineDomain is a dedicated system designed specifically for capturing and baking world data into CoastlineState. The architecture of the BP_FluxCoastlineDomain system is similar to the BP_FluxSimulationDomain, ensuring consistency and familiarity.
The coastline state serves as a fundamental data source during the rendering process for coastlines and oceans. The BP_FluxCoastlineDomain can communicate with the FluxSurface actor and feed it with data needed to render the water as presented in the short video tutorial below:
If after following the tutorial steps, the coastline does not appear, you have likely encountered one of the scenarios listed below:
- Z location of the Coastline actor is wrong:
Remember that after adding the BP_FluxCoastlineDomain actor on your map you need to modify the height (Z position) of the domain actor depending on your landscape. Otherwise, you may not be able to see coastline waves.
The debug grid on top of the landscape geometry is a good indicator that everything is working fine.
- Landscape material uses Pixel Depth Offset
If the “PixelDepthOffset” feature is used in the material then it may be not rendered to a ground map and cause some simulation problems. This problem can be easily fixed in your material by simple modification.
Use the MF_FluxPixelDepthOffset material node that will automatically disable “PixelDepthOffset” while caching the ground map.
The M_Photoscan_Master material is an example of a workaround for this problem with the use of the MF_FluxPixelDepthOffset node.
The BP_FluxCoastlineDomain actor generates a state that can be exported and saved as the data asset in the project files. It can be used as an initial state or directly in the BP_FluxSurfaceActor, just like the SimulationState. This simplifies the workflow and makes the system even more user-friendly.
Exporting the current coastline state can be described in a few simple steps:
- Create an empty coastline data asset for storing the data.
- Save to newly created data assets.
Exported CoastlineState data asset stores two textures.
- WorldGroundMap stores the height map of the coastline area.
- WorldCoastlineMap stores the distance to the coastline, direction, wave height, and blending of the coastline.
If you are not planning to update the coastline dynamically then maybe a better option would be removing (or disabling) the CoastlineDomain actor and using CoastlineState directly in the Surface actor. It may be way faster, more reliable, and save some memory.
Try this configuration:
- Configure CoastlineDomain and export it to the state.
- Set CoastlineDomain->AffectWorld = false
- Set CoastlineDomain->IsEditorOnlyActor = true
- Set Surface->CoastlinerState directly using the exported asset.
You don’t have to remove the domain actor from the scene because IsEditorOnlyActor will remove it automatically for you in final build. Thanks to this solution you are able to use it later again in the editor for regenerating the state if the level geometry change.
(More tutorials soon, thank you for your patience)
Preparing an ocean scene is an advanced topic because it requires multiple actors working together at the same time. It’s good to try all other tutorials before starting to work on recreating the ocean scene.
Examples of setup are presented in the demo maps FluxIslandMap and FluxBeachMap you can copy this setup (Surface, Simulation, WaveTexture, WaveModifier) or create it from scratch on your map. There is no video tutorial for ocean waves yet because I am planning a lot of improvements on this topic (infinity ocean surface already implemented) that will be published soon in version 1.2 of Fluid Flux. I have decided to make a tutoprial after the release.
Step by step
I’ve prepared a minimal MinimalOceanMap with all those parameters set according to this list and sending it to you in an attachment so you can check every actor and compare it with your config.
Start with an empty map with some island/landscape/ground mesh:
- Add BP_FluxSimulationDomain actor
- Add BP_FluxSurfaceOcean actor (make sure that you use Ocean actor)
- Add BP_FluxOceanWave actor
- Add BP_FluxModifierWaveActor actor
Configure Simulation BP_FluxSimulationDomain:
1. Pin SuraceActor to SiumationActor
SuraceActorReference = BP_
2. Adjust the transform of ModifierWave to cover the area of the simulation (change scale and position)
Configure Surface BP_FluxSurfaceOcean:
3. Set WaveTexture = BP_FluxOceanWave actor
4. Set WaveTextureStateAreaBlend = 4
5 Set SurfaceMeshTransform.Scale = (4,4,1)
6. Set SurfaceMeshMode = Plane_1024
Configure Distant meshes in BP_FluxSurfaceOcean:
7. Add SM_FluxPlane512x512 on level
8. Set SM_FluxPlane512x512 to BP_FluxSurfaceOcean.
– WaveTextureActor texture actor added in the previous step.
– WaveTextureStateAreaBlend the hardness of blending between simulation and ocean wave
– WaveTextureStateAreaBorder edges of simulation that will be blended with wave texture
– Scale/Move the component to cover the simulation area
– Set SurfaceHeight to generate water at a certain height
– Set StateAreaBorders to select which borders should generate fluid and affect the simulation
The BP_FluxOceanWave is a dedicated actor for simulating ocean waves. Implementation is much simpler than the classical analytical approaches like Gertner or FFT. The system uses multiple tillable textures and combines them into a height map that can be used in the post-process/surface/Niagara system to represent wave displacement.
The fluid surface uses data from BP_FluxOceanWave placed on the map pinned to the BP_FluxSurfaceActor variable. The blending between simulations of ocean waves can be configured in special cases like on the beach map.
The beach example contains ocean waves blended with fluid simulation. All materials configurated for use with oceans are declared in the Surface/Templates/Ocean/ folder. Surface material uses the UseFluxOcean=true flag to activate ocean wave blending.
- Ocean waves in the simulation are generated using the modifier BP_FluxModifierWaveActor which adds fluid and velocity at the borders of the simulation area.
- Additional waves in the background with simplified material (SurfaceDistantMaterial) are attached to the surface in the “DistantMeshes“.
- You can use RenderDebugPreview to see the analytical waves preview. This actor will not be visible it’s only there to generate the texture of ocean waves that the surface will use.
- Change Z location to adjust the height of the ocean wave.