About / Context:
This is an effects shot I created for my dynamics 3 class at Gnomon taught David Stripinis. There were a few requirements for this project:
-
Use Houdini's Pyro tools to make fire
-
Use Houdini's FLIP tools to make water
I had an Idea of the shot I wanted to do and made a few more requirements for myself.
-
Use as few simulations as possible
-
Do as little comp work as possible, ideally the rendered image is good enough to go on screen.
Movement:
I started with locking down my camera and then getting the lantern movement how I wanted. The lantern movement is entirely noise based which allowed for very quick iterations. Below is a walk through of that setup:
I isolated the curves my ropes were created from and just noised them up a bit in VOPs. Nothing special just a low frequency turbulent noise.
I wanted to isolate just the bottom of the curve so I got the Tangentv with the polyframe SOP and just culled them by the dot product with an up vector.
I also culled every nth point. These will be the points I will copy the lanterns to.
I deleted the first and last points on the line as they were the anchor points to the ship. I then ran another turbulent noise over the points and saved the output as a windForce attribute.
Since Normals decide the direction of the lanterns, I took care in my approach. The vex code below picks a random vector (either positive Z or negative Z). And then rotates it around an up axis a random amount between -30 and 30 degrees. It then rotates a downward facing normal around that derived axis using the windForce attribute as an amplitude.
Here's what that looks like:
This is good to get my lanterns swinging but there's no rotation information in there. That's easily solved! I just use the windForce attribute to spin the lanterns about their new Normals.
All that work leads up to this!
Simulations:
I wanted to use as few simulations as possible but for the fire there wasn't really any way around it. I knew that I didn't want to sim a unique fireball in each of these lanterns so I broke the problem down.
The lanterns in the direct foreground needed to be unique but I could sim them each at different resolutions. For the rest of the lanterns I sim'd three low res variations. I placed a point in the center of each lantern before I copied them to points. To create my variants I would take a random point and apply its velocity information to a fire emitter in a still lantern. This allowed me to then instance the fire using the same movement attributes as described above and have three unique simulations that got their information from actual movement. And these simulations could be applied to any lantern regardless of its movement. here's what my emitter with the applied velocity looked like.
I Sim'd three of these and then instanced them back into lanterns in Solaris. Without this technique this project would have not been possible.
I also ran a quick particle simulation to act as rain. I culled the particles by the camera frustum to make rendering a little lighter. I originally was going to use particle collisions with the lanterns to source my FLIP but that was terrible to art direct. I ended up just making my lanterns "sweat" and just occasionally scattering a sphere of FLIP to the surface with some downward velocity. Using FLIP on this small scale was not an enjoyable experience.
Lighting:
I used an HDRI as a base and was hoping that having my volumes act as light sources would be enough. That ended up looking like this. I also clearly didn't have my fireball instancing figured out yet...
I knew I needed a little more so I had the idea of having Rect lights act as "Light Panels" on the outside of each pane of glass. This led me to the second setup in this project that I'm proud of.
Building the light panels was a little difficult. But I had the idea of using the dimensions and orientations of the glass planes and copying lights to those in Solaris. So first I needed to derive all that information from my lanterns. I came up with this setup:
This setup iterates over one point on each face and since I know they are perfect rectangles, it builds basis vectors from the Normal and the point positions of neighboring points. It then converts that into a quaternion and saves that to a point at the center of each face. It also saves the dimensions of the plane to scale the light.
That yields these points.
I didn't just want all of my lanterns to be spitting out the same amount of light so I made a setup to make my light panels react to the fireball inside of them. I don't have the caches anymore, but I converted my fireballs into point clouds with their attributes intact. Then I had each "Light Panel Point" open a point cloud to its fireball and sample those attributes with pcfilter(). I then mapped those values to intensity and color and learned a cool Solaris thing: When you copy to points a USD prim in Solaris any attributes on the source points can be used to set the USD primvars on that prim. That made it super easy to set the intensity and color. With that setup my shot now looked like this:
A lot better to be sure but I didn't like how flickery the lights were. I used CHOPs to filter the colors and intensities over time and that gave me a result that I was really happy with. The final steps were to just add some fog and overlay my rain and that was it.
Again this was another project that I couldn't have completed without my Envy system. Karma CPU is not a fast renderer and this shot has pretty much everything renderers hate: Strong depth of field, Motion blur, Refractive things, Volumetric things, and emissive things inside of volumetric things inside of refractive things. I am happy with the result though, but if I were to do it again I would take time into making things look more wet.