Rippulu
By Homam Bahnassi
This tutorial is divided into the following sections:
Skill Requirements
Good knowledge in using XSI particles, Render Tree and Render Passes.
Introduction
Ah winter... It's cold, rainy and windy out there. Many of us love this dark season, but not when
it comes to simulating it in a 3D scene!
It's a bad dream if we just imagine all the rain and floods that should be there,
and it's a nightmare is we're to do it in 3D using standard tools.
Of course, if you have a very experienced R&D team in your company, you might be pretty safe.
But for those of us who aren't so lucky, our best bet would be to find hacky ways to fake the same
effects you need to achieve without needing that much of in-depth research.
Throughout this tutorial, we'll examine one method to mimic rain drops falling on water surface
without using complex simulation calculations for deforming the water surface.
The result is pretty good, but of course not as perfect as a CFD simulation can be.
In many times I prefer faked methods over simulations because they usually needs less
hardware capabilities and so they are easier to fine tune.
So let's prepare our umbrellas for a rainy day.
Building The Water Surface
We'll start this tutorial from scratch since it doesn't contain any special models or something.
You can also load the companion scene
and see the final results if you just want to follow the tutorial steps without doing it on your own.
Let's start by building the water surface, get a polygonal mesh grid and size it to some reasonable value
(try 40x40). Don’t care about the subdivisions because we won't alter the grid's mesh.
Give the grid a meaningful name (something like "WaterSurtace").
Add a new material to this grid and an XZ Texture Support.
In the RenderTree build your favorite water surface, or use the following shader preset
that I used in the companion scene.
Our next step is to setup the rain particle cloud.
Creating the Rain Cloud
Create particles from grid and place the emitter grid above the water surface, and rotate it
so the particles get emitted towards the ground. The following values were used in the companion scene:
RotX = 170
PosY = 25
Modify the emitter's size to 10x10. This will be the rain particle emitter.
In the explorer, expand the cloud node and rename both its particle type and emission properties
to meaningful names (use "PEmission_Rain" for the emission property and "PType_Rain" for the particle type).
This way you can edit your particles more easily even if they get crowded with other properties.
Edit the "PType_Rain" particle type parameters as shown:
Don't stick yourself to these settings. You can always try other combinations and still get interesting results.
Now modify the rain emission parameters as follows:
Adding Water Ripples
Here we come to the place where we add interesting behavior to our particles.
For every time a rain drop hits the water surface we'll emit a ripple sprite on top of the water surface.
To do this, add the "WaterSurface" as an obstacle from "Environment > Set Obstacle" in the
"Simulate" toolbar.
This command will create a new collision event for your particle cloud and opens the obstacle PPG.
Modify it as shown:
Expand the cloud node in the explorer and note the new properties that were
added under "RainPType" and "ParticlesOp".
As usual, give these new properties meaningful names as following: "PEvent_RainRipples" for the new
particle event and "Obstacle_WaterSurface" for the WaterSurface_Obstacles.
Open the event property and choose "Emit and Disappear" from the "Action List".
In the emission field, create a new emission property for this event.
Click the "Edit" button to open the new emission PPG.
Modify the following emission parameters as following:
From the emission PPG add a new particle type by clicking the ‘New’ button that's beside the ‘ParType’ list.
Click the edit button to open the new particle type PPG. Set the following values:
Here we need to add key frames for the size parameter to make the particles size grows.
Add the first keyframe at frame 1 with the size value 4, and another keyframe at frame 100 with size is 6.
Now we need to change the value type in the "General" tab to "age%" in order to make each emitted particle
to grow as it get older.
Now for the fading effect. This effect will make each water ripple fade gradually instead of just
disappearing suddenly. So we need to do something with the color properties like what we did with
the size parameter, but unfortunately because of some sort of a bug in the XSI particle system
you can’t animate more than one parameter using the “Age%” value type in the same particle cloud.
Don’t be worry about it because in XSI every thing has 101 ways to get it achieved, and we’re going
to do this fade effect using a RenderTree trick so let’s take a look.
Fixing the Ripples Particle Type Shader
In this section, we’ll use one great particles shader node to fix the particles fading problem
we talked about above. This is the "Particle_Scalar" node which returns a wide variety of
Particles Scalar information. So open a RenderTree window for the particles cloud and from
the ParTypes list select the "PType_Ripples".
Expand the "Particle Shape" node, you’ll get a huge list of ports.
Here, we need to drive the "Input" port (which controls the color and transparency of the particles).
Since we need only to modify the transparency of the particles, we need to control only the alpha channel.
This could be done by using an "RGBA_Combine" node where we can modify each color channel separately,
then combine them together as a color output that can be fed to the "Input" port in the "particle_shape" node.
Now we are ready to control the alpha channel of the particles. Grab a "Particle_Scalar" node and connect
it to the alpha port in the "RGBA_Combine" node. Open the "Particle_Scalar" node and select "Age"
from the output list. Make sure to check "Normalize" to get the age values fit in the range from 0 to 1.
Finally, modify its name to "Particle_Age" to be make it more informative in the render tree.
Now if you do a render test to the particles, you’ll notice that the particles are born gradually
and then die suddenly, this is because the "Particle_Age" node is returning values from 0 when the
particle born and fades gradually to 1 when the particle dies.
This is the exact opposite of the effect we need.
So we need to invert the "Particle_Age" values using a "Scalar_Invert" node.
You can do now a render test to see how the particle ripples are born and then gradually fade until they die.
Growing Ripples
In real world, if you take a look at a water ripple, you’ll notice that as it grows, new rings
are born from its center until it fades out. In our particle system, the rings only get bigger
without introducing new rings when it grows. This is another case for the "Particle_Scalar" node to fix.
Since the "Paricle_Scalar" node can return information about the particle radius, we can use this to control
the number of rings in the "Paricle_Shape" node so as the particle radius gets bigger, we increase the
number of rings.
In the "ripplesPType" rendertree grab a new "Particle_Scalar" and connect it to the "SineScale" port
in the "Particle_Shape" node. This is the port that controls the number of rings for each particle.
Open the new "Paricle_Scalar" and select "Radius" from the Output list. Rename it to "Particle_Radius".
This is not enough because the number of rings will be fairly low since the particles radius is generally small.
To fix this, we need a "Scalar_Math_Basic" node to multiply the values we get from the "Particle_Radius"
node with the average rings count. So grab a "Scalar_Math_Basic" node, and insert it
after the "Particle_Radius" node. Open it and change as shown:
Do a render test to view the final result for the particles ripples pass.
We’ll see later how we’ll render this particle type in a separate pass and use in the final renders.
Next we need to do the water splashes to complete the particle work for this scene.
Adding Water Splashes
Now it's time for the water splashes. Actually, we can do these with a new particle
cloud or even build the effect in an entirely new scene since we’ll render the complete effect
with multiple passes. However, this is not advisable because we’ll lose our scene's management,
and may cause us much pain if we decided to modify some parameters in the base particles properties.
In XSI, we can render as many particle types separately from one particle cloud using the
render passes capabilities. So we’ll continue adding new particles types and emission
properties to the same particle cloud.
Select the particle cloud and add a new collision event with the same water surface.
Open the new Particle Event PPG, change the Action to "Emit & Disappear", then
create and edit a new Emission property as shown:
Notice that we set the "Azimuth" and "Declination" values to emit the new particles perpendicular
to the water surface. It's prefered that you set simple expressions to control these parameters
in relation with the Emitter orientation and obstacle’s elasticity.
Create a new particle type for this emission property and set its parameters as shown below:
We need to fade the particle splashes before they die, so open the render tree for
the "SplashesPType" and build the same tree we've built before for the "RipplesPType".
Oh, and one more thing... In order to improve the look of the particle splash,
we’ll add a "Scalar_Math_Exponent" to modify the values we get from the "Particle_Scalar".
In the "Scalar_Math_Exponent" PPG set the factor value to 0.5. This will cause the particles
to fade out in a square exponent way.
Do a render test for the new particles splashes to complete the particle work for this tutorial.
Next we’ll set the cameras and render passes for the scene to complete the effect.
Setting Render Passes
In this step we need to render-map the water ripples so we can use it lately as a bump
for the water surface. However, because the render-map property in XSI doesn’t render particles,
we need to do render this one manually using a separate pass.
Before we start creating the new passes, we need to set a camera for them.
Get an orthographic camera and position it exactly in the middle above of the water surface.
In its properties set the "Ortho Height" to 40 which is the dimension of the water surface
grid, and change "Pict. Ratio" to 1.0.
Create a new empty pass for the new camera and modify its rendering "Picture Ratio" and "Output Camera"
in the "Format" tab to match the setting in the camera properties.
For "Image Resolution", choose a resolution that suffices your final rendering resolution.
(a value between 512 and 1024 would be enough for most cases).
Create a new partition under the new pass and the old pass, then add the particle cloud to it.
Set render/view visibility to hide for the other partition.
Finally, we need to add overrides for each render pass, which enables us to mute specific particle event.
Add an override to each cloud partition in each pass. Before you start adding parameters to these overrides,
we need to create a Custom Parameters Set that contains the mute parameters for each particle events.
This is because if you try to add these parameters directly, they’ll conflict with each other because
they get the same parameter name under one cloud.
To fix this we use the Custom PSet trick with a simple expression linking between the mute parameter
under the cloud event and the mute parameter in the Custom PSet.
Now you can add those new parameters in the new Custom PSet to the partition overrides as shown:
To hide the rain particles, we'll add one last paremeter to the "RainDrops_Pass" only.
This is the "rainPType" alpha value.
Set the overrides valus for each pass so you get in the "RainDrops" pass only the water ripples sprites
and the inverse for the beauty pass.
Putting it All Together
What remains now is to render the first "RainDrops_Pass", and then add the rendered frames
as a bump map to the water surface.
Finally you can render the full frame effect using the other "beauty_pass".
To see also a final rendering preview of this effect, play the "RainDrops" video in the companion project.
Enjoy.