Monday, 25 May 2020

Rain VFX

One of the last things on my To-Do list was adding Rain VFX to the scene. It was something I had done before during my placement year, so I quickly created a Particle System for testing purposes.

I decided to only have a small area of rain right in front of the player, instead of trying to cover the entire playable area. That way I wouldn't have to worry about having to spawn loads of particles or worry about the particle system being culled.
When testing I found out, that the spawn location of the particles didn't updated quick enough, when the player was moving. This resulted in being able to walk "through" the rain, which of course broke the illusion of wide rain coverage.
To avoid that I probably could have increased the spawn area, but I wanted to see, if I could solve this problem without having to use a particle system at all. I ended up creating the falling rain drops purely in a shader.

I went into 3DS Max and created a stack of quads, each of which would be a rain drop. The problem I was facing now was, that I had to somehow be able to control them individually. I solved that by assigning them different grayscale vertex colors, which I could use as offset values. To do that I used the 'Data Channel' Modifier with the following settings.

Data Channel Modifier Settings

Vertex Color Values

I didn't collape that modifier before exporting the mesh and once I had brought it into Unreal I can access the stored vertex colors through the Vertex Color Node.

In Unreal I used the mesh as the preview mesh in the rain material, so I could immediately see how the shader affected the mesh. I had two main problems to solve. 1) XY Distribution and 2) Z - Position.
I started figuring out the XY distribution and got briefly distracted with making some random shapes, just using a bit of maths.

Just because I can

Only the first one was really relevant, as I wanted to distribute the cards in a circular area. To get the circle I used the sine and cosine of the vertex color values as X and Y Coordinates multiplied by a radius value. But to avoid them being sorted like in the picture above, I multiplied the vertex color values by a large number, which resulted in this.

Circular Distribution
Now I obviously wanted to also have the inside of the circle filled, so I needed another value for each of the cards to controll the offset from the center. Putting them through some other nodes, including the hash function I had previously used for the other rain shaders and multiplying the resulting values times the XY Offset I got the desired distribution.

Fixed Distribution
Before moving on to dealing with the movement of the drops I wanted to make sure that the cards are always facing in the direction of the Camera on the X and Y Axis, which I achieved with the following setup.

Billboarding
I'll try and explains the maths behind it, as far as I have understood it.
The first step is calculating the normalized vector between Camera Position and Object Position. In my case I need to add the offset of the individual cards, to get a vector for each of them. I then somehow need to get an angle, by which they need to be rotated to face the camera.
When taking the Y and X position of a vector and putting that through the atan2 function, it returns the angle between the vector and the +X axis (1, 0). This angle α is in the range -π < α π, so it has to be divided by 2π to bring it to the range 0 < α < 1, which is the required input for the RotateAboutAxis Node.
When using the angle right now, the cards rotate in a way that the faces are aligned along the Camera Position - Object Position Vector, since the original orientation of the faces is along the +Y-Axis. It looks like this:

Wrong rotation
Fortunately this can be easily fixed, by adding 90° to the input angle, so 0.25 in Unreal's units. After doing that, the cards are facing in the right direction.
If the initial orientation of the cards is along the +X-Axis, adding 0.25 isn't necessary.
The other inputs for the RotateAboutAxis node are (0,0,1) for the NormalizedRotationAxis, since we want the cards to only rotate aroung the Z-Axis, Object Position for Pivot Point and AbsoluteWorldPosition for Position. The output of this gets added to the offset calculated before and connected to the World Position Offset Node.
I made a sketch, showing all that (face orientation being +X). I hope it makes things a bit more clear.


And here is a comparison of the material without and with the camera- facing rotation.


Funnily enough that math, using atan2, is very similar to how I calculated the rotation of the modular kit pieces in the Building Generator to align with the splines.

Next I moved on to sorting the falling movement. This was pretty straight forward. I know, that I want the cards to move from a higher to a lower position on the Z-Axis. Once they have reached the lowest defined position they should immediately go back to the highest position, looping infinitely.
I want the pivot point to be directly in front of the camera, so the rain need to move both above and below the pivot point.
I use time put through a frac node to interpolate between those two positions. Additionally I use the vertex color again to add offset to the time, so that the drops are all at different Z positions.


This is basically the interesting part done. I added some nodes to apply a drop texture and used a distorted cubemap our scene for the color input. The material is Translucent, Unlit and because of the implemented rotation Single Sided.

As mentioned before I added the Rain Card Mesh with this material applied to the First Person Character BP and attached it to the Camera, so that the pivot point is always in view and the rain doesn't get culled. Also an important note: The rotation of the rain mesh needs to be set to Absolute Rotation, so that it keeps the relative position to the camera, but the rotation stays at (0, 0, 0).

First Person BP Setup

To at least have touched Particle Systems once during this project I added some small splashes on the ground. The location update delay isn't as noticable as with the falling rain, so it works in this case.


 Last but not least rain isn't much of rain without a bit of sound. I went online and looked for some free sound samples and ended up using this one: https://freesound.org/people/vdr3/sounds/393703/
I added an Audio Component to the FirstPerson BP and this is how everything looks in the level. Unfortunately I wasn't able to get a good video, because my PC has lots of trouble recording and playing the level at the same time.

No comments:

Post a Comment