Tornado Project
Recreating Giants Deep
This project was a bit of a love letter to one of my favorite games, Outer Wilds. One of the moments that stuck with me was landing on Giant’s Deep—an ocean planet covered in violent storms and towering tornadoes.
I became fascinated with how these tornadoes were created and set out to recreate them. Using the developer insights available for the game as a starting point, I broke down the effect and built my own procedural solution in Unreal Engine.
I deliberately went beyond recreating the tornadoes themselves, building the entire effect on a spherical ocean world, complete with a custom ocean shader and sky dome. This introduced a number of additional technical challenges, but resulted in a much closer recreation of the original setting.
This project pushed me into more advanced Blueprint systems, procedural animation, and Control Rig. It was also where I first really fell in love with Control Rig—a tool that has since become a staple of my Technical Art workflow.
- Control Rig Displayed (Slide one)
- Tornado Randomness on Begin Play (Slide Two)
- Control Rig Node Network (Slide Three and Four)
Procedural Tornado Rig
To create a large number of tornadoes with distinct silhouettes, I built a procedural spline rig in Control Rig.
The rig uses three main controllers to shape each tornado. The standard spline setup I started from only accounted for controller positions, so I extended it to also incorporate rotation and scale.
This allowed each tornado’s controllers to be procedurally randomized in position, scale, and movement, producing a wide range of S-curves, C-curves, tubes, and swinging motions from the same rig.
The result was a reusable procedural system where a relatively small number of parameters could generate a large amount of variation while keeping the overall shape and animation under control.
Spherical Surface Alignment
Because the tornadoes were placed on a spherical ocean, they needed to conform to the planet’s surface while remaining upright relative to the terrain.
I solved this using raycasts from the tornado’s control points to sample the ocean surface. The resulting distances were used to adjust the tornado’s position, while the surface normals provided the orientation needed to align each tornado to the curvature of the planet.
For the final presentation, I simplified the system to use the bottom surface trace while procedurally varying the tornado height. Rather than implementing an AI system to move them around the planet, I had the tornadoes orbit the planet’s center, giving the scene the desired motion while keeping the system manageable.
- The tornado Tracing the planet
- VertexColors + Secondary Elements = Tornado (Slide one)
- Tornado Main Texture/Normal (Slide Two)
- Splash/Swirls/Rain Textures (Slide Three)
Tornado Shading & Secondary Elements
The tornado mesh uses vertex displacement driven by scrolling textures and a custom Substance Designer normal map. To break up the repeating pattern, I used vertex colors to divide the tornado into randomized sections, with each color controlling the amount of displacement applied across XYZ.
Additional scrolling textures, Fresnel, and a color gradient add further movement and variation to the surface.
Early iterations felt too solid and lacked the sense of energy and interaction with the surrounding storm. Feedback from the VFX Apprentice community and my class led me to focus more on secondary motion and connecting the tornado to the ocean.
I added two mist particle systems following the top and bottom Control Rig controllers, along with additional wind meshes and planes attached to the same rig. Simple shader movement on these elements creates the impression of wind streaming around the tornado.
Finally, I layered a second version of the tornado mesh with different material parameters and partial opacity, adding another layer of depth and helping sell the overall energy of the effect.
Ocean Shader & Tornado Interaction
The ocean combines Gerstner waves with texture-driven detail to create layered waves at different scales. I built the Gerstner wave as a reusable material function, with smaller waves driven by texture channels that blend over time to add variation.
The main challenge was making the tornadoes feel physically connected to the ocean. I used Unreal Engine’s Distance Fields to detect a mesh positioned beneath each tornado and push the water vertices along their normals, creating the impression that the tornado is pulling the ocean upward.
These interaction meshes are tied to the tornadoes’ bottom Control Rig controllers, so the deformation follows their procedural movement. Combined with splash particles at the base, this helps sell the connection between the tornado and the water.
- Distance Field Showcase (Slide one)
- Gerstner Wave with texture function (Slide Two)
- Wave Textures Packed in RGBA (Slide Three)












