Quoting wikipedia: "diffusion is the net movement of anything, driven by a gradient in concentration". Most typical example is heat diffusion: Imagine a swimming pool filled with cold water. There's a nearby building projecting shadow over it, so that sun only reaches half of the pool. Intuition tells us that there won't be an instant transition between scalding hot and freezing cold water in the middle of the pool. Instead heat will gradually travel (diffuse) trough water and after enough time, the entire pool will be warm.
Diffusion is also the reason why frying pans and pots have protective handles: even though only their bottom is in contact with a heat source, heat diffuses and their entire surface becomes too hot to touch after a while.
In Obi Fluid each particle has 4 floating point values that you can assign any value to, and that diffusion will be applied to during simulation. These values don't have any pre-defined meaning, you can interpret this data as colors, temperature, or any other property. The 4 diffusion channels are exposed as User Data in the blueprint (see fluid blueprints) and as the solver.userData array in the C# particle API.
During simulation, particles closer than the fluid's smoothing radius will average their 4 diffusion values at a rate defined by the blueprint's diffusion property, modulated by the ObiSolver's diffusionMask property.
Let's say you want fluids of different colors to mix together. One possible approach is to use only one diffusion channel, and interpolate between two colors using the value of this channel. This will only let us mix two colors, but allows us to perform this mixing / interpolation in fancy ways (e.g. using gradients). This is the approach used by the included "FluidMixing" sample scene.
A more general method is to use 3 of the 4 diffusion channels to store color data (red, green and blue, the 4th channel will always be 1) and let diffusion average them. This will let us mix any number of differently colored fluids, in this case we will go with just 2 but this method generalizes to 3, 4, or more.
Let's create 2 fluid blueprints, and initalize their diffusion data to red (1,0,0,1) and yellow (1,1,0,1). Also, we'll set the diffusion rate to a small value, like 0.05. When mixing them, we will get the average of both colors: orange (1,0.5,0,1).
Now we need to map the diffusion data in the solver.userData array to particle color. We can do this in LateUpdate(), right before rendering the fluid:
void LateUpdate() { for (int i = 0; i < solver.userData.count; ++i) solver.colors[i] = solver.userData[i]; }
You can write a component specifically for this, or add this to an existing component you're using. Note all you need is a reference to a ObiSolver.
Once this is done, we place a couple emitters in our scene and assign the red blueprint and the yellow blueprint to them. This is the result:
You can see how color mixes where both fluids meet, giving rise to a nice color gradient. Stirring the fluid would yield a more uniform mix, as more particles come into close proximity of each other.
For more advanced code examples using diffusion, see the scripting diffusion section.