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 |
Fixed Distribution |
Billboarding |
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 |
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