Ink in Water

One way to achieve this effect is using a looot of particles advected by a velocity field generated by some gas simulation. Why not use the gas sim itself ? Cause in order to achieve the same detail offered by particles, the resolution of the gas grid should be so high that even Hal 9000 wouldn't be able to handle it or Sky-net would suddenly become self-unaware.

So I generated a simple smoke sim using H13 Smoke Solver. I didn't use Pyro cause it was probably overkill for such a simple sim. Then I wedged and cached to disk 10 versions of the smoke sim varying parameters like the turbulence amplitude and twirl radius (finding out what parameters to wedge is an art on its own).

Once I had 10 different smoke sims, I had 10 different velocity field sequences that I can use to advect my points.
Now, two ways to advect points in Houdini are:

  • create a POP system in a DOP Network and use the POP Advect by Volumes DOP node making sure to point it to the velocity fields cached on disk and re-imported somewhere else at the SOP level.
    PROs: POP land provides a large range of nodes to control particle motion.
    CONs: Slow
  • convert the velocity to VDB, merge the fields into one single VDB vector field (with VDB Vector Merge - don't worry if Houdini complains cause the grid components are different), then use VDB Advect Points in a SOP Solver to advect your points.
    PROs: Very fast.
    CONs: you've to do everything yourself.
    • PRO of this CONS: you CAN do whatever you want  :) !

When I mentioned thet the POP is slow, I still mean that it can process several hundreds of thousands of particles per second. The VDB solution can handle millions of points per second. Because of this, you can avoid rendering different versions of the particle sim and compositing them in order to smooth out the "particular" look (which is the main challenge of ink in the water effect).

So I decided to adopt the VDB solution.

In order to add extra points in the areas where the particles were more sparse, I added an Attribute Wrangle node in the end of the chain and I called it Fill Gaps. Since Attribute Wrangle works in the CVEX context, I am given the opportunity to add (or destroy) geometry.
The purpose of the script is basically adding points where there aren't.

This is the content of the script (make sure to create the proper UI parameters before sourcing the script) and feed the same point geometry both in input 1 and 2 of the Attrib Wrangle node.

Note: this fill gap algorithm is FAR from being perfect. Plus it just really fills the spaces between points larger than "mindist" within "seachrad". So the results might not be as expected. The good thing is that the added points remain surprisingly consistent during the animation, so , at least, you don't see crazy artifacts or points popping in suddenly, in the render.

float searchrad=ch("searchrad");
float mindist=ch("mindist");
int maxpoints=ch("maxpoints");
int fillpoints=ch("fillpts");

vector clpos;
int handle=pcopen(@OpInput2,"P",@P,searchrad,maxpoints+1);
int i=0;
while(pciterate(handle))
{
    if (i==0) // the first point found should be the closest, in this case, itself. We want to skip it.
    {
        i++;
        continue;
    }
    pcimport(handle,"P",clpos);
    if (length(@P-clpos)>mindist)
    {
        vector pointstep=(clpos-@P)/(fillpoints*2+1); // this ensures there are no duplicate point
                                                                                  // at the cost of doubling the fill points number
        for (int t=0;t<fillpoints;t++)
            addpoint(geoself(),@P+(pointstep*float(t+1)));
    }
}

After rendering 10 exr sequences, I imported them in Nuke and used them as sprites on a particle distribution scattered over a large plane, and rendered with DOF. Kinda slow actually, and the DOF in comp is always a PITA (has this improved in the last 15 years ? nope!).

This is the result.
Oh, there is a card disappearing in the last 10 frames, probably one of the Nuke particles ran out of fuel.



Ink in Water - test from Alessandro Pepe on Vimeo.

Thank you for reading !

5 comments:

  1. Hi Alessandro!

    Thanks for this post!

    I'm trying to do a similar effect however I'm unable to import my vel field from my cached pyro sim. Is it possible to use the DOP import Fields on a cached sim?

    I also tried using the Advect Particles from Volume DOP which did get a result but the particles were not following my pyro sim but rather moving in their own strange direction. Do you know what could cause this?

    Thanks for your blog!
    Nick

    ReplyDelete
    Replies
    1. Hi Nick,
      make sure you're caching on disk the vel field , in your Dop Import Field, before the cache.
      If you want to re-import the cache just use a file sop.

      For what concerns your particle moving in their own strange direction after you advect them with volumes it's hard to tell without. Anyway check the parameter "Advection Type" in your POP Advect by Volumes node. Changing that parameter will cause a very different particle motion.

      Delete
  2. Hi fxthinking,
    I am trying to do the same fx. It is surprising in 2021 there is still not much detailed info on how to achieve this fx. May I have a look of your hip file? Google wont grant me access to it :(. thanks!

    ReplyDelete
    Replies
    1. Of course, I granted permission to the file. This is an old setup (2014) so it might not work if you're using a late Houdini build. Let me know how it goes.

      Delete

Featured Post

Cigarette Smoke - Part 3 - Houdini 19

Since a lot of people are asking me about this setup I thought it would be a good idea to update the setup for H19. The logic is pretty much...

Most Popular